Two token types
| Token | Used by | Used on |
|---|---|---|
af_bot_<32hex> | bot dev’s server | every /api/v1/* call from the bot |
af_session=<jwt> | AgentFlow web user | provisioning endpoint POST /api/v1/bots |
Bot token header
Every API call from your bot’s server includes:@bot_<slug>:agentflow.website). The platform looks up the bot, finds the stored Matrix access_token, and proxies the call upstream — your code never sees the Matrix token directly.
Why this design
- One leaked Matrix access_token = full account compromise. With the wrapper, a leaked bot token still only grants access to one bot, and you can rotate it without re-registering a Matrix user.
- Same shape as Telegram bot tokens — devs know what to do.
- Lets the platform enforce rate limits, billing, and webhook delivery before reaching Matrix.
Token format
POST /api/v1/bots). They’re stored hashed (sha256) — the platform itself cannot recover a token after issue.
Lifecycle
| Action | Endpoint |
|---|---|
| Create bot + first token | POST /api/v1/bots |
| Show token to dev | response body of create (one time) |
| Rotate token | POST /api/v1/bots/:slug/rotate (v0.2 — planned) |
| Revoke / delete | DELETE /api/v1/bots/:slug (v0.2 — planned) |
| Whoami | GET /api/v1/bots/me |
Session cookie
The provisioning endpointPOST /api/v1/bots accepts a session cookie because creating a bot is a user-level action — a person owns the bot, not a bot. The cookie is the same af_session JWT that authenticates the AgentFlow web app, set on the .agentflow.website parent domain.
For curl / CI:
Errors
| Status | Body error | Meaning |
|---|---|---|
| 401 | missing_bot_token | X-AgentFlow-Bot-Token header absent |
| 401 | invalid_bot_token_shape | not af_bot_<64hex> |
| 401 | unknown_bot_token | hash doesn’t match any row |
| 401 | unauthenticated | provisioning endpoint hit without session |
| 401 | invalid_session | session JWT malformed |
| 403 | reserved_slug | tried to claim af-* slug as non-admin |
| 429 | rate_limited | exceeded rate_limit_qps for your tier |
Rate limits
Per-bot limits, refreshed every second:| Tier | qps |
|---|---|
| free (default) | 30 |
| pro (planned) | 200 |
| enterprise | unlimited |
Retry-After: 1 and error: rate_limited. Back off and retry.
Security best practices
- Never log the bot token (
af_bot_*) in plaintext. CI secrets / vaults only. - Use HMAC-signed webhooks. Verify
X-AgentFlow-Signature(HMAC-SHA256 of body using the secret you supplied atsetWebhook). - Don’t expose your
af_sessionJWT — it grants user-level access to all your bots. - Rotate tokens if a teammate leaves or a leak is suspected.