Get started

Authentication

Every request to /v1 carries a bearer token. There is one header form and no query-string alternative.

The only auth header
Authorization: Bearer upfynai-sk-...

API keys#

A key is the string upfynai-sk- followed by 32 hex characters. We store a hash of it, never the key, which has one consequence worth stating plainly: the full key is returned exactly once, when you create it. After that every listing shows only a preview like upfynai-sk-...4f31.

Creating a key

POST /v1/me/keys
curl https://ai.upfyn.com/v1/me/keys \
-H "Authorization: Bearer $UPFYN_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "production-worker", "scopes": ["gateway:inference"] }'
201 Created
{
"id": "ak_7c19d4a2f0b34e6d81af52c9e7d03b1a",
"key": "upfynai-sk-9f3c1d70a84b42e5b1c6a7d208e94f31",
"user_id": "usr_...",
"name": "production-worker",
"scopes": ["gateway:inference"],
"key_type": "user",
"app_id": null
}
FieldTypeRequiredNotes
namestring—A label for you. Name it after the thing that will use it.
scopesstring[]—Defaults to gateway:full if omitted or empty. See below.
app_idstring—Attributes usage to one of your developer apps.
expires_atstring—ISO timestamp. The key stops working after it.

Treat a key like a password

A key spends your credits. Keep it on a server you control, in an environment variable. Never ship one in a browser bundle, a mobile binary, or a public repository. If one leaks, revoke it from API Keys immediately — revocation takes effect on the next request.

Scopes#

Scopes narrow what a key may do. Give a key the least it needs: a worker that only runs inference has no business reading your billing history.

ScopeGrants
gateway:inferenceChat, tools, images, audio, video — every model endpoint.
profile:readRead your account and workspace.
profile:writeUpdate your profile and rename your workspace.
usage:readUsage, logs and session history.
billing:readPurchases and the credit ledger.
gateway:fullEverything, including creating and deleting sessions. The default.

Scopes on API keys are narrower than they look

Scope checks on the account endpoints (/v1/me/*) currently apply to OAuth tokens only. An API key with just gateway:inference is still blocked from inference it lacks — but it is not blocked from reading /v1/me. Do not rely on a narrow scope as a hard boundary against your own account data; rely on it for inference control, and treat every key as account-level for reads.

Other credentials#

The same header accepts three other kinds of token, tried in order. You are unlikely to need any of them directly.

  • OAuth access tokens — issued to a developer app acting for a user. These do get strict scope enforcement, and they cannot manage API keys.
  • Shared session tokens — minted by Upfyn sign-in and used by our own apps.
  • Session cookie — when there is no Authorization header, the dashboard’s own cookie is used. Browser only.

There is no x-api-key header

Some providers accept a key in a custom header or a query parameter. This one does not. A request without Authorization: Bearer … is a 401.

What failure looks like#

StatuscodeMeaning
401invalid_api_keyMissing, malformed, revoked or expired. The only 401 in the auth path.
403insufficient_scopeValid key, but it lacks the scope this endpoint needs.
403account_blockedThe account is suspended. Contact support.
403api_access_disabledAPI access is turned off for this account.
402insufficient_creditsAuthentication was fine; you are out of credits. See Credits.

A 402 is not an auth failure and should not trigger a re-auth. Retrying it without adding credits will fail identically.