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
- Go to Developer settings in your ONCE account (Account → Developer).
- Click Create token.
- Give it a name (e.g.
Backend uploader) and choose an optional expiration — 30 days, 90 days, 1 year, or no expiration. - 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/meThe 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/creditsManage 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:
- Generate a PKCE
code_verifierand itsS256code_challenge. - Send the user to
https://beta.once.app/oauth/authorizewithresponse_type=code, yourclient_id,redirect_uri,scope=once:mcp, and thecode_challenge. - Exchange the returned code at
POST /v1/auth/tokenwith the matchingcode_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:
| Endpoint | Description |
|---|---|
POST /v1/accounts | Create 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/authorize | Password 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.