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:

bash
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:

bash
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_166 when 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_ips on create)
  • Revoke at any time from Settings → Developers, or with POST /api/v1/tokens/{token_id}/revoke (keeps the record, marks it revoked) or DELETE /api/v1/tokens/{token_id}
  • GET /api/v1/tokens lists your tokens (add include_revoked=true to 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:

  1. The client discovers auth requirements via /.well-known/oauth-protected-resource and /.well-known/oauth-authorization-server.
  2. It registers via dynamic client registration and opens a browser to /oauth2/authorize.
  3. You sign in and approve scopes on the consent page.
  4. The client exchanges the code at /oauth2/mcp/token for 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.