# Connections API reference

> Canonical HTML: https://screenrig.ai/docs/api/connections
> Source SHA-256: e0c997a2ab813502f0d99a41d2ed1d3d6b26dbaf1a3d7e514c1cce0278ff8422

Connections: a project's reusable access to Microsoft and Google. This group has 9 operations, each with its authentication, parameters, request body fields, request template and responses. The [API overview](https://screenrig.ai/docs/api.md) covers services, authentication, requests and retries, problem codes and versioning.

Replace uppercase placeholders. Save a schema-valid JSON body in request.json when required. Cookie examples use a local cookie jar from an authenticated session.

## Connections: a project's reusable access to Microsoft and Google

### GET /api/connections

**List Connections**

Lists the project's connections, newest first, at most 200 a page; pass next_cursor back as after for the next.

A connection is the project's reusable access to Microsoft or Google for sources that run unattended: a microsoft365 or google_calendar data source, a Power BI connection and a SharePoint media sync account name one in config.connection_id instead of carrying credentials of their own (docs/connections.md).

A secret, a key or a refresh token is never returned: secret shows whether one is held and a hint that is not secret. A read never carries a consent link.


Operation: listConnections.

- Authentication: projectBearer OR dashboardSession
- Request body: none

#### Parameters

| Name | Send in | Required? | Description |
| --- | --- | --- | --- |
| ScreenRig-Project | header | optional | Deprecated for one release. Must be consistent with the JWT projects grants; adds Deprecation and Warning headers. No token exchange. |
| after | query | optional | next_cursor of the previous page of the same list, with the same filters. Omitted starts at the newest row. A value that is not such a cursor is invalid_request. |

#### Request template

~~~sh
curl --request GET --header 'Authorization: Bearer [SCREENRIG_TOKEN]' --cookie cookies.txt --cookie-jar cookies.txt 'https://screenrig.ai/api/connections'
~~~

#### Responses

| Status | Meaning | Body and headers |
| --- | --- | --- |
| 200 | One page of connections. | ConnectionList (application/json); headers: Cache-Control |
| 400 | invalid_request, including a malformed cursor. | Problem (application/problem+json) |
| default | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |

### POST /api/connections

**Create Connection**

Creates a connection to Microsoft (provider microsoft) or Google (provider google). mode own_app is the customer's own application: for Microsoft, config.tenant_id (the directory id or primary domain; common, organizations and consumers are refused), config.client_id and secret (the value of one of the app's client secrets); for Google, secret is the service account's JSON key file.

The secret is sealed and never returned. mode screenrig_app uses screenRIG's own application and takes no config and no secret: the connection is created pending_consent and the answer carries consent_url, a one-time link (valid until consent_expires_at) for the person who completes it.

For Microsoft that is a Microsoft 365 administrator, who consents to screenRIG's application for the tenant; the browser then signs in to the tenant Microsoft names, so the connection records the tenant that was confirmed, never one a callback only claims.

For Google it is the account holder, who grants read-only access to the calendars the account can see; screenRIG keeps the refresh token sealed and the account's address. The link is a credential of one consent: send it to that person only.

A server without screenRIG's application for the provider answers 409 connection_app_not_configured, and own_app connections keep working. An organization has at most 50 connections across its projects (connection_limit_reached). Appends connection.created.

An exact retry with the same Idempotency-Key returns the same connection (a screenrig_app retry gets a new consent link, which replaces the first).


Operation: createConnection.

- Authentication: projectBearer OR dashboardSession
- Request body: ConnectionWrite

#### Parameters

| Name | Send in | Required? | Description |
| --- | --- | --- | --- |
| ScreenRig-Project | header | optional | Deprecated for one release. Must be consistent with the JWT projects grants; adds Deprecation and Warning headers. No token exchange. |
| Idempotency-Key | header | optional | Omit for a fresh operation. Supply and reuse a key to deduplicate retries; the CLI manages keys automatically. |

#### Request body fields

| Field | Required? | Type | Description |
| --- | --- | --- | --- |
| provider | required | string | Allowed: "microsoft", "google" |
| mode | required | string | Allowed: "own_app", "screenrig_app" |
| name | required | string | minLength: 1 maxLength: 80 |
| config | optional | ConnectionConfigWrite | Microsoft, mode own_app: both members. Not accepted for a Google connection or for mode screenrig_app. |
| secret | optional | string | Mode own_app. Microsoft: the value of one of the app's client secrets (not its id; at most 1024 characters), with config.tenant_id and config.client_id. Google: the service account's JSON key file, whole (at most 16384 bytes). Sealed on arrival and never returned; the CLI reads it from a file or stdin, never an argument. Not accepted in mode screenrig_app. minLength: 1 maxLength: 16384 |

