Get started
Authentication
API keys, scopes and headers for REST, plus the bearer JWT agent runtimes use for MCP — two credential types over a single identity and permission surface.
Authenticate REST calls with an API key in the X-API-Key header;
MCP agent runtimes use a bearer JWT. The two credential types sit over
one identity surface:
| Surface | Credential | Use case |
|---|---|---|
| REST | API key in X-API-Key |
Server-to-server integrations, scripts, CI |
| MCP | API key or session JWT, as Authorization: Bearer |
Agent runtimes — Claude Code, Cursor, custom |
| Dashboard | Session JWT + refresh + MFA | Humans in the browser |
API keys never grant admin-plane access. Billing, member invites, the credential vault, SSO/SCIM, and tenant settings stay JWT-only. A leaked key has a bounded blast radius — its minted scope set is the maximum reach.
API keys
Minting a key
From the dashboard:
- Sign in.
- Settings → API keys → New key.
- Name it (e.g.
production-erp-sync), pick scopes, copy the plaintext. - The plaintext is shown once. We store a one-way Argon2 hash and cannot recover it. If you lose it, revoke and re-mint.
Keys can also be minted programmatically with the api-keys API using a
user session JWT (an owner or admin whose email is verified) — the
plaintext is returned once. Unknown scopes are dropped against the
catalog below; if every requested scope is unknown the call returns
400 bad_request. API keys themselves cannot mint other keys — key
management requires a user JWT, so a compromised key can never create a
successor with broader scope.
Format
ak_live_dXt8q2Rb_9f3c…6Pk
└┬┘ └┬─┘ └──┬───┘ └───┬───┘
│ │ │ └─ secret (shown once, never stored in plaintext)
│ │ └──────────── public prefix (identifies the key in logs / lists)
│ └────────────────── mode: "live" or "test"
└────────────────────── key marker
Sending a key
API keys go in the X-API-Key header:
X-API-Key: ak_live_…
Authorization: Bearer …is reserved for user/MCP JWTs and is not a valid transport for an API key. Put API keys inX-API-Key.
If your key is scoped to a tenant with more than one organization, add
X-Org-Slug: <slug> to pin the org context.
Test vs live keys
| Prefix | Cost | Notes |
|---|---|---|
ak_test_… |
€0 | Sandbox keys. Refused in the production environment. |
ak_live_… |
Billed | Real traffic. |
Mint test keys for CI; mint live keys for production deployments.
Rotating a key
Rotate a key from the dashboard (or the api-keys API). Rotation keeps the
name, scopes, and expires_at intact and issues a fresh secret, returned
with its plaintext exactly once. Deploy the new key first, then rotate —
the old secret stops working immediately.
Revoking a key
Revoke a key from the dashboard. Revocation is immediate — requests with the
revoked key get 401 (invalid_api_key) from the next request onward.
A key also stops working, with the same 401, once the member who created
it is deactivated or leaves the organization, whether they are removed in
the dashboard or deprovisioned by your identity provider. Create integration
keys from an account that stays with the organization.
Listing keys and their scopes
View your keys in the dashboard. The list shows each active key's prefix,
name, scopes, and expires_at — never the plaintext. Key management is
a user-session (owner/admin) operation, so it isn't reachable with an API
key.
Scopes
Scopes follow <resource>:<action>. Mint the narrowest set you can:
a leaked parts:read key cannot trigger a billable calculation.
| Scope | Lets the holder |
|---|---|
parts:read |
List + read parts, revisions, and calculation results |
parts:write |
Create / update / delete parts and revisions, and create + run calculations (billable) |
uploads:read |
List + read existing uploads |
uploads:write |
Upload new CAD / drawings / RFQ text |
webhooks:read |
List webhook endpoints and deliveries |
webhooks:write |
Create / update / delete webhook endpoints |
Calculations authorize on
parts:read/parts:write. Finer- grainedparts:calculations:read/parts:calculations:writescopes exist in the catalog for forward compatibility, but calculation endpoints currently enforceparts:read(reads) andparts:write(create + run). To run a calculation, mint a key withparts:write.
Admin scopes don't exist. Plan changes, member invites, SSO/SCIM, credentials, OAuth provider config, the wallet and the audit log are human-dashboard-only. Machine keys cannot reach those surfaces by design. A scope is a restriction: a key holds exactly the scopes it was minted with, whoever created it.
Required headers
Every authenticated REST request includes:
X-API-Key: ak_live_…
Content-Type: application/json (or multipart/form-data for uploads)
Recommended:
Idempotency-Key: 9c5f-… (UUIDv4 from your client — see Idempotency)
X-Org-Slug: your-org-slug (required only for multi-org tenants)
We stamp X-API-Version and X-Request-ID on every response. Echo
the request id when filing a support ticket — we can pull the
structured log row in one query.
MCP authentication
The MCP server at https://api.arcnm.io/mcp-server/mcp is a bearer-token
protected resource and publishes
RFC 9728 protected-resource metadata
at /.well-known/oauth-protected-resource. The verifier accepts either
credential in the Authorization: Bearer … header:
- an ARCNM API key (
ak_live_…/ak_test_…) — the same key you use for REST, just carried as a bearer token (tried first); or - a tenant-scoped session access token (a JWT, audience-pinned to
/api/v1). Refresh tokens and tokens for other audiences are rejected.
Most agent setups use an API key — it's long-lived, revocable, and
scoped. Supply it to your agent runtime's client config — see
MCP for the exact claude mcp add / Cursor mcp.json
snippets. Note the MCP door only reads the Authorization: Bearer
header — there is no X-API-Key transport on the MCP server (that header
is REST-only).
Verifying webhook payloads server-side
ARCNM signs every webhook with the per-endpoint secret using the
Standard Webhooks scheme. Verify
the webhook-signature header before trusting a delivery — see
Webhooks → verifying signatures.
See also
- Errors —
401 invalid_api_key,403 insufficient_scope. - Rate limits — per-key and per-caller limits.
- Versioning — the
X-API-Versionresponse header. - MCP — bearer auth, tenant scoping, exposed tools.