Docs/Authentication

Authentication

The Apertur API uses API keys for authentication. Keys are scoped to a project.

API key format

API keys follow the format:

aptr_{env}_{random}
PartValueDescription
aptrFixed prefixIdentifies an Apertur key
random32 hex charsCryptographically random secret

Example:

aptr_live_z9y8x7w6v5u4t3s2r1q0p9o8n7m6l5k4

Sending the API key

Include your API key in the Authorization header of every request using the Bearer scheme:

Authorization: Bearer aptr_live_xxxx

API keys must be kept secret. Never expose them in client-side JavaScript or commit them to version control. Use environment variables on your server.

curl https://api.apertur.ca/v1/upload-sessions \
  -H "Authorization: Bearer aptr_live_xxxx"

Request signing

For extra protection against tampering and replay, enable HMAC request signing on an API key from its settings in the dashboard. Once enabled, every request must also carry a valid signature — signing is an additional factor, so the Bearer key is still required on every request.

Send the signature and timestamp in the X-Aptr-Signature and X-Aptr-Timestamp headers, computed with HMAC-SHA256 over the timestamp, method, path, and body hash:

X-Aptr-Signature: sha256=<hex>
X-Aptr-Timestamp: <unix seconds>

Sign the full request path exactly as sent, including the /api/v1 prefix and any query string — for example /api/v1/upload-sessions. The method is uppercase, the timestamp is Unix seconds, and the body hash is the lowercase hex SHA-256 digest of the exact request body bytes (the digest of an empty string when there is no body).

HMAC_SHA256(signingSecret, `${timestamp}.${method}.${path}.${sha256hex(body)}`)

Requests older than 5 minutes are rejected.

Signing secret

Enable, rotate, or disable signing for a key from its settings in the dashboard. Enabling or rotating returns the signing secret once — copy it now, as it cannot be retrieved again.

SIGNING_SECRET=your-signing-secret   # shown once when you enable signing
TS=$(date +%s)
BODY='{"destination_ids":["dst_xxxx"]}'
BODY_HASH=$(printf '%s' "$BODY" | openssl dgst -sha256 | sed 's/^.* //')
SIG=$(printf '%s' "$TS.POST./api/v1/upload-sessions.$BODY_HASH" | openssl dgst -sha256 -hmac "$SIGNING_SECRET" | sed 's/^.* //')

curl https://api.aptr.ca/api/v1/upload-sessions \
  -H "Authorization: Bearer aptr_live_xxxxxxxx" \
  -H "X-Aptr-Timestamp: $TS" \
  -H "X-Aptr-Signature: sha256=$SIG" \
  -H "Content-Type: application/json" \
  -d "$BODY"

Rate limits

The API applies rate limits per API key. Limits are returned in response headers:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 97
X-RateLimit-Reset: 1711627200
EndpointLimitWindow
POST /api/v1/sessions100 requestsper minute
GET /api/v1/sessions300 requestsper minute
All other endpoints200 requestsper minute

When a rate limit is exceeded, the API returns 429 Too Many Requests. See the Errors page for details.

Authentication | API Documentation | Apertur