Current account
curl https://api.webot.agency/api/v1/me \ -H "Authorization: Bearer $WEBOT_API_KEY"
Authenticated API docs
Dashboard-facing guidance for account owners and admins using the implemented API key, usage, entitlement, job, and file routes.
Create API keys from a dashboard owner/admin session. The platform returns plaintext_key one time, then list and revoke responses expose metadata only. Never log, persist in job payloads, or screenshot real key values.
curl https://api.webot.agency/api/v1/api-keys \
-X POST \
-H "Authorization: Bearer $SUPABASE_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "name": "Fulfillment client" }'
{
"api_key": {
"id": "key_example",
"name": "Fulfillment client",
"prefix": "a1b2c3d4e5f6",
"scopes": ["api:read", "api:write"],
"status": "active"
},
"plaintext_key": "wbot_a1b2c3d4e5f6_exampleTokenForOneTimeDisplay"
}curl https://api.webot.agency/api/v1/me \ -H "Authorization: Bearer $WEBOT_API_KEY"
curl https://api.webot.agency/api/v1/entitlements \ -H "Authorization: Bearer $WEBOT_API_KEY"
curl "https://api.webot.agency/api/v1/usage?job_id=job_example" \ -H "Authorization: Bearer $WEBOT_API_KEY"
Usage is server-written. Clients can read current-period totals, remaining quota, service-family buckets, entitlement buckets, billing-period buckets, API-key buckets, and recent safe usage events.
Remaining capacity is calculated from verified active plans created by signed Stripe webhooks. Display-only checkout return parameters do not change quota.
{
"usage": {
"period": {
"start": "2026-06-01T00:00:00.000Z",
"end": "2026-07-01T00:00:00.000Z"
},
"totals": {
"quantity": 12,
"quota": 500,
"remaining": 488,
"unit": "job"
},
"summaries": {
"by_entitlement": [
{ "key": "api_agent_top", "quantity": 12, "quota": 500, "remaining": 488 }
],
"by_service_family": [
{ "key": "create_polish", "quantity": 7 }
],
"by_api_key": [
{ "api_key_id": "key_example", "quantity": 12 }
]
},
"recent_events": []
}
}Presign requests create short-lived upload contracts for account-owned work. They do not create durable public file URLs.
curl https://api.webot.agency/api/v1/files/presign \
-X POST \
-H "Authorization: Bearer $WEBOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"purpose": "job_source",
"content_type": "application/pdf",
"size_bytes": 1048576,
"file_name": "source-notes.pdf",
"job_id": "job_example",
"retention_days": 7
}'Reject responses are designed for customer and agent decisions. Use the code and action; do not parse message text.
{
"error": {
"code": "quota_exceeded",
"message": "This account has reached its current plan limit.",
"action": "Wait for the next billing period or choose a plan with more capacity.",
"request_id": "req_example"
}
}Rate-limit rejects also include a standard Retry-After header. The JSON body mirrors it as retry_after_seconds and includes retry_at so agents can schedule a retry without parsing message text.
HTTP/1.1 429 Too Many Requests
Retry-After: 60
{
"error": {
"code": "rate_limit_exceeded",
"message": "This request is over the current rate limit.",
"action": "Wait briefly before trying again, or reduce request frequency.",
"request_id": "req_example",
"retry_after_seconds": 60,
"retry_at": "2026-06-28T14:01:00.000Z"
}
}invalid_request: request body or parameter shape is not usable.unsupported_service: service family/type is not in the catalog.entitlement_required: account does not have active access for the request.quota_exceeded: account has no remaining quota for the current period.rate_limit_exceeded: caller exceeded the current route/key/account limit; use Retry-After or retry_after_seconds before retrying.concurrency_limit_exceeded: account already has the maximum active jobs for its tier.job_not_found: job is missing or not owned by the account.job_not_cancelable: job has reached a status that cannot be canceled.revision_unavailable: revision is not available for the job.unsupported_file: upload content type or purpose is not supported.file_too_large: file exceeds the current upload limit.unsafe_request: request cannot be accepted safely.