Organization Integrations
7 operations.
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/organization-integrations/presets | List BYOC preset catalog |
| GET | /api/v1/organizations/{organizationIdOrSlug}/integrations | List organization integrations |
| POST | /api/v1/organizations/{organizationIdOrSlug}/integrations | Register a BYOC organization integration |
| GET | /api/v1/organizations/{organizationIdOrSlug}/integrations/{integrationId} | Get organization integration |
| PATCH | /api/v1/organizations/{organizationIdOrSlug}/integrations/{integrationId} | Rotate client credentials |
| DELETE | /api/v1/organizations/{organizationIdOrSlug}/integrations/{integrationId} | Remove an organization integration |
| POST | /api/v1/organizations/{organizationIdOrSlug}/integrations/{integrationId}/verify | Verify BYOC OAuth credentials |
List BYOC preset catalog
GET /api/v1/organization-integrations/presets
List the OAuth 2.0 BYOC integration presets supported by this deployment. Each preset carries the principal-binding declaration, documented scopes, admin setup instructions, and the redirect URI that must be registered on the admin's OAuth client.
Static bearer-token presets are intentionally excluded from this OAuth client-registration catalog because they do not require an OAuth client.
The catalog is a curated, code-defined list — only Perstack ships new presets; admins register credentials against an existing preset.
Responses
| Status | Description | Body |
|---|---|---|
200 | Response for status 200 | application/json — object — data: object (required) |
400 | The request is malformed or cannot be processed. | application/json — PublicApiError — error: object (required) |
401 | Authentication failed. The Authorization header is missing, or the credential is invalid or expired. | application/json — PublicApiError — error: object (required) |
403 | Access denied. The authenticated user does not have permission to perform this action. | application/json — PublicApiError — error: object (required) |
404 | Resource not found. | application/json — PublicApiError — error: object (required) |
409 | Request conflicts with current state of the resource, including safe deployment conflict classifications. | application/json — PublicApiError — error: object (required) |
422 | Request validation failed. Check the request body, query parameters, or path parameters. | application/json — PublicApiError — error: object (required) |
429 | Too many requests. The code foreign_resource_rate_limited means the caller made too many requests for Projects outside its reach: correct the Project id instead of retrying. | application/json — PublicApiError — error: object (required) |
500 | The server could not complete the request. | application/json — PublicApiError — error: object (required) |
503 | Service temporarily unavailable (e.g. execution capacity exhausted). The response carries a Retry-After header; retry with backoff. | application/json — PublicApiError — error: object (required) |
List organization integrations
GET /api/v1/organizations/{organizationIdOrSlug}/integrations
List BYOC OAuth 2.0 client registrations for the current organization. Only returns metadata — client secrets are never included in the response.
Parameters
path
| Name | Type | Required | Description |
|---|---|---|---|
organizationIdOrSlug | one of 2 types | required | Identifies the organization by its stable identifier or slug. Applies to List organization integrations. |
Responses
| Status | Description | Body |
|---|---|---|
200 | Response for status 200 | application/json — object — data: object (required) |
400 | The request is malformed or cannot be processed. | application/json — PublicApiError — error: object (required) |
401 | Authentication failed. The Authorization header is missing, or the credential is invalid or expired. | application/json — PublicApiError — error: object (required) |
403 | Access denied. The authenticated user does not have permission to perform this action. | application/json — PublicApiError — error: object (required) |
404 | Resource not found. | application/json — PublicApiError — error: object (required) |
409 | Request conflicts with current state of the resource, including safe deployment conflict classifications. | application/json — PublicApiError — error: object (required) |
422 | Request validation failed. Check the request body, query parameters, or path parameters. | application/json — PublicApiError — error: object (required) |
429 | Too many requests. The code foreign_resource_rate_limited means the caller made too many requests for Projects outside its reach: correct the Project id instead of retrying. | application/json — PublicApiError — error: object (required) |
500 | The server could not complete the request. | application/json — PublicApiError — error: object (required) |
503 | Service temporarily unavailable (e.g. execution capacity exhausted). The response carries a Retry-After header; retry with backoff. | application/json — PublicApiError — error: object (required) |
Register a BYOC organization integration
POST /api/v1/organizations/{organizationIdOrSlug}/integrations
Register the admin-supplied OAuth 2.0 client credentials for a preset.
The credentials are probed against the provider's token endpoint inside
this request — registration is only persisted when the probe succeeds
(invalid_grant response). A definitive rejection of the supplied
config (invalid_client, redirect_uri_mismatch, unexpected response
shape) returns 400 with the diagnostic and writes no row. A transient
upstream outage returns 503, and an upstream rate-limit returns 429
with a Retry-After header — neither writes a row, so the caller can
retry. A successful registration stamps verifiedAt for the probed
credential version.
Subsequent operational drift (rotated credentials, revoked client) is
detected via the manual re-verify endpoint
POST /:integrationId/verify, which updates verifiedAt independently
from lifecycle status and lets ops triage integration-side vs.
connection-side failures.
Only one registration per (organization, presetKey) pair is allowed — re-registering the same preset returns 409; rotate through update or delete + create instead.
Parameters
path
| Name | Type | Required | Description |
|---|---|---|---|
organizationIdOrSlug | one of 2 types | required | Identifies the organization by its stable identifier or slug. Applies to Register a BYOC organization integration. |
Request body
Required — Request body for: Register a BYOC organization integration.
application/json
| Name | Type | Required | Description |
|---|---|---|---|
presetKey | "google-workspace" | required | |
clientId | string | required | |
clientSecret | string | required |
Responses
| Status | Description | Body |
|---|---|---|
200 | Response for status 200 | application/json — object — data: object (required) |
400 | The request is malformed or cannot be processed. | application/json — PublicApiError — error: object (required) |
401 | Authentication failed. The Authorization header is missing, or the credential is invalid or expired. | application/json — PublicApiError — error: object (required) |
403 | Access denied. The authenticated user does not have permission to perform this action. | application/json — PublicApiError — error: object (required) |
404 | Resource not found. | application/json — PublicApiError — error: object (required) |
409 | Request conflicts with current state of the resource, including safe deployment conflict classifications. | application/json — PublicApiError — error: object (required) |
422 | Request validation failed. Check the request body, query parameters, or path parameters. | application/json — PublicApiError — error: object (required) |
429 | Too many requests. The code foreign_resource_rate_limited means the caller made too many requests for Projects outside its reach: correct the Project id instead of retrying. | application/json — PublicApiError — error: object (required) |
500 | The server could not complete the request. | application/json — PublicApiError — error: object (required) |
503 | Service temporarily unavailable (e.g. execution capacity exhausted). The response carries a Retry-After header; retry with backoff. | application/json — PublicApiError — error: object (required) |
Get organization integration
GET /api/v1/organizations/{organizationIdOrSlug}/integrations/{integrationId}
Fetch a single BYOC OAuth 2.0 client registration. Client secret is never returned.
Parameters
path
| Name | Type | Required | Description |
|---|---|---|---|
organizationIdOrSlug | one of 2 types | required | Identifies the organization by its stable identifier or slug. Applies to Get organization integration. |
integrationId | string | required | Identifies the organization integration being addressed. Applies to Get organization integration. |
Responses
| Status | Description | Body |
|---|---|---|
200 | Response for status 200 | application/json — object — data: object (required) |
400 | The request is malformed or cannot be processed. | application/json — PublicApiError — error: object (required) |
401 | Authentication failed. The Authorization header is missing, or the credential is invalid or expired. | application/json — PublicApiError — error: object (required) |
403 | Access denied. The authenticated user does not have permission to perform this action. | application/json — PublicApiError — error: object (required) |
404 | Resource not found. | application/json — PublicApiError — error: object (required) |
409 | Request conflicts with current state of the resource, including safe deployment conflict classifications. | application/json — PublicApiError — error: object (required) |
422 | Request validation failed. Check the request body, query parameters, or path parameters. | application/json — PublicApiError — error: object (required) |
429 | Too many requests. The code foreign_resource_rate_limited means the caller made too many requests for Projects outside its reach: correct the Project id instead of retrying. | application/json — PublicApiError — error: object (required) |
500 | The server could not complete the request. | application/json — PublicApiError — error: object (required) |
503 | Service temporarily unavailable (e.g. execution capacity exhausted). The response carries a Retry-After header; retry with backoff. | application/json — PublicApiError — error: object (required) |
Rotate client credentials
PATCH /api/v1/organizations/{organizationIdOrSlug}/integrations/{integrationId}
Rotate the admin-supplied client ID and/or client secret. The new credentials are probed against the provider's token endpoint inside this request — the rotation is only persisted when the probe succeeds. A definitive probe rejection returns 400 with the diagnostic; a transient upstream outage returns 503 and an upstream rate-limit returns 429 with a Retry-After header. In every failure case the existing row is left untouched, so the integration cannot silently degrade into an unusable state.
Rotation creates a new immutable credential version from exactly the
probed client ID and secret and stamps verifiedAt for it. A rotation
that replaced the stored version while this request was probing returns
409 with conflictReason integration-rotated and persists nothing;
reload and retry. The preset key is immutable.
Parameters
path
| Name | Type | Required | Description |
|---|---|---|---|
organizationIdOrSlug | one of 2 types | required | Identifies the organization by its stable identifier or slug. Applies to Rotate client credentials. |
integrationId | string | required | Identifies the organization integration being addressed. Applies to Rotate client credentials. |
Request body
Required — Request body for: Rotate client credentials.
application/json
| Name | Type | Required | Description |
|---|---|---|---|
clientId | string | optional | |
clientSecret | string | optional |
Responses
| Status | Description | Body |
|---|---|---|
200 | Response for status 200 | application/json — object — data: object (required) |
400 | The request is malformed or cannot be processed. | application/json — PublicApiError — error: object (required) |
401 | Authentication failed. The Authorization header is missing, or the credential is invalid or expired. | application/json — PublicApiError — error: object (required) |
403 | Access denied. The authenticated user does not have permission to perform this action. | application/json — PublicApiError — error: object (required) |
404 | Resource not found. | application/json — PublicApiError — error: object (required) |
409 | Request conflicts with current state of the resource, including safe deployment conflict classifications. | application/json — PublicApiError — error: object (required) |
422 | Request validation failed. Check the request body, query parameters, or path parameters. | application/json — PublicApiError — error: object (required) |
429 | Too many requests. The code foreign_resource_rate_limited means the caller made too many requests for Projects outside its reach: correct the Project id instead of retrying. | application/json — PublicApiError — error: object (required) |
500 | The server could not complete the request. | application/json — PublicApiError — error: object (required) |
503 | Service temporarily unavailable (e.g. execution capacity exhausted). The response carries a Retry-After header; retry with backoff. | application/json — PublicApiError — error: object (required) |
Remove an organization integration
DELETE /api/v1/organizations/{organizationIdOrSlug}/integrations/{integrationId}
Remove an organization's OAuth 2.0 client registration by its integration ID.
Parameters
path
| Name | Type | Required | Description |
|---|---|---|---|
organizationIdOrSlug | one of 2 types | required | Identifies the organization by its stable identifier or slug. Applies to Remove an organization integration. |
integrationId | string | required | Identifies the organization integration being addressed. Applies to Remove an organization integration. |
Responses
| Status | Description | Body |
|---|---|---|
204 | Response for status 204 | none — none |
400 | The request is malformed or cannot be processed. | application/json — PublicApiError — error: object (required) |
401 | Authentication failed. The Authorization header is missing, or the credential is invalid or expired. | application/json — PublicApiError — error: object (required) |
403 | Access denied. The authenticated user does not have permission to perform this action. | application/json — PublicApiError — error: object (required) |
404 | Resource not found. | application/json — PublicApiError — error: object (required) |
409 | Request conflicts with current state of the resource, including safe deployment conflict classifications. | application/json — PublicApiError — error: object (required) |
422 | Request validation failed. Check the request body, query parameters, or path parameters. | application/json — PublicApiError — error: object (required) |
429 | Too many requests. The code foreign_resource_rate_limited means the caller made too many requests for Projects outside its reach: correct the Project id instead of retrying. | application/json — PublicApiError — error: object (required) |
500 | The server could not complete the request. | application/json — PublicApiError — error: object (required) |
503 | Service temporarily unavailable (e.g. execution capacity exhausted). The response carries a Retry-After header; retry with backoff. | application/json — PublicApiError — error: object (required) |
Verify BYOC OAuth credentials
POST /api/v1/organizations/{organizationIdOrSlug}/integrations/{integrationId}/verify
Probe the provider's token endpoint with the admin-registered credentials and
a deliberately-bogus authorization code. A correctly-configured OAuth client
fails with invalid_grant (credentials valid, code wrong) — that is the
success signal. Any other failure maps to a specific diagnostic the UI can
render.
A definitive verification result (success or a config-level failure) is
persisted to verifiedAt for the probed credential version and returned
200 with the outcome in the body. If the credentials were rotated while the
probe ran, nothing is persisted and the endpoint returns 409 with
conflictReason integration-rotated; run verify again. A transient
upstream outage returns 503 / 429 with a Retry-After header and leaves the
stored verification state unchanged, so a provider blip can never poison the
integration's verification state.
Parameters
path
| Name | Type | Required | Description |
|---|---|---|---|
organizationIdOrSlug | one of 2 types | required | Identifies the organization by its stable identifier or slug. Applies to Verify BYOC OAuth credentials. |
integrationId | string | required | Identifies the organization integration being addressed. Applies to Verify BYOC OAuth credentials. |
Responses
| Status | Description | Body |
|---|---|---|
200 | Response for status 200 | application/json — object — data: object (required) |
400 | The request is malformed or cannot be processed. | application/json — PublicApiError — error: object (required) |
401 | Authentication failed. The Authorization header is missing, or the credential is invalid or expired. | application/json — PublicApiError — error: object (required) |
403 | Access denied. The authenticated user does not have permission to perform this action. | application/json — PublicApiError — error: object (required) |
404 | Resource not found. | application/json — PublicApiError — error: object (required) |
409 | Request conflicts with current state of the resource, including safe deployment conflict classifications. | application/json — PublicApiError — error: object (required) |
422 | Request validation failed. Check the request body, query parameters, or path parameters. | application/json — PublicApiError — error: object (required) |
429 | The provider rate-limited the verify probe. Retry after the Retry-After interval. The stored verification state is left unchanged. | application/json — PublicApiError — error: object (required) |
500 | The server could not complete the request. | application/json — PublicApiError — error: object (required) |
503 | The provider was transiently unreachable during the verify probe. Retry with backoff. The stored verification state is left unchanged. | application/json — PublicApiError — error: object (required) |