Authentication
All DayZero API requests require a Bearer token in the Authorization header. Almost every endpoint also needs a business context header, because one token can usually reach more than one business.
Obtaining a Token
Generate an API token from your DayZero dashboard under Settings → Developers. A person creates every token in the dashboard: minting one requires two-factor authentication on the account, and the dashboard asks you to verify both factors when you generate it. There is no way to mint a token via the API — POST /api/v1/tokens refuses an API token with 403 AUTH_057, so a leaked key can never be used to create more keys.
Tokens look like dz_.... When you create one you choose:
| Option | Values | Notes |
|---|---|---|
| Name | text | Shown in the dashboard; use it to identify the integration |
| Expiration | 1–365 days (default 365) | Expired tokens return 401 |
| Scope | (omit), read_only, credit, credit:read, credit:payments |
Omit for full access. read_only blocks every mutating endpoint. credit / credit:read / credit:payments limit the token to the partner-credit API (all methods, GET only, or payment writes) |
| Allowed IPs | IPv4, IPv6, or CIDR | Optional. When set, requests from any other address return 403 AUTH_028. Set at minting; mint a new token to change the list |
The plaintext token is shown once, in the dashboard. Store it; it cannot be retrieved again. Create a separate token per integration so one can be revoked without breaking the others.
Making Authenticated Requests
Start by listing the businesses the token can access — this is the one common endpoint that does not need x-business-id:
curl "https://api.ondayzero.com/api/v1/businesses" \
-H "Authorization: Bearer dz_your_token_here" \
-H "Accept: application/json"Then send both headers on every other request:
curl "https://api.ondayzero.com/api/v1/invoices?limit=20" \
-H "Authorization: Bearer dz_your_token_here" \
-H "x-business-id: 01912345-abcd-7000-8000-000000000001" \
-H "Accept: application/json"| Header | Required | Description |
|---|---|---|
Authorization |
Yes | Bearer dz_... token |
x-business-id |
Yes, on business-scoped endpoints | UUID of the business. Operations that need it list it as a required header parameter in the API Reference |
Accept |
Recommended | application/json guarantees JSON error bodies (HTML error pages are only rendered for browser-style text/html requests) |
Content-Type |
On requests with a body | application/json |
Authentication errors
| Status | code |
Meaning |
|---|---|---|
401 |
AUTH_008 |
x-business-id header missing on an endpoint that requires it |
401 |
AUTH_010 |
The token cannot access that business |
401 |
other AUTH_* |
Token missing, malformed, expired or revoked |
403 |
— | Token is valid but its scope (e.g. read_only) does not permit the operation |
403 |
AUTH_028 |
Token is valid but the request did not come from an allowed IP |
403 |
AUTH_057 |
The operation needs a recent identity check an API token cannot provide (for example POST /api/v1/tokens). Do it in the dashboard while signed in |
None of these are worth retrying unchanged — fix the header or the token. See Error Handling for the response envelope.
Token Limits and Revocation
- Maximum 10 active tokens per user (
VALIDATION_166when exceeded) - Optional expiration between 1 and 365 days. Mint a replacement before expiry, swap the integration, then revoke the old token so nothing breaks mid-swap
- Optional IP allowlist per token (
allowed_ipson create) - Revoke at any time from Settings → Developers, or with
POST /api/v1/tokens/{token_id}/revoke(keeps the record, marks it revoked) orDELETE /api/v1/tokens/{token_id} GET /api/v1/tokenslists your tokens (addinclude_revoked=trueto see revoked ones); plaintext values are never returned
Partner OAuth 2.0
DayZero also runs an OAuth 2.0 token service for approved partner integrations: POST /api/v1/oauth2/token issues access + refresh tokens for a user, authenticated with an HMAC-SHA256 signature over a partner client_id, timestamp and nonce; POST /api/v1/oauth2/refresh renews them. It is provisioned per partner and is not self-serve — for your own integrations, use API tokens.
AI Assistants (MCP)
The DayZero MCP server (https://api.ondayzero.com/mcp) lets AI assistants like Claude, ChatGPT, Cursor and Codex interact with your accounting data through OAuth 2.1:
- The client discovers auth requirements via
/.well-known/oauth-protected-resourceand/.well-known/oauth-authorization-server. - It registers via dynamic client registration and opens a browser to
/oauth2/authorize. - You sign in and approve scopes on the consent page.
- The client exchanges the code at
/oauth2/mcp/tokenfor MCP-scoped tokens.
Important: MCP tokens and REST API tokens are separate credential types:
| Credential | Works on MCP | Works on REST API |
|---|---|---|
MCP OAuth token (type=mcp) |
✓ | ✗ |
REST API key (type=api, dz_…) |
✗ | ✓ |
SPA session token (type=access) |
✗ | ✓ |
Review and revoke MCP-connected clients with GET /api/v1/oauth/grants and DELETE /api/v1/oauth/grants/{grant_id}. REST API keys are revoked separately (see above).
See the MCP Server guide for setup, scopes, and troubleshooting, or Using DayZero from an AI Agent if you are building an agent against the REST API.