Errors
Akol returns standard HTTP status codes and a consistent JSON envelope for errors. Always inspect both the status code and the response body.
Error envelope
{
"success": false,
"error": "Human-readable summary",
"errors": [
{ "field": "email", "message": "Invalid format" }
]
}errors is only present for 422 Unprocessable Entity responses (Zod
validation failures). For everything else, just use error.
Status codes
| Status | Meaning | Common causes |
|---|---|---|
200 | OK | Successful GET / PATCH |
201 | Created | Successful POST that creates a resource |
400 | Bad Request | Malformed JSON, missing required field outside Zod scope |
401 | Unauthenticated | No token, expired token, blacklisted token |
403 | Forbidden | Token valid but user lacks permission. Also returned when email is not verified yet (/auth/login returns 403 with “verify your email”). |
404 | Not Found | Resource doesn’t exist OR belongs to another tenant (we don’t distinguish — prevents enumeration). |
409 | Conflict | Duplicate email on /auth/register, conflicting state (e.g. campaign already running). |
422 | Unprocessable Entity | Body shape valid, but field validation failed. Inspect errors[] for details. |
423 | Locked | Account temporarily locked (login lockout). |
429 | Too Many Requests | Rate limit hit. Honor Retry-After. |
500 | Server Error | Unexpected — please report at support@akol.ai with the X-Request-Id header. |
503 | Service Unavailable | Dependent service (Stripe, Telnyx, etc.) is down. Usually transient. |
Common error messages
| Message | Status | Fix |
|---|---|---|
Invalid email or password | 401 | Wrong credentials. Don’t differentiate “no such user” vs “wrong password” — that’s intentional anti-enumeration. |
No bearer token provided | 401 | Add Authorization: Bearer ... header. |
Token has been revoked | 401 | The token was logged out or rotated. Re-authenticate. |
Please verify your email before logging in. | 403 | Check your inbox for the verification code from /auth/register. |
Account temporarily locked... | 423 | Wait 30 minutes or contact support. |
Too many failed login attempts | 429 | IP-level cooldown — wait 15 minutes. |
Invalid or expired reset code | 400 | Request a fresh code via /auth/forgot-password. |
Insufficient permissions | 403 | Your role doesn’t allow this action. Admin-only routes return 403 for non-admins. |
Idempotency
Mutating endpoints with side effects (booking, billing, sending) accept an
Idempotency-Key header. Submit the same key on retries and Akol will
return the original response without re-running the side effect:
POST /api/v1/calls
Authorization: Bearer ...
Idempotency-Key: 3a7f9b2c-...
{ ... }Keys are scoped per-account and remembered for 24 hours.
Debugging
Every response includes an X-Request-Id header. Include this when reporting
issues to support@akol.ai — it lets us locate the request in our logs in
seconds.
Last updated on