#### Request template

~~~sh
curl --request POST --header 'Authorization: Bearer [SCREENRIG_TOKEN]' --cookie cookies.txt --cookie-jar cookies.txt --header 'Content-Type: application/json' --data '@request.json' 'https://screenrig.ai/api/connections'
~~~

#### Responses

| Status | Meaning | Body and headers |
| --- | --- | --- |
| 201 | Created. A connection in mode screenrig_app carries consent_url and consent_expires_at. | ConnectionConsent (application/json); headers: ETag, Location, Cache-Control |
| 400 | invalid_request, naming the field that is not valid. | Problem (application/problem+json) |
| 409 | connection_app_not_configured (this server has no screenRIG application for the provider), connection_limit_reached or idempotency_mismatch. | Problem (application/problem+json) |
| default | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |

### GET /api/connections/{id}

**Get Connection**

One connection, with its status, its last error and its last test.


Operation: getConnection.

- Authentication: projectBearer OR dashboardSession
- Request body: none

#### Parameters

| Name | Send in | Required? | Description |
| --- | --- | --- | --- |
| ScreenRig-Project | header | optional | Deprecated for one release. Must be consistent with the JWT projects grants; adds Deprecation and Warning headers. No token exchange. |
| id | path | required |  |

#### Request template

~~~sh
curl --request GET --header 'Authorization: Bearer [SCREENRIG_TOKEN]' --cookie cookies.txt --cookie-jar cookies.txt 'https://screenrig.ai/api/connections/RESOURCE_ID'
~~~

#### Responses

| Status | Meaning | Body and headers |
| --- | --- | --- |
| 200 | One connection. | Connection (application/json); headers: ETag, Cache-Control |
| 404 | not_found. | Problem (application/problem+json) |
| default | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |

### PATCH /api/connections/{id}

**Update Connection**

Changes a connection's name or, in mode own_app, its credentials: config.tenant_id and config.client_id (Microsoft) or secret (a sent secret replaces the sealed one; an omitted one is kept). A connection in mode screenrig_app can only be renamed: connect it again (POST /api/connections/{id}/connect) to change who consented.

A change to the credentials returns the connection to ready, clears last_error and last_test and retires every token minted for the old credentials. Appends connection.updated. If-Match guards the revision.


Operation: updateConnection.

- Authentication: projectBearer OR dashboardSession
- Request body: ConnectionPatch

#### Parameters

| Name | Send in | Required? | Description |
| --- | --- | --- | --- |
| ScreenRig-Project | header | optional | Deprecated for one release. Must be consistent with the JWT projects grants; adds Deprecation and Warning headers. No token exchange. |
| id | path | required |  |
| If-Match | header | optional | Optional positive resource revision. Omit to write the current resource; a supplied stale revision is revision_conflict. |
| Idempotency-Key | header | optional | Omit for a fresh operation. Supply and reuse a key to deduplicate retries; the CLI manages keys automatically. |

#### Request body fields

| Field | Required? | Type | Description |
| --- | --- | --- | --- |
| name | optional | string | minLength: 1 maxLength: 80 |
| config | optional | ConnectionConfigWrite | Microsoft, mode own_app: both members. Not accepted for a Google connection or for mode screenrig_app. |
| secret | optional | string | Replaces the stored secret or key; omit it to keep the stored one. Mode own_app only. minLength: 1 maxLength: 16384 |

#### Request template

~~~sh
curl --request PATCH --header 'Authorization: Bearer [SCREENRIG_TOKEN]' --cookie cookies.txt --cookie-jar cookies.txt --header 'Content-Type: application/json' --data '@request.json' 'https://screenrig.ai/api/connections/RESOURCE_ID'
~~~

#### Responses

| Status | Meaning | Body and headers |
| --- | --- | --- |
| 200 | The updated connection. | Connection (application/json); headers: ETag, Cache-Control |
| 400 | invalid_request, naming the field that is not valid; config and secret do not apply to a connection in mode screenrig_app. | Problem (application/problem+json) |
| 404 | not_found. | Problem (application/problem+json) |
| 412 | revision_conflict. | Problem (application/problem+json) |
| default | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |

### DELETE /api/connections/{id}

**Delete Connection**

