Skip to main content
Use a test key for the fictional sandbox or a live key for the three live account/license reads. Discovery, JWKS and receipt retrieval are public. Verification looks only in the caller’s mode; see the verification table. Connections and Talent API OAuth below describe the planned contract and cannot be used yet.

Secret keys

Send your key as a bearer token:
Choose Test or Live when creating a key in the dashboard. A key is a 256-bit secret, shown once when you create it. Reflections stores only a hash, so a lost key cannot be shown again; create a new one. To rotate a key, create the new key, deploy it, then revoke the old one in the dashboard. A revoked key stops working at once and cannot be restored. Keep keys on your server. Never put a key in a browser, a mobile app, a prompt or a model’s context. A client that follows a live session connects to the session stream with the session token instead.

Restricted keys

A restricted key can call only the endpoints its scopes cover. Give each service the scopes it needs: the supported inline generation flow needs checks:write and generations:write. Test helpers require an unrestricted key. A scope name does not mean its planned endpoint is implemented. For live mode, licenses:read covers only license list/retrieve; revision and material access remain planned. generations:read covers the live output list for a license. GET /v1/account works with any valid key. GET /v1/account works with any key. Connections and the test helpers need an unrestricted key. A call without the scope fails with:

Endpoints that need no key

Retrieve a receipt, discovery and JWKS need no key. A receipt’s unguessable ID grants access to its public JSON. Talent API OAuth metadata is planned. Verification searches only the caller’s mode. A request with no key searches live receipts: A receipt from the other mode returns 200 with result: "not_found", not an error. Do not read not_found as proof that a receipt does not exist until you have checked with the right key.

Planned: act for a licensee

A license belongs to its licensee, such as Ridgeline. When a platform such as Northlight runs the generation, it calls with its own secret key and names the licensee in Reflections-Account:
The header is valid only while an active connection links the two accounts and its scopes include what the call needs. Otherwise the call fails with 403 account_not_connected. The check records both sides: licensee is Ridgeline and platform is Northlight, and the receipt names both. Endpoints that accept the header list it on their reference page. Webhook endpoints and events do not: to receive events about a connected licensee’s objects, create the endpoint with connected: true (see Webhooks).

Planned: connect a licensee with OAuth

A connection is created when the licensee approves your platform through OAuth 2.0 authorization code with PKCE (S256). The authorization server metadata is at https://app.reflections.ai/.well-known/oauth-authorization-server.
1

Read your client ID

GET /v1/account returns platform.client_id and the platform.display_name the licensee will see. Register your redirect URI in the dashboard.
2

Send the licensee to the authorization page

Create a code verifier, keep it with the user’s session, and redirect to the authorization page, https://app.reflections.ai/oauth/authorize:
scope is a space-separated list of the connection scopes: talent:read, licenses:read, license_requests:write, files:write, checks:write, generations:write, sessions:write, revocations:write, usage:write and statements:read. Ask only for what you use.
3

The licensee approves

The licensee signs in to Reflections and sees your display_name, the scopes, and a choice of licenses: all of them, or the ones they list. If they decline, your redirect URI receives error=access_denied.
4

Create the connection

Your redirect URI receives code, state and iss. Check that state matches and that iss is https://app.reflections.ai, then redeem the code from your server with POST /v1/connections, your secret key and the code verifier, within 10 minutes:
No access token is issued: the code proves the licensee approved, and your secret key proves who you are. A code works once. An unknown, expired or used code, or a code_verifier or redirect_uri that does not match, returns 400 authorization_code_invalid; send the licensee through the authorization page again. Your account also receives connection.created.
5

Call for the licensee

Send your own secret key with Reflections-Account set to the connection’s licensee.
Either side can end a connection with DELETE /v1/connections/{connection_id}. You receive connection.revoked, and calls for that licensee fail with account_not_connected from that moment. Agents connect to the MCP server with OAuth 2.1 instead: they register and receive an access token from /oauth/token. See MCP.

Act for a talent

A representative, such as an agency or a manager, calls with its own key and names the talent in the path or the body. No header is needed: the mandate the talent gave your account decides what you may do, power by power. A call the mandate does not cover fails with 403 mandate_required, and every call fails that way once the mandate ends. See Talent representatives.

Parties

Talent, licensees, platforms and end users, and who answers for what.

Security

Key handling, token verification and webhook signing.