Authentication
Create an API key and send it as a bearer token.
curl https://serpon.ai/user \
-H "Authorization: Bearer $SERPON_TOKEN" \
-H "Accept: application/json"
{
"id": 7,
"name": "Ada Lovelace",
"email": "ada@example.com",
"created_at": "2026-01-04T09:12:00.000000Z"
}
{
"message": "Unauthenticated."
}
Every request carries an API key in the Authorization header.
Authorization: Bearer 12|kR7xQ8fZ...
Accept: application/json
Content-Type: application/json
A key looks like 12| followed by 40 random characters. Send it whole — the leading ID is part of the credential.
Accept: application/json matters: without it, some failures render as HTML redirects instead of JSON.
Creating a key
Keys belong to an account, not to a person's login, so an integration keeps working when team membership changes.
Open API keys
Go to Account → API keys. You will be asked to confirm your password first — the page is behind a recent-authentication check.
Name and scope the key
Give it a name you will recognise in the list later, choose its access level, optionally restrict it to specific projects, and optionally set an expiry date.
Copy it once
The full key is displayed only at creation. Afterwards the list shows a fragment like kR7…9Qm and nothing more. Lost keys are replaced, not recovered.
Access levels
| Level | Abilities granted |
|---|---|
| Full access | * — everything the creating user's account role permits |
| Read only | articles:read, workflows:read, projects:read |
Abilities are always intersected with the creator's current account role, checked on each request. A key created by an admin who is later downgraded to member loses the admin-only abilities immediately; a key created by someone who leaves the account stops working. Nothing needs to be revoked by hand for that to happen.
| Ability prefix | Minimum role |
|---|---|
articles:*, workflows:*, projects:read | Member |
projects:write, projects:delete, members:*, tokens:* | Admin |
Project scoping and expiry
A key can be limited to a subset of the account's projects, and given an expires_at date. Expiry is enforced on every request — an expired key returns 401 with Token has expired.
Project scoping is enforced on Serpon's MCP server. On the REST endpoints, access is decided by the key's account and the creating user's project permissions, so treat a project-scoped key as an organisational label rather than a REST boundary.
Who am I
To confirm a key works and see which user it authenticates as:
See Current user for the full reference.
Failure modes
| Status | Body | Cause |
|---|---|---|
401 | {"message": "Unauthenticated."} | Header missing, malformed, or the key was deleted |
401 | {"message": "Token has expired."} | Past expires_at |
401 | {"message": "You are no longer a member of this account."} | Creator removed from the account |
403 | {"message": "This account is unavailable."} | The creating user's account has been disabled |
402 | NO_ACTIVE_SUBSCRIPTION | Key is valid, but the account has no plan |
A valid key is not enough on its own — an active subscription is checked before every /v1 route.
Handling keys
- Keep keys in environment variables or a secret manager, never in client-side code or a repository. Any holder of the key can spend the account's word quota.
- Use one key per integration so a single one can be revoked without disturbing the rest.
- Set an expiry on keys handed to contractors or short-lived jobs.
- Delete unused keys from Account → API keys; deletion takes effect immediately.