Deletes a connection that nothing reads through. While a data source, a Power BI connection or a media sync account does, the answer is resource_conflict naming them (used_by lists their type and id).

Deleting does not end the vendor's side: a Microsoft 365 tenant keeps screenRIG's application until its administrator removes it, and a Google account keeps its grant until its holder revokes it. Appends connection.deleted. If-Match guards the revision.


Operation: deleteConnection.

- Authentication: projectBearer OR dashboardSession
- Request body: none

#### Parameters

| Name | Send in | Required? | Description |
| --- | --- | --- | --- |
| ScreenRig-Project | header | optional | Deprecated for one release. Must be consistent with the JWT projects grants; adds Deprecation and Warning headers. No token exchange. |
| id | path | required |  |
| If-Match | header | optional | Optional positive resource revision. Omit to write the current resource; a supplied stale revision is revision_conflict. |
| Idempotency-Key | header | optional | Omit for a fresh operation. Supply and reuse a key to deduplicate retries; the CLI manages keys automatically. |

#### Request template

~~~sh
curl --request DELETE --header 'Authorization: Bearer [SCREENRIG_TOKEN]' --cookie cookies.txt --cookie-jar cookies.txt 'https://screenrig.ai/api/connections/RESOURCE_ID'
~~~

#### Responses

| Status | Meaning | Body and headers |
| --- | --- | --- |
| 204 | Deleted. | no body |
| 404 | not_found. | Problem (application/problem+json) |
| 409 | resource_conflict, something still reads through the connection. | Problem (application/problem+json) |
| 412 | revision_conflict. | Problem (application/problem+json) |
| default | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |

### POST /api/connections/{id}/test

**Test Connection**

Signs in with the connection and stores the answer as last_test.

For Microsoft the checks are credentials (Microsoft issued an app token for the tenant) and permissions (which of Calendars.Read, Sites.Selected, Files.Read.All, Sites.Read.All and Place.Read.All the app's token carries; an app that holds none fails the check, and Sites.Selected alone is a warning because each SharePoint site needs a grant).

For Google the check is credentials: Google accepted the service account or the granting account's refresh token, and the answer names the account the calendars must be visible to. A refusal is a failed check and moves the connection to error with last_error; a success returns it to ready.

It does not judge a calendar's sharing, a mailbox access policy or a site grant, which a source or sync proves when it runs. At most 30 a minute per organization.


Operation: testConnection.

- Authentication: projectBearer OR dashboardSession
- Request body: none

#### Parameters

| Name | Send in | Required? | Description |
| --- | --- | --- | --- |
| ScreenRig-Project | header | optional | Deprecated for one release. Must be consistent with the JWT projects grants; adds Deprecation and Warning headers. No token exchange. |
| id | path | required |  |
| Idempotency-Key | header | optional | Omit for a fresh operation. Supply and reuse a key to deduplicate retries; the CLI manages keys automatically. |

#### Request template

~~~sh
curl --request POST --header 'Authorization: Bearer [SCREENRIG_TOKEN]' --cookie cookies.txt --cookie-jar cookies.txt 'https://screenrig.ai/api/connections/RESOURCE_ID/test'
~~~

#### Responses

| Status | Meaning | Body and headers |
| --- | --- | --- |
| 200 | The checks. | ConnectionTest (application/json); headers: Cache-Control |
| 404 | not_found. | Problem (application/problem+json) |
| default | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |

### POST /api/connections/{id}/connect

**Connect Connection**

Makes a new one-time consent link (consent_url, valid until consent_expires_at) for a connection in mode screenrig_app, to send to the person who completes it: the Microsoft 365 administrator, or the Google account holder. It replaces any earlier link.

A connection that works stays as it is until the new consent completes, so this also renews one that moved to error (consent removed, access revoked) or moves it to another tenant or account. The link is a credential of the consent: send it to that person only.

When the person finishes, the browser returns to GET /oauth/connections/{provider}/callback and is sent on to the connection's page in the dashboard, which reads status and last_error. A connection in mode own_app has no consent step (409 resource_conflict); a server without screenRIG's application for the provider answers 409 connection_app_not_configured.


Operation: connectConnection.

- Authentication: projectBearer OR dashboardSession
- Request body: none

#### Parameters

| Name | Send in | Required? | Description |
| --- | --- | --- | --- |
| ScreenRig-Project | header | optional | Deprecated for one release. Must be consistent with the JWT projects grants; adds Deprecation and Warning headers. No token exchange. |
| id | path | required |  |
| Idempotency-Key | header | optional | Omit for a fresh operation. Supply and reuse a key to deduplicate retries; the CLI manages keys automatically. |

#### Request template

~~~sh
curl --request POST --header 'Authorization: Bearer [SCREENRIG_TOKEN]' --cookie cookies.txt --cookie-jar cookies.txt 'https://screenrig.ai/api/connections/RESOURCE_ID/connect'
~~~

#### Responses

| Status | Meaning | Body and headers |
| --- | --- | --- |
| 200 | The connection with a new consent_url. | ConnectionConsent (application/json); headers: ETag, Cache-Control |
| 404 | not_found. | Problem (application/problem+json) |
| 409 | resource_conflict (the connection is in mode own_app) or connection_app_not_configured. | Problem (application/problem+json) |
| default | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |

### GET /oauth/connections/microsoft/callback

**Complete Microsoft Connection Consent**

Where Microsoft sends the browser of a Microsoft 365 administrator after the admin consent page (and again after the sign-in step that follows it) for a connection in mode screenrig_app.

It carries no credential: the signed state in the query is the only authority, is verified before anything it names is read, and is honored only while it is the connection's pending consent.

The first return names a tenant, which is not authenticated: the answer is a redirect to that tenant's sign-in, whose code is redeemed with the application's secret and a PKCE verifier only this server can derive, and the tenant the ID token carries is the one the connection records after a client-credentials token proves the application holds its permissions there.

Every outcome after a verified state redirects to the connection's page in the dashboard (/dashboard/connections/{id}?consent=connected or ?consent=failed), which reads status and last_error; the error text is built from fixed sentences and Microsoft's own error answer (its AADSTS code), never from what the callback's query carried.

A state that is unknown, expired, used, replaced or for a deleted connection renders a page that names nothing. Answers only on the API host the callbacks are registered under.


Operation: completeMicrosoftConnectionConsent.

- Authentication: none
- Request body: none

#### Parameters

| Name | Send in | Required? | Description |
| --- | --- | --- | --- |
| state | query | optional |  |
| admin_consent | query | optional |  |
| tenant | query | optional |  |
| code | query | optional |  |
| error | query | optional |  |
| error_description | query | optional |  |

#### Request template

~~~sh
curl --request GET 'https://api.screenrig.ai/oauth/connections/microsoft/callback'
~~~

#### Responses

| Status | Meaning | Body and headers |
| --- | --- | --- |
| 302 | To Microsoft's sign-in for the tenant that consented, or to the connection's page in the dashboard. | no body |
| 200 | Where no dashboard is configured, a page that says the connection is complete. | string (text/html) |
| 400 | A page that says the link was already used or has expired, or where no dashboard is configured why nothing was connected. | string (text/html) |
| 429 | Too many callbacks from this address. | no body |

### GET /oauth/connections/google/callback

**Complete Google Connection Consent**

Where Google sends the browser of the account holder after the consent page for a connection in mode screenrig_app.

It carries no credential: the signed state in the query is the only authority, is verified before anything it names is read, and is honored only while it is the connection's pending consent. screenRIG redeems the code with the application's secret and a PKCE verifier only this server can derive, requires that the calendar scope was granted (a person can untick it on the consent page) and a refresh token, reads the granting account from the ID token Google returned over that call, seals the refresh token and appends connection.connected.

Every outcome after a verified state redirects to the connection's page in the dashboard (/dashboard/connections/{id}?consent=connected or ?consent=failed), which reads status and last_error. A state that is unknown, expired, used, replaced or for a deleted connection renders a page that names nothing.

Answers only on the API host the callbacks are registered under.


Operation: completeGoogleConnectionConsent.

- Authentication: none
- Request body: none

#### Parameters

| Name | Send in | Required? | Description |
| --- | --- | --- | --- |
| state | query | optional |  |
| code | query | optional |  |
| error | query | optional |  |

#### Request template

~~~sh
curl --request GET 'https://api.screenrig.ai/oauth/connections/google/callback'
~~~

#### Responses

| Status | Meaning | Body and headers |
| --- | --- | --- |
| 302 | To the connection's page in the dashboard. | no body |
| 200 | Where no dashboard is configured, a page that says the connection is complete. | string (text/html) |
| 400 | A page that says the link was already used or has expired, or where no dashboard is configured why nothing was connected. | string (text/html) |
| 429 | Too many callbacks from this address. | no body |


## Sitemap

See the [public documentation sitemap](https://screenrig.ai/sitemap.md).
