Authentication and API keys
Every /v1 request is authenticated with an API key.
curl -s "https://api.upserve.app/v1/deployments" \
-H "Authorization: Bearer $UPSERVE_API_KEY"A key is a string that starts with up_. A missing key, a malformed key, or a revoked or expired key returns 401 INVALID_API_KEY.
The key is shown only once
- The key itself appears only in the response when you create or rotate it. The server stores only a one-way hash of the key, so it cannot show it again.
- If you lose it, create a new key or rotate.
- Keep it in an environment variable or a secret store. Do not put it in code, logs, error reports, a browser, or a mobile app.
- A key belongs to a Project. Key management (create, rotate, revoke) is done only by an organization OWNER through the signed-in management screen or the management API. An execution API key cannot do it.
- If the person who issued a key loses organization OWNER permission, that key starts returning
401 INVALID_API_KEY.
Scopes
You choose the allowed scopes for each key. An operation without its scope returns 403 INSUFFICIENT_SCOPE.
| scope | Allowed operations |
|---|---|
deployments:read | List and read Deployments |
sessions:read | Read Sessions and Items |
sessions:write | Create, close, and delete Sessions |
turns:read | List Turns and read their status |
turns:write | Create Turns (including the first Turn of a new Session) |
turns:cancel | Cancel a Turn |
events:read | Read Session and Run events (SSE) |
usage:read | Read usage |
files:write | Upload input files (including Session files) |
artifacts:read | Read Artifact details and download |
workflows:read | Read workflow details |
workflows:run | Submit a Run |
runs:read | Read Run status and results |
runs:cancel | Cancel a Run |
runs:delete | Delete a Run |
actions:resolve | Resolve questions (RequiredAction) that the caller may answer |
actions:approve | Submit human approvals or rejections collected by your service (explicit delegation) |
works:read | Read and list organization work preparations |
works:write | Submit an organization work, revise its spec, and answer preparation questions |
works:approve | Submit a person’s scope confirmation collected by your service (explicit delegation) |
One request can require several scopes. For example, creating a Session needs sessions:write and turns:write, and reading a Turn result needs turns:read and sessions:read. Grant only the minimum scopes you need.
Deployment and workflow allowlists
Separately from scopes, a key has a list of Deployments and workflows it may call.
- A Deployment or workflow that is not on the key answers
404 NOT_FOUND, so its existence is not revealed. - The effective permission is the intersection of the key scopes, the Project and key allowlists, and the capabilities frozen at publication. Scopes alone never widen access.
- Split keys by purpose, and allow each key only the Deployments it needs.
- A key with at least one works scope and nothing else but
usage:readruns no Deployment, so it can be created without one. A key that mixes in any other scope needs at least one Deployment. See organization works.
Rotation
Use rotation to replace a key. Rotating creates a new key with the same name, scopes, and allowlists, and the new key appears once in the response.
- At rotation you explicitly choose an overlap time (
overlap_seconds, 0 to 86,400 seconds). The default of 0 revokes the old key immediately. - With an overlap, the old key expires once that time has passed, and both keys work in the meantime. It gives your callers time to move to the new key.
- Rotating a key that is already revoked, expired, or rotated returns
409 KEY_NOT_ROTATABLE. Create a new key instead. - Idempotency receipts are kept at Project scope, so resending with the same
Idempotency-Keystill works after rotation.
Revocation
- Revocation immediately blocks new requests and the start of new external effects right after it commits. Later requests return
401 INVALID_API_KEY. - Unfinished Turns and Runs that were already accepted are switched to cancel requests. Effects that already completed are not undone, and an in-flight model call is not guaranteed to stop at once.
- Open SSE connections are closed at their periodic revalidation.
- Revoking a Project disables all of its keys.
Expiry
A key has no caller-chosen lifetime (expiry date). A key expires in only two ways.
- The old key expires at a set time after a rotation that had an overlap.
- An owner revokes it.
Rotate on a regular schedule to keep key lifetimes short.
Rate limits
Call rates are limited per key, Project, and Deployment. When you exceed them you get 429 RATE_LIMITED and Retry-After. See limits and data for the numbers.