Authentication
Every request to a /v1/* endpoint requires an API key, sent as a bearer token in the Authorization header:
curl -s https://astral-external-api-iksoi6t3nq-ue.a.run.app/v1/western/positions \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{"subject": {"datetime": "1990-05-15T14:30:00-04:00"}}'That is the entire auth model: one header on every request. There is no OAuth client-credentials flow — no token endpoint, no refresh step, no expiring access token to babysit — and no HTTP Basic, which dates from an era of credentials-in-code and offers nothing over a bearer key for server-to-server calls. A static key in a header is the settled answer for machine clients, and it is the only mechanism the API accepts.
The health probes (GET /health, GET /ready) are the exception: they are unauthenticated so load balancers and uptime checks can reach them without a secret.
Key format
Section titled “Key format”Keys are prefixed by environment:
| Prefix | Use |
|---|---|
ak_test_ |
Development and evaluation |
ak_live_ |
Production traffic |
The prefix is deliberately identifiable. You can tell at a glance — in a log line, a config diff, or a secret scanner rule — which environment a key belongs to, without ever exposing the rest of the key. If you log anything about a key, log only its prefix.
Getting a key
Section titled “Getting a key”The API is in early access. Keys are provisioned manually: request one through your early-access contact and you will receive an ak_test_ key (and an ak_live_ key when you are ready for production).
Once you have a key, export it in your shell — the examples across these docs assume $API_KEY is set:
export API_KEY=ak_test_your_key_hereWhat a 401 looks like
Section titled “What a 401 looks like”Authentication failures return 401 with an RFC 9457 problem body. Two codes cover the space.
No Authorization header at all yields auth.missing:
curl -s https://astral-external-api-iksoi6t3nq-ue.a.run.app/v1/western/positions \ -H "Content-Type: application/json" \ -d '{"subject": {"datetime": "2000-01-01T00:00:00Z"}}'A header carrying a key the API does not recognize — revoked, mistyped, or from the wrong environment — yields auth.invalid_key:
curl -s https://astral-external-api-iksoi6t3nq-ue.a.run.app/v1/western/positions \ -H "Authorization: Bearer ak_test_not_a_real_key" \ -H "Content-Type: application/json" \ -d '{"subject": {"datetime": "2000-01-01T00:00:00Z"}}'Branch on the code field, not the message text. See Errors for the full catalog.
Rotating keys
Section titled “Rotating keys”Each account can hold two active keys at once. That is the rotation contract: you never have to revoke a key before its replacement is live, so rotation is zero-downtime by construction.
- Request a second key. Both keys now authenticate.
- Deploy the new key to your services.
- Confirm traffic has moved (no more requests on the old key).
- Revoke the old key.
Rotate on your own schedule, and immediately if a key may have leaked. During early access, steps 1 and 4 go through your early-access contact.
Keeping keys secret
Section titled “Keeping keys secret”- Environment variables, not source code. Inject keys through your deployment environment or secret manager. A key in a repository is a key you should consider leaked — rotate it.
- Server-side only. Never ship a key in a browser bundle, a mobile app, or anything else that runs on hardware you don’t control; anyone can extract it. Route those clients through your own backend, which holds the key and calls the API.
- Don’t log full keys. The
ak_test_/ak_live_prefix is safe and useful in logs; the remainder is not.
API spec v0.1.0 · docs 0e4f5ec