Errors
The error shape and the status codes the API returns.
Failures from the API's own handlers share one shape — a single message
field, safe to show to the user:
{ "message": "alias limit reached for your plan" }Status codes
| Status | Meaning | Typical cause |
|---|---|---|
400 | Invalid input | Body is missing or not JSON; a required field is absent or malformed; no field given in a partial update. |
401 | Not authenticated | Token missing, malformed, or expired. Returned by API Gateway, before any handler runs. |
404 | Not found | The id does not resolve within the caller's account, or a verification token is invalid or expired. Also used when an id belongs to someone else — see Tenancy model. |
409 | Conflict | Duplicate address, quota exhausted, recipient unverified or inactive, or a state rule (last destination, already verified). |
500 | Server error | Unexpected failure. The message is generic; details are in the API's CloudWatch access logs. |
403 exists in the taxonomy for ownership failures, but in practice ownership
failures surface as 404.
Messages are stable enough to branch on
Handlers return fixed messages for the cases clients need to distinguish —
for example alias limit reached for your plan for a quota, versus
alias address already exists for a duplicate. Treat them as UX copy, not as
an API contract: branch on the status code and use the message to explain.
Validation happens in layers
Malformed request bodies are rejected by API Gateway's request validator
before the Lambda runs, and the same rules are re-checked in code. Both
produce the {"message": ...} shape, but a 400 from the validator may arrive
without the API's usual response headers.