Skip to main content
The Talent API serves the fictional sandbox and three live account/license reads. Sandbox tokens and receipts do not authorize real talent use. Follow the quickstart for the test journey. Key protection applies to both modes. Sections on connected licensees, sessions and webhooks describe the security requirements for planned capabilities.

Secret keys

Test keys start with rk_test_; live keys start with rk_live_. Both are sent as Authorization: Bearer. Each is a 256-bit secret, shown once when you create it in the dashboard. Reflections stores only a hash, so a lost key cannot be shown again; create a new one.
  • Keep keys on your servers, in a secret manager. Never put one in a web page, a mobile app, a browser extension or a repository.
  • Use a separate key for each service. Keep live credentials separate from test keys.
  • Do not log keys. Redact the Authorization header in your request logs.

Rotate a key

1

Create the new key

Create it in the dashboard with the same scopes.
2

Deploy it

Roll it out to every instance of the service and confirm traffic uses it.
3

Revoke the old key

Revoke it in the dashboard. Requests with it then fail with 401 invalid_api_key.
If a key leaks, revoke it first and deploy the replacement second. A few minutes of failed checks is better than a key someone else can use.

Restricted keys

A restricted key carries only the scopes you give it. A call outside them returns 403 insufficient_scope. The authentication reference lists the endpoints each scope is intended to cover. A scope does not make an unserved endpoint available; see Sandbox for test support and live reads for the three live endpoints. A live license reader needs licenses:read only. Give each service the least it needs. A generation worker needs files:write, checks:write and generations:write. A revocation worker needs revocations:write. Only your admin tooling needs webhooks:manage.

Acting for licensees

Connected-licensee access is not served in either mode. The API accepts your own account ID and rejects another account with account_not_connected. The following requirements apply to the planned connection flow. A platform acts for a connected licensee by sending its account ID in Reflections-Account. The call then runs under that licensee’s licenses, within the connection’s scopes and licenses. Without an active connection that allows the call, it fails with 403 account_not_connected. The header is a statement that this request is the licensee’s work. Treat it that way:
  • Set it from your own record of which licensee the signed-in user acts for. Never take it from a request parameter, a form field or anything the user can change.
  • Send a licensee’s account only for that licensee’s work. Running another customer’s request, or your own, under Ridgeline’s account uses Ridgeline’s licenses for work they did not commission.
  • When you receive connection.revoked, stop sending that account at once.
Only Ridgeline’s connected platforms can send acct_2q8v1m3n7p4r6s9t0wxyhk5zba, and every check records both the licensee and the platform.

Verify tokens

An authorization token (typ: tlp-auth+jwt) or a session token (typ: tlp-session+jwt) tells a generation tool what was authorized. The sandbox issues test authorization tokens only; it does not serve sessions or clear real talent. Verify every token before relying on it in its intended environment:
1

Signature

ES256, against the key with the token’s kid in https://app.reflections.ai/.well-known/jwks.json.
2

Header and issuer

typ is the type you expect, and iss is https://app.reflections.ai.
3

Audience

aud is the platform account you serve. A token issued to another platform fails here.
4

Time

exp has not passed and iat is not in the future, each with at most 60 seconds of leeway.
5

Version and obligations

tlp.ver has major version 1, and every type in tlp.obligations is one you handle.
6

Model and count

For an authorization token, tlp.execution.model is the model about to run, and you have run fewer than tlp.max_generations generations for this jti. For a session token, tlp.session is the session you are running; it carries no count and is replaced by renewal every minute.
Any JOSE library can do this. These examples use jose for Node.js and PyJWT for Python:
reserve(jti, n, max, exp) stands for an atomic increment in a store every instance of your tool shares: it adds n to the count for jti and returns false if that would pass max. Keep each count until 60 seconds after exp, and count a generation you start even if it fails.

Cache the JWKS

Cache the key set for the Cache-Control max-age of its response. When a token names a kid you do not have, refetch once; if it is still unknown, reject the token. The production protocol requires new keys to be published 30 days before signing, retired public keys to remain available, and each kid to be unique. These are production requirements, not evidence that a sandbox key has completed that publication period. The current sandbox uses rfl-test-… signing key IDs.

Webhook signatures

Hosted webhook delivery and secret rotation are not served by the current sandbox. The following is the required verification and rotation contract for the planned service. Every delivery is signed with your endpoint’s whsec_… secret under the Standard Webhooks scheme. The handler in Handle revocations shows the full check. The rules:
  • Verify against the raw body, before any JSON parsing changes it.
  • Compute HMAC-SHA256 with the secret’s base64 part over webhook-id.webhook-timestamp.body, and accept the delivery if it matches any v1, entry in webhook-signature. Compare in constant time.
  • Reject a webhook-timestamp more than 5 minutes from your clock.
  • Use only HTTPS endpoint URLs.
To rotate a secret, call POST /v1/webhook_endpoints/{endpoint_id}/rotate_secret. For 24 hours, deliveries carry signatures from both the old and the new secret, so you can deploy the new one without dropping events. Rotate at once if a secret leaks.

Data you send

Send end users as opaque platform IDs, never emails or names, and keep personal data out of metadata. Session tokens may reach a client to open the session stream; secret keys never do. See Privacy modes.

Report a vulnerability

Email security@reflections.ai. Include what you found, the steps to reproduce it, the request IDs involved, and what an attacker could do with it. Test only in test mode, with your own account and the sandbox talent. Do not access other accounts’ data, real talent’s material or other platforms’ outputs, and do not degrade the service for others. Keep the details private until Reflections has fixed the issue.
Never send a live secret key, a webhook secret or an end user’s personal data in a report. If a key was exposed, revoke it in the dashboard before you write.

Authentication

Keys, scopes, Reflections-Account and OAuth.

Authorization token

Every claim of the check token.

Security in the Standard

The threat model and its requirements.

Webhooks

Signing, retries and replay.