All errors are returned as JSON with an error field:
"error": "Human-readable error message"
| Error | Status | Cause |
|---|
Missing or invalid parameters | 400 | Required query params missing |
Only S256 code_challenge_method is supported | 400 | Plain PKCE not allowed |
Invalid client_id | 400 | Project doesn’t exist |
Invalid redirect_uri | 400 | URI not in project’s allowlist |
| Error | Status | Cause |
|---|
Missing client_id | 400 | No client_id in body |
Rate limited | 429 | >20 requests in 60s for this client |
Invalid client_id | 400 | Project doesn’t exist |
Invalid client_secret | 401 | Wrong client secret |
Missing required fields | 400 | Missing code/verifier/redirect_uri |
Invalid or expired code | 400 | Auth code not found or expired |
redirect_uri mismatch | 400 | Doesn’t match stored URI |
project mismatch | 400 | Code issued for different project |
PKCE verification failed | 400 | Code verifier doesn’t match challenge |
Missing refresh_token | 400 | No refresh_token in body |
Invalid refresh token | 401 | Not found, wrong project, or revoked |
Refresh token expired | 401 | Past expiration date |
Account blocked | 403 | User blocked in this project |
PIN revoked | 403 | PIN has been revoked |
User not found | 401 | User deleted since token was issued |
Unsupported grant_type | 400 | Not authorization_code or refresh_token |
| Error | Status | Cause |
|---|
Missing token or client_id | 400 | Required fields missing |
| Error | Status | Cause |
|---|
Invalid credentials | 401 | Email not found or wrong password |
Account blocked | 403 | User is blocked in this project |
Not a member | 403 | User exists but not in this project |
Rate limited | 429 | 5+ attempts in 15 min from this IP |
| Error | Status | Cause |
|---|
Invalid PIN | 401 | PIN doesn’t match any active project PIN |
Rate limited | 429 | 5+ attempts in 15 min from this IP |
| Error | Status | Cause |
|---|
Email already registered | 409 | Email exists in the system |
Invalid password | 400 | Doesn’t meet requirements |
Registration closed | 403 | Project doesn’t allow new signups |
Rate limited | 429 | 3+ signups in 1 hour from this IP |
| Error | Status | Cause |
|---|
Rate limited | 429 | 3+ sends in 1 hour for this email |
Invalid or expired token | 400 | Token not in KV (expired/used) |
Registration closed | 403 | New user + closed registration |
| Error | Status | Cause |
|---|
Unauthorized | 401 | Missing or invalid Bearer token |
Forbidden | 403 | Valid token but not admin |
Not found | 404 | Resource doesn’t exist |
Max active PINs reached | 400 | 10 active PINs already exist |
Rate-limited responses include:
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
No Retry-After header is included. Clients should implement exponential backoff.