Every /v1/* route accepts three credential types through one policy:
customer API keys, Firebase ID tokens for signed-in web users, and Firebase
App Check tokens for anonymous browser scans.
Prefer Authorization: Bearer for new clients. X-Api-Key exists for
environments where setting the authorization header is inconvenient.
Signed-in web users send a Firebase ID token as the bearer credential:
text
Authorization: Bearer <firebase-id-token>
Anonymous browser scans send a Firebase App Check token instead:
text
X-Firebase-AppCheck: <app-check-token>
Credentials are resolved fail-closed. When an Authorization header is
present it must be valid on its own; an invalid bearer credential is never
downgraded to the App Check path even if an X-Firebase-AppCheck header is
also sent. An invalid Firebase ID token or App Check token returns
401 invalid_public_credential.
json
{
"error": {
"code": "invalid_public_credential",
"message": "Missing or invalid public credential."
}
}
API keys and signed-in Firebase users hold all public scopes:
Anonymous App Check credentials are scoring only: they hold just
score_jobs:create and score_jobs:read. A /v1/rewrite-jobs or
/v1/uploads request with only an App Check token returns
403 insufficient_scope.
Missing, unknown, expired, revoked, or rotated-away API keys return
401 invalid_api_key. A valid key without the required scope returns
403 insufficient_scope.
json
{
"error": {
"code": "invalid_api_key",
"message": "The API key is missing or invalid."
}
}
Jobs are owned by the credential that created them: an API key sees only its
own jobs, a signed-in user sees the jobs created with their ID token, and an
anonymous browser can poll only the jobs created with the same App Check app
and network origin. Anonymous and free-account scans are subject to the
allowances described in rate limits.
Dashboard authentication is separate. /dashboard/* routes use Firebase ID
tokens for the web app, not customer API keys, and are unsupported internal implementation
details for public API clients.