Manage API keys
Generate, rotate and revoke the x3d_live_ key that authenticates the print API — from the browser, because these endpoints use your session rather than a key.
One account holds one API key. This page covers the three calls behind the Developer API key panel on /profile: read the key's status, generate or rotate it, and revoke it. All three are authenticated by your signed-in browser session — an API key cannot manage API keys.
Read the key status#
/api/account/api-keySigned inWhether the account has a key, and what it looks like.
{
"hasKey": true,
"prefix": "x3d_live_ab12cd…",
"createdAt": "2026-09-09T12:00:00.000Z"
}hasKeybooleanoptional- true when a key exists on the account.
prefixstring | nulloptional- The non-secret display prefix: x3d_live_ plus the first six characters of the secret and an ellipsis. Enough to recognise which key is deployed where, not enough to use. null when there is no key.
createdAtstring | nulloptional- ISO 8601 timestamp of when the current key was issued. null when there is no key.
Generate or rotate#
/api/account/api-keySigned inIssue a new key, replacing any existing one. No request body.
const res = await fetch("/api/account/api-key", {
method: "POST",
credentials: "include",
});
const data = await res.json();
if (res.status === 402) throw new Error(data.error); // code: "CARD_REQUIRED"
// The only time you will ever see this value.
console.log(data.apiKey);{
"apiKey": "x3d_live_ab12cd34ef56...",
"prefix": "x3d_live_ab12cd…",
"createdAt": "2026-09-09T12:00:00.000Z"
}apiKeystringrequired- The full secret: x3d_live_ followed by 48 lowercase hex characters, 57 characters in total. Returned exactly once and never recoverable. Copy it into a secret store or environment variable before you close the tab.
prefixstringrequired- The display prefix for the key just issued. Safe to log and to show in a UI.
createdAtstringrequired- ISO 8601 timestamp of issue.
The card-on-file prerequisite#
A key can only be issued to an account with a saved payment method, because API orders bill automatically. Add one from /profile, then generate. If payments are not configured in a deployment at all, the check is skipped and a key is issued without a card — self-hosted setups will see that behaviour, x3dstudios.com will not.
{
"error": "Add a card on file first — API print orders are billed automatically to your saved card.",
"code": "CARD_REQUIRED"
}Revoke#
/api/account/api-keySigned inDelete the key. No request body.
This clears the stored hash, the prefix and the created date. Every request using that key gets 401 from then on. Orders already submitted are unaffected — they are paid work at the farm, and revoking a key does not cancel them, but you also lose the ability to poll them until you generate a new key.
{ "ok": true }| Method | Status | Body |
|---|---|---|
| GET | 200 | { hasKey, prefix, createdAt } |
| GET / POST / DELETE | 401 | { "error": "Unauthorized" } |
| POST | 200 | { apiKey, prefix, createdAt } |
| POST | 402 | { error, code: "CARD_REQUIRED" } |
| DELETE | 200 | { "ok": true } |
Handling the key#
- Store it as an environment variable or in a secret manager. It authorises real charges to your card.
- Keep it server-side. Anything in browser JavaScript, a mobile binary or a public repository is public.
- Log the prefix, never the key. That is what the prefix is for.
- Revoke immediately if it leaks — a revoked key cannot be used, and generating a new one revokes the old one anyway.
- The prefix is not a password hint: it is nine fixed characters plus six of the secret, and it is safe to paste into a support ticket.