Authentication
All public Diafunc APIs share a single authentication model based on API tokens. This page describes how to obtain a token, how to present it on a request, which scopes control what operations, and the shape of the error responses returned by every API.
API tokens
API tokens are structured, prefixed strings of the form dfat_<id>_<secret>: a dfat_ prefix, a token id, and a secret part; callers treat the secret as opaque. They are issued by the Admin API. Each token is bound to one of three things, described under Token kinds below, and carries a set of scopes that determine which operations it can perform.
A token is presented on every request as a Bearer token in the Authorization header.
Example request
curl -H "Authorization: Bearer dfat_..." \
https://diafunc.com/api/v1/storage/table-importersWeb sessions
User sessions from the Diafunc web application use a separate mechanism: OpenID Connect with ES256-signed JWTs issued by auth.diafunc.com. The signing keys are published at auth.diafunc.com/.well-known/jwks.json and rotated periodically. API tokens remain the right choice for programmatic access from external systems.
Scopes
The following scopes can be granted to an API token. Scopes are additive: a token with storage:write also implicitly allows storage:read operations on the same resource.
| Scope | Grants |
|---|---|
| project:read | Read project metadata, members, and settings. |
| project:write | Modify project metadata, members, and settings. |
| storage:read | Read entities, links, events, tables, and notebooks of a project. |
| storage:write | Create, update, and delete project content. |
| evaluation:read | Inspect evaluations, outputs, and logs. |
| evaluation:execute | Start and stop evaluations, manage triggers. |
Token kinds
Every token is one of three kinds. Its scopes limit it further in each case.
| Kind | Where it is created | What it reaches |
|---|---|---|
Personal (user) | Account page, tab API tokens. Only you can create, list and revoke your personal tokens. | Every project you can open with your own sign-in (your own, those shared with you, and your team's), with the same roles. It can create projects and analyses owned by you. |
Project (project) | Project settings, section API tokens, by an owner or maintainer of the project. | That one project. It cannot create projects. |
Team (team) | Team page, tab API Tokens, by an owner or admin of the team. | Every project the team owns. It can create projects owned by the team. |
No token reaches account management: password, sign-in methods, profile, plan, billing, invoices, team administration and the tokens themselves need a signed-in session. Analysis presets belong to a user, so only a personal token reaches them; a project or team token is refused with
403 and the error code personal_api_token_required. A personal token reaches more than a token bound to one project, so grant it only the scopes a client needs, choose a short validity, and revoke it when it is no longer used. Tokens are valid for at most one year. Through the Admin API, a personal token is created with
POST /api/v1/admin/api-tokens and "resourceType": "user"; resourceId may be left out, the server fills in your own user id. A request naming another user is refused. Tokens can be issued, listed, and revoked through the Admin API. Rotating a token means issuing a new one with the same scopes and revoking the old one once the new one has been deployed. Every token listing carries
lastUsedAt, the time the token last authenticated a request (recorded at most once an hour, and null for a token that has never been used), which shows when the old token has stopped being used. Errors
Error responses share a common JSON shape across all APIs. The HTTP status is repeated in the body for convenience; error carries a short lower-case identifier (for example
unauthorized, bad_request or method_not_allowed) and message a human-readable explanation. Example error response
{
"status": 401,
"error": "unauthorized",
"message": "Invalid or expired API token."
}| Status | Meaning |
|---|---|
| 400 Bad Request | The request body or parameters did not validate. |
| 401 Unauthorized | The token is missing, invalid, revoked, or the owning user is locked. |
| 403 Forbidden | The token is valid but lacks the scope or permission for the requested operation. |
| 404 Not Found | The resource does not exist or is not visible to the caller. |
| 429 Too Many Requests | Rate limit exceeded for authentication or enumeration endpoints. |
| 500 Internal Server Error | Unexpected server-side failure. |