Skip to main content
An OAuth connection belongs to one organization. A protection belongs to one external provider key inside that connection. Two external keys create two protectionId values, credentials, gateways, and runtime tokens.
The OAuth access token identifies the parent connection. Every child operation accepts only protectionId; it never accepts the parent OAuth connection ID, gateway ID, credential ID, or token ID. An ID from another connection returns 404 without revealing whether it exists.

Authentication and scopes

Send the OAuth access token as Authorization: Bearer. Required scopes:
  • protections:provision — provider discovery, preflight, model discovery, and creation.
  • protections:read — list and read protections.
  • protections:update — gateway name, models, settings, and entitled OTel configuration.
  • protections:manage — revoke, reactivate, and rotate provider/runtime credentials.
  • protections:read-logs — request metadata for runtime tokens owned by this installation.
  • protections:read-spend — token usage and monetary spend for this installation.
  • offline_access — rotating refresh tokens.
Private and public Apps use these same protection operations and scopes. The OAuth token’s installation binding—not the App distribution—selects the organization and resources that each request can access.

Resolve providers

Resolve by slug; never hard-code the UUID. kind, native_base_path, and base_url_default describe the provider and its upstream API. They do not form an /gw/... URL. Build data-plane URLs from the returned gateway slug with buildGatewayConnectionConfig() or use the connection paths documented in Connect an AI client. kind is one of openai-compatible, anthropic, gemini, or arc.

Preflight

Preflight performs no writes and receives no provider key.
After first-use provisioning, project and serviceAccount in resources become 0, and project contains the existing installation project.

Discover models

This operation validates but does not persist the key. canonicalId, aliases, modes, lifecycle, and pricing are optional because upstream catalogs do not all publish them. capabilities describes the provider claim; supportedCapabilities and airctrlSupport describe what can safely route. Capability values are chat, vision, tools, streaming, responses, embeddings, image_generation, audio, realtime, moderation, ocr, completions, code_completion, video, native_completion, code_generation, generative_ui, research, document_generation, and browser. An upstream 401 or 403 is a typed, non-exceptional invalid-key result:

Create one protection

Use one stable idempotency key for one external key and request body. Reuse both unchanged after an uncertain network result.
Input validation follows the API contract: Creation is atomic. The first protection lazily creates the connection’s project and internal Service Account, and adds the approving user to the project as ProjectAdmin. Every protection creates its own credential, gateway, model bindings, and runtime token. That gateway token has only the data-plane run scope; it cannot manage resources or read logs.
Persist externalResourceId → protectionId. The nested IDs are metadata; lifecycle operations require only protectionId.

List and read protections

The list response uses { "ok": true, "data": [...] }; the read response uses { "ok": true, "data": { ... } }. Runtime token plaintext is omitted from ordinary list/read responses.
Every protection returns one explicit lifecycle state:
  • active — runtime access is enabled.
  • connection_suspended — an installation disconnect disabled runtime access; this protection is eligible for automated restoration after reauthorization.
  • revoked — this protection was explicitly revoked and must never be restored automatically.
After reconnecting, list protections and call reactivate for the selected connection_suspended entries. A partner may reactivate several existing protections and provision new external keys in the same OAuth session. Each operation remains independent and idempotent. The connection-details surface presents current permissions separately from Connection history. Every Connect/Disconnect history event includes the scope snapshot effective for that event, so later reauthorization never rewrites the evidence of earlier consent.

Update a protection

The response is the updated protection object. validates models again and encrypts OTel headers. Updating one protection does not alter siblings. Protection list/read/update responses do not return the OTel configuration or its headers. Keep the desired non-secret OTel settings in the partner backend; header plaintext is write-only and is never returned. Changing gatewayName also derives and replaces that gateway’s slug. Read the returned gateway.slug and rebuild any stored connection URLs. A slug collision returns oauth_gateway_name_conflict. OTel updates are partial. Omit otel.headers to preserve the encrypted headers already stored by . Send "headers": null or an empty object to clear them. Send a non-empty object to replace them. Enabling OTel requires the organization’s effective otelExport entitlement; disabling an existing configuration does not. Run preflight with otel=true before offering enablement. exportBodies=true additionally requires both loggingEnabled=true and logBodies=true. Turning off either gateway setting automatically turns off OTel body export. OTel is optional: the OAuth log and spend endpoints below work without it. OTel delivers the same canonical events in real time with an OTLP envelope when the customer plan permits export.

Read protection logs

Requires protections:read-logs. Supported filters are since, provider, model, status, limit, offset, and opaque cursor. Do not combine a cursor with a non-zero offset. limit defaults to 50 and must be between 1 and 200. offset defaults to 0 and cannot be negative. When cursor is present, reuse the exact filters from the preceding page.
The query is restricted to the protection gateway and runtime tokens owned by this installation’s internal Service Account. Rotated replacement tokens remain included; customer-created tokens on the same gateway are excluded. cost is null unless the access token also has protections:read-spend. OAuth never exposes stored request or response bodies.

Read protection spend

Requires protections:read-spend. since is optional and must be an ISO 8601 timestamp.
Totals are derived from persisted request logs for the same installation-owned runtime-token boundary as the log endpoint. They do not include customer-created tokens or another protection.

Rotate the provider key

validates the replacement against every model currently bound to the gateway before atomically replacing the encrypted credential. The key is never returned.

Rotate the runtime token

The previous runtime token is revoked atomically. The response is the protection object and includes the replacement gatewayToken.plaintext once.

Revoke one protection

The operation is idempotent. It revokes that protection’s runtime token, sets state to revoked, and stamps accessRevokedAt. It does not delete the gateway, credential, logs, settings, or audit history. Sibling protections remain active.

Reactivate one protection

revalidates the stored provider credential and model bindings, then issues a new runtime token. The response includes the new plaintext once. An already-active protection is an idempotent no-op and does not mint another token. Retry with the same idempotency key to recover the same one-time plaintext after an uncertain response. Successful reactivation clears both lifecycle timestamps and returns state: "active". If a newer runtime-token operation already superseded that result, retrying the older idempotency key returns 409 with idempotency_operation_superseded. Keep the newest successful runtime token and do not retry the older operation with a new key.

Successful response families

The complete protection object is the shape shown in Create one protection. Operations are grouped below because they deliberately reuse that same object: Idempotent create, runtime rotation, and reactivation responses may also include replayed: true. Store a returned plaintext before acknowledging the operation to the external platform.

OAuth token lifecycle and full disconnect

  • POST /v1/oauth/token exchanges an authorization code or rotates a refresh token.
  • POST /v1/oauth/revoke revokes the submitted access token or refresh-token family.
  • Connected apps → Disconnect revokes the entire OAuth connection, every access/refresh token, every active protection runtime token, and the internal Service Account. Protections that were active become connection_suspended; protections already marked revoked remain revoked. Resources and audit history remain.
  • Reauthorizing the same App/organization reuses the installation and preserved resources but revokes every prior access/refresh token before the new authorization code is issued.
See OAuth protocol for complete token and revocation request/response payloads.

Errors and retries

Resource API failures use the standard error envelope:
Stable codes include:
  • idempotency_key_invalid, idempotency_key_reused, idempotency_operation_in_progress, and idempotency_operation_superseded;
  • oauth_external_resource_already_protected, oauth_gateway_installation_changed, oauth_gateway_installation_not_found, and oauth_gateway_name_conflict;
  • oauth_gateway_protection_revoked and oauth_gateway_protection_connection_suspended;
  • oauth_project_unavailable, oauth_service_account_inactive, and oauth_service_account_unrecoverable;
  • provider_key_invalid, provider_endpoint_not_configured, provider_validation_unavailable, provider_model_not_available, provider_model_not_supported, model_required, and gateway_name_invalid; and
  • otel_endpoint_required, otel_not_available, log_bodies_require_logging, otel_bodies_require_gateway_log_bodies, and otel_headers_invalid.

SDK mapping

  • Preflight — preflightProtection()
  • Create — provisionProtection()
  • List / read — listProtections() / getProtection()
  • Update — updateProtection()
  • Request logs — listProtectionLogs()
  • Spend — getProtectionSpend()
  • Rotate provider key — rotateProtectionProviderKey()
  • Rotate runtime token — rotateProtectionRuntimeToken()
  • Revoke — revokeProtection()
  • Reactivate — reactivateProtection()
CLI and MCP do not expose OAuth App credential modes or protection lifecycle commands. Keep OAuth client secrets and refresh tokens out of their configuration. OAuth Apps are confidential-backend integrations available through direct HTTP/OpenAPI and OAuthPartnerClient.