anon_email
Guides

CORS

Calling the API from a browser, and the preflight behaviour.

The API is designed to be called from a browser as well as from scripts, so every authenticated resource answers CORS preflight:

OPTIONS /v1/aliases HTTP/1.1
Origin: https://app.example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: authorization,content-type
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Content-Type,Authorization
Access-Control-Allow-Methods: GET,POST,PUT,PATCH,DELETE,OPTIONS

Preflight is answered by the API itself (a mock integration), unauthenticated, because preflight requests never carry credentials.

The actual-response caveat

The Lambda handlers add Access-Control-Allow-Origin: * to every response they produce, so browser calls to Lambda-backed routes work.

The read-only routes that talk to DynamoDB directly (the GET endpoints under /aliases, /recipients, /account, and /subscription) return data through response templates that do not set CORS headers. Preflight for them still succeeds, so the browser sends the request and then blocks the response. A browser app should treat a network-level failure on those GETs — with an opaque error and no status code — as this case, and fall back to a Lambda-backed route or a same-origin proxy until the API sends the header on those responses too.

Notes

  • Preflight answers are cached by the browser; the headers above cover every method the API exposes.
  • The API is token-authenticated, so a permissive origin does not expose data: the Authorization header is what grants access, and it is never sent implicitly.
  • No cookies are used, so Access-Control-Allow-Credentials is not needed.

The built-in API playground on this site is disabled for the same reason: a static site cannot proxy requests, so it would rely on the caveat above.

On this page