> ## Documentation Index
> Fetch the complete documentation index at: https://highseat.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# OAuth

> Let people connect your app to Highseat by signing in: the endpoints, the authorization code flow with PKCE, tokens, and how a person ends a connection.

Use OAuth when your app acts for other people, such as a desktop extension, a browser add-on or a hosted integration. A person signs in, picks a workspace, the sites your app may reach and what it can do, and allows it. Your app never handles an API key.

For your own scripts, use an [API key](https://highseat.com/docs/api/authentication.md) instead.

## How it works

Highseat supports the authorization code flow with PKCE, using `S256`. Your app runs as a public client, so it holds no secret.

The authorization server publishes its endpoints at:

```text Discovery document theme={null}
https://app.highseat.com/.well-known/oauth-authorization-server/api/auth
```

| Step | Endpoint |
| - | - |
| Send the person to sign in | `https://app.highseat.com/api/auth/oauth2/authorize` |
| Exchange the code, refresh a token | `https://app.highseat.com/api/auth/oauth2/token` |
| End a token | `https://app.highseat.com/api/auth/oauth2/revoke` |
| Register a client | `https://app.highseat.com/api/auth/oauth2/register` |

## Identify your app

Pick one of these:

* **A Client ID Metadata Document.** Host a JSON document on your own domain and use its URL as your `client_id`. The document holds `client_id`, `client_name` and `redirect_uris`. The `client_id` must equal the document's URL, and the picker shows your domain to the person connecting.
* **Dynamic client registration.** Send your `client_name` and `redirect_uris` to the register endpoint, and use the `client_id` it answers with. A client nobody connects within a day is deleted.

The `redirect_uri` you send must match a registered one exactly, query string included.

## Ask for access

Send the person to the authorize endpoint:

```text Authorization request theme={null}
https://app.highseat.com/api/auth/oauth2/authorize
  ?response_type=code
  &client_id=YOUR_CLIENT_ID
  &redirect_uri=YOUR_REDIRECT_URI
  &scope=read%20offline_access
  &state=A_RANDOM_VALUE
  &code_challenge=YOUR_CODE_CHALLENGE
  &code_challenge_method=S256
```

* `read` is required. The person decides on the consent page whether your app reads or also makes changes, so there is no scope for writing.
* `offline_access` returns a refresh token, which keeps your app connected after the access token expires.
* `resource` is optional. It defaults to `https://api.highseat.com/v1`.

After the person allows it, your `redirect_uri` receives a `code`. Exchange the code at the token endpoint with `grant_type=authorization_code`, the `code`, the `redirect_uri`, your `client_id` and the `code_verifier`.

## Call the API

Send the access token as a bearer token, as you would an API key. It reaches the workspace and sites the person picked, and every route and [limit](https://highseat.com/docs/api/limits.md) applies as it does to a key. The budget is counted per connection.

```bash theme={null}
curl https://api.highseat.com/v1/credential \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```

[Describe the credential](https://highseat.com/docs/api/credential/describe-the-credential) answers with the workspace, the access and the sites the person picked, so your app can show what it is connected to.

In TypeScript, the `highseat` package has a typed client. Pass a function as `token` so each call uses the current access token:

```ts theme={null}
import { createApi } from "highseat/api"

const api = createApi({ token: getAccessToken })

const { data } = await api.get("/sites/{site}/realtime", {
  path: { site: "example.com" },
})
```

## Keep a connection alive

An access token lasts one hour. Send the refresh token to the token endpoint with `grant_type=refresh_token` and your `client_id` to get a new one. A refresh token lasts 30 days, and each refresh returns a new refresh token, so store it.

A call with a token that is no longer valid answers `401` with the code `UNAUTHORIZED`. Refresh the token, and if that fails, ask the person to connect again.

## End a connection

A person disconnects your app under **Connected apps** in **Workspace settings › API keys**. A connection also ends when the person leaves the workspace. If the person loses the role that allows changes, the connection goes back to reading.

To disconnect from your app, send the refresh token to the revoke endpoint.

## Get verified

A verified app shows a gold seal and its icon on the consent page. To list yours, contact [support](mailto:support@highseat.com).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.