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-typeHTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Content-Type,Authorization
Access-Control-Allow-Methods: GET,POST,PUT,PATCH,DELETE,OPTIONSPreflight 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
Authorizationheader is what grants access, and it is never sent implicitly. - No cookies are used, so
Access-Control-Allow-Credentialsis 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.