Authentication
Every endpoint on the Archivist is server-to-server. We use HTTP Bearer tokens — pass your key in the Authorization header on every request and you’re in. No cookies, no sessions, no CSRF surface to worry about.
A first request — curl
The fastest sanity check. Replace $ARCHIVIST_KEY with the key we issued you:
curl https://api.archivist.dev/bills \
-H "Authorization: Bearer $ARCHIVIST_KEY" \
-H "Accept: application/json"A 200 response with a populated items array means the key is good. A 401 means the header was missing or the key is wrong; a 403 means the key’s tier doesn’t have access to this endpoint.
From JavaScript
The fetch pattern is identical: set Authorization and call the endpoint. Use the built-in fetch — no SDK is required.
// Node 20+ (built-in fetch)
const res = await fetch('https://api.archivist.dev/bills', {
headers: {
Authorization: `Bearer ${process.env.ARCHIVIST_KEY}`,
Accept: 'application/json',
},
});
if (!res.ok) throw new Error(`Archivist ${res.status}`);
const { items, nextCursor } = await res.json();In a browser, the key should never reach the client. Pass the user’s session through your own backend and proxy the request.
// Browser-side fetch — load the key through your backend, never expose it.
const res = await fetch('/api/proxy/bills', {
headers: { Authorization: `Bearer ${userToken}` },
});
const data = await res.json();Key placement — what to do (and what not to)
Store the key in a backend-only secret manager or environment variable.
Rotate keys via the console; we accept up to two live keys per org.
Keep keys per-environment — a separate key for staging and production.
Never ship the key to the client bundle, a NEXT_PUBLIC_* env var, or a public repo.
Don’t hardcode the key in source — read it from env at runtime.
Don’t reuse the same key across organizations; scopes don’t overlap.
Errors & limits
Errors are JSON. Every error response carries a stable shape so clients can match on error without parsing prose:
{
"error": "Rate limit exceeded"
}| Status | When | What to do |
|---|---|---|
| 401 | Missing or invalid key The Authorization header was absent, malformed, or the key no longer exists. | Send `Authorization: Bearer <key>`; regenerate the key in the console if it was rotated out. |
| 403 | Scope or tier The key’s tier is not entitled to this endpoint family. | Check the key is for the tier that owns this surface; contact us to upgrade. |
| 429 | Rate limit You have exceeded the per-minute quota on your tier. | Honor the `Retry-After` header and consider upgrading; the paid beta tier is ~100 req/min. |
Prefer the diff webhook over polling. Webhook deliveries are HMAC-SHA256 signed with X-Archivist-Signature and are replayable by cursor — a missed delivery costs nothing.