API reference
Connections
Connections: per-user OAuth authorizations for end users (Gmail, Calendar, Slack) and your own OAuth apps.
Generate an authorization link for an end user
POST/v1/connections/authorize
Your backend calls this endpoint and sends the end user to the returned url (the provider's consent page). The link is valid for 10 minutes and can be used only once (only a hash of state is stored);
Google links use PKCE. connectors must all belong to the same provider: gmail and calendar belong to google, slack belongs to slack; duplicates are removed.
After the end user consents, the provider redirects to GET /v1/oauth/{provider}/callback; the control plane exchanges the code for tokens and then redirects to return_url. See that endpoint's description.
Each (developer, end user, provider) has at most one active connection at a time; authorizing again replaces the old one.
If you have not registered your own OAuth app (PUT /v1/oauth-clients/{provider}) and no platform test app is configured either, 409 no_oauth_client is returned.
Request body application/json · AuthorizeConnectionRequest
| Field | Type | Description |
|---|---|---|
end_user_idrequired | string | |
connectorsrequired | array of Connector | Connectors of a single provider; unknown connectors, or a mix of two providers, give 400. |
return_urlrequired | string (uri) | The page of yours to return to after authorization; must be an absolute http(s) URL. |
Responses
- 201Authorization link
ConnectionAuthorization - 400Invalid parameters: validation failed, the body is not valid JSON, or the query string could not be parsed (all returned in the same JSON shape).
- 401Missing, invalid or revoked key
- 409State conflict; `error` holds the specific code
- 415Missing `Content-Type: application/json` (`unsupported_media_type`)
- 422The JSON does not match the schema: a missing field, a wrong type or enum value, or an unknown field (`invalid_body`)
- 500Internal error (details are recorded only in server logs)
Provider OAuth callback (public)
GET/v1/oauth/{provider}/callback
Not for developers to call: this is the callback URL you register with Google / Slack (redirect_uri; see GET /v1/oauth-clients).
It is public, takes no API key, and accepts only a one-time state.
- Valid
state: thecodeis exchanged for tokens, the account details are fetched and everything is stored encrypted in the credential vault; the response is then a 302 redirect to thereturn_urlgiven when authorization started, with these appended after any existing query parameters: on successstatus=ok&connection_id=conn_...; on failure (the user declined at the provider, or the token exchange failed)status=error&error=<reason>. The response carriesCache-Control: no-store. On success aconnection.createdwebhook is sent. - Missing
state, orstateexpired or already used: there is nowhere to redirect, so a 400 HTML error page is returned (meant for the end user, not JSON). - Unknown
provider: 404.
Parameters
| Parameter | In | Type | Description |
|---|---|---|---|
state | query | string | |
code | query | string | |
error | query | string | Sent back by the provider when the user declines authorization there. |
Responses
- 302Redirect to your `return_url` with `status`, plus `connection_id` or `error`
- 400`state` missing, expired or already used (HTML error page)
- 404Does not exist, or does not belong to this developer (`no such resource`); for a nonexistent route `message` is `no such route`
- 500Internal error (details are recorded only in server logs)
List connections
GET/v1/connections
Newest first, at most 500, not paginated: when there are more, has_more is true; filter by end_user_id to see them. Revoked connections are excluded by default. Tokens are never included in the response.
Parameters
| Parameter | In | Type | Description |
|---|---|---|---|
end_user_id | query | string | Only list this end user's connections. |
include_revoked | query | boolean | Include revoked connections. |
Responses
- 200Connections
ConnectionList - 400Invalid parameters: validation failed, the body is not valid JSON, or the query string could not be parsed (all returned in the same JSON shape).
- 401Missing, invalid or revoked key
- 500Internal error (details are recorded only in server logs)
Get a connection
GET/v1/connections/{id}
Responses
- 200Connection
Connection - 401Missing, invalid or revoked key
- 404Does not exist, or does not belong to this developer (`no such resource`); for a nonexistent route `message` is `no such route`
- 500Internal error (details are recorded only in server logs)
Revoke a connection
DELETE/v1/connections/{id}
Makes a best effort to revoke the tokens at the provider too (a failure there does not block the local revocation); locally the encrypted tokens are erased, the placeholder tokens issued to environments are invalidated, the status becomes revoked,
and a connection.revoked webhook is sent. Returns the revoked connection (200, not 204). Revoking an already revoked connection returns it unchanged.
Responses
- 200Connection
Connection - 401Missing, invalid or revoked key
- 404Does not exist, or does not belong to this developer (`no such resource`); for a nonexistent route `message` is `no such route`
- 500Internal error (details are recorded only in server logs)
List registered OAuth apps
GET/v1/oauth-clients
One entry per provider (google, slack): the client_id you registered (null if none; the secret is never returned), whether the platform test app is available,
and the callback URL redirect_uri (which you must register with the provider).
Responses
- 200One entry per provider
OAuthClientList - 401Missing, invalid or revoked key
- 500Internal error (details are recorded only in server logs)
Register your own OAuth app (your branding)
PUT/v1/oauth-clients/{provider}
Once registered, the consent page shows your app's name; otherwise the platform's test app is used (only test users can authorize it). The client secret is stored encrypted and never returned afterwards.
A second PUT replaces it. An empty client_id or client_secret gives 400; an unknown provider gives 404.
Request body application/json · SetOAuthClientRequest
| Field | Type | Description |
|---|---|---|
client_idrequired | string | |
client_secretrequired | string |
Responses
- 200Registered
OAuthClientRegistered - 400Invalid parameters: validation failed, the body is not valid JSON, or the query string could not be parsed (all returned in the same JSON shape).
- 401Missing, invalid or revoked key
- 404Does not exist, or does not belong to this developer (`no such resource`); for a nonexistent route `message` is `no such route`
- 415Missing `Content-Type: application/json` (`unsupported_media_type`)
- 422The JSON does not match the schema: a missing field, a wrong type or enum value, or an unknown field (`invalid_body`)
- 500Internal error (details are recorded only in server logs)