REST APIAuthentication

Authentication

Every request (except a few public discovery endpoints) requires an OAuth 2.1 access token with scope once:mcp, sent as a bearer token:

Authorization: Bearer <access_token>

A missing or invalid token returns 401 with an authentication_error.

There are three ways to obtain a token, in order of increasing setup effort:

  • Personal Access Token — create one from your ONCE account in seconds. Best for individual developers, agents, migration scripts, and backend automations.
  • OAuth 2.1 browser flow (PKCE) — best for apps that sign in on behalf of other users.
  • Partner server-to-server flow — for allowlisted partners provisioning their own users’ accounts.

Personal Access Tokens

A Personal Access Token (PAT) is a long-lived bearer token you create from your ONCE account. It works against every REST endpoint with exactly the same account permissions, credits, validation, rate limits, and release ownership as your account — no OAuth flow required.

Create a token

  1. Go to Developer settings in your ONCE account (Account → Developer).
  2. Click Create token.
  3. Give it a name (e.g. Backend uploader) and choose an optional expiration — 30 days, 90 days, 1 year, or no expiration.
  4. Click Create token and copy the value.

⚠️ The full token is shown only once, immediately after creation. ONCE stores only a hash, so it cannot be displayed again. If you lose it, revoke it and create a new one.

Tokens are prefixed once_pat_ so they’re easy to spot in logs and secret scanners. Store yours in an environment variable rather than committing it to source control:

export ONCE_ACCESS_TOKEN=once_pat_xxx
 
curl -H "Authorization: Bearer $ONCE_ACCESS_TOKEN" https://once.app/v1/me

The same token works for every endpoint — uploads, AI detection, release submission, and status:

curl -H "Authorization: Bearer $ONCE_ACCESS_TOKEN" https://once.app/v1/me/credits

Manage and revoke

Developer settings lists each token’s name, created date, last-used date, expiration, scopes, and status. Revoking a token takes effect immediately — any request using it afterwards fails with 401 authentication_error. Expired tokens fail the same way.

Scopes

PATs currently carry the once:mcp scope, which grants full REST API access on behalf of your account. More granular scopes may be added later.

Browser flow (PKCE)

For interactive apps, use the standard OAuth 2.1 authorization-code flow with PKCE:

  1. Generate a PKCE code_verifier and its S256 code_challenge.
  2. Send the user to https://beta.once.app/oauth/authorize with response_type=code, your client_id, redirect_uri, scope=once:mcp, and the code_challenge.
  3. Exchange the returned code at POST /v1/auth/token with the matching code_verifier.
curl -X POST https://once.app/v1/auth/token \
  -H 'Content-Type: application/json' \
  -d '{
    "grant_type": "authorization_code",
    "code": "<code>",
    "code_verifier": "<verifier>",
    "redirect_uri": "<your_redirect_uri>",
    "client_id": "<your_client_id>"
  }'

OAuth discovery metadata is published by the platform; the token endpoint is /v1/auth/token and the authorization endpoint is the platform oauth/authorize.

Partner (server-to-server) flow

Partners that run their own product on top of ONCE (the AIMD pattern) can provision and authorize their users’ ONCE accounts entirely server-side, without handling user passwords in the browser:

EndpointDescription
POST /v1/accountsCreate an account for an allowlisted partner client_id (PKCE required). Returns a one-shot authorization_code to exchange at /v1/auth/token with the matching code_verifier.
POST /v1/auth/authorizePassword authorize for an existing account (allowlisted partners). Returns a one-shot authorization_code.

Unknown client_ids are rejected, and these endpoints are rate-limited per IP and client_id.

Becoming a partner

To get an allowlisted client_id, a provenance tag, and a sandbox walkthrough, email tech@once.app. Once allowlisted, tag your requests with the X-Once-Provenance header (e.g. AIMD) so releases are attributed to your surface for analytics. There is no need to share any partner database credentials with ONCE — the bearer token is the only credential the gateway needs, and it is forwarded verbatim to the platform, which enforces authentication, allowlists, and rate limits.