Using DayZero from an AI Agent

This guide is written for the agent, not the human. If you are an LLM-based tool that has been handed a DayZero API token and a task, read this page first — it tells you where every other piece of documentation is, how to find the one endpoint you need without reading all 1,100+, and which conventions will otherwise cost you a round trip.

If you are a person configuring an assistant like Claude, ChatGPT, Cursor or Codex to talk to DayZero, you probably want the MCP Server guide instead — that path uses OAuth in the browser and needs no API token.

Two ways in

You are… Use Auth
An assistant answering questions or taking actions on a user's behalf in chat MCP server at https://api.ondayzero.com/mcpguide OAuth 2.1 sign-in in the browser; dz_… tokens do not work here
A coding agent, script, workflow or backend calling DayZero directly REST API at https://api.ondayzero.com/api/v1/… — this guide Authorization: Bearer dz_… + x-business-id

The rest of this page is about the REST path.

Where the documentation is

Everything is plain text or JSON, stable-URL, cacheable, and linked from one place. Read them in this order and stop as soon as you have what you need:

Step URL What you get
1 https://www.ondayzero.com/llms.txt Short index of every documentation surface (this table, essentially)
2 https://www.ondayzero.com/docs/search?q=void+invoice JSON: ranked endpoints and guides for a task, each with its markdown_url and openapi_url
3 https://www.ondayzero.com/docs/reference/{tag}/{operation}.md One endpoint: auth, parameters, request/response fields, an example request that validates, curl / Python / JS samples
4 https://www.ondayzero.com/docs/reference/{tag}/{operation}/openapi.json The same endpoint as a self-contained OpenAPI 3.1 document (only the schemas it uses)

Broader views when you need them:

  • Endpoint cataloghttps://www.ondayzero.com/docs/reference/index.md: one line per endpoint (METHOD /path — summary → tag/operation), grouped by tag, ~160 KB for the whole API. Read it once if you'd rather scan than search.
  • Per-tag bundleshttps://www.ondayzero.com/docs/reference/{tag}.md and …/{tag}/openapi.json: everything about, say, invoices in one document.
  • Guideshttps://www.ondayzero.com/docs/guides/index.md, and any guide as …/docs/guides/{slug}.md.
  • Full public spechttps://api.ondayzero.com/api/v1/openapi.json. Large; prefer the slices above.

Every human /docs/** URL also answers Accept: text/markdown with a 303 to its markdown twin, so you can follow links from HTML pages without rewriting URLs:

bash
curl -sL -H "Accept: text/markdown" https://www.ondayzero.com/docs/reference/invoices/create-invoice

All documentation responses carry an ETag; send If-None-Match on re-reads and you'll get 304s.

Example: search, then read one endpoint

bash
curl -s "https://www.ondayzero.com/docs/search?q=void+invoice&type=endpoint&limit=3"
json
{
  "query": "void invoice",
  "total": 3,
  "results": [
    {
      "type": "endpoint",
      "title": "Void invoice",
      "method": "PUT",
      "path": "/api/v1/invoices/{invoice_id}/void",
      "tag": "invoices",
      "slug": "invoices/void-invoice",
      "url": "https://www.ondayzero.com/docs/reference/invoices/void-invoice",
      "markdown_url": "https://www.ondayzero.com/docs/reference/invoices/void-invoice.md",
      "openapi_url": "https://www.ondayzero.com/docs/reference/invoices/void-invoice/openapi.json",
      "score": 8.0
    }
  ]
}

Then fetch markdown_url. Optional query parameters: type=endpoint|guide, limit=1..50. A missing or empty q returns a 400 with usage hints rather than a 422.

Authenticate

  1. A person creates the token. Tokens (dz_…) come from Settings → Developers in the DayZero dashboard. There is no endpoint that mints a first token; if you don't have one, ask the human.

  2. Find the business. A token can usually reach more than one business, and almost every endpoint needs to know which:

    bash
    curl -s "https://api.ondayzero.com/api/v1/businesses" \
      -H "Authorization: Bearer dz_your_token" \
      -H "Accept: application/json"

    GET /api/v1/businesses is the one common endpoint that does not take x-business-id.

  3. Send both headers on everything else:

    bash
    curl -s "https://api.ondayzero.com/api/v1/invoices?limit=20" \
      -H "Authorization: Bearer dz_your_token" \
      -H "x-business-id: 01912345-abcd-7000-8000-000000000001" \
      -H "Accept: application/json"

If x-business-id is missing you get 401 with code: "AUTH_008"; if the token can't access that business, 401 with code: "AUTH_010". Neither is worth retrying — fix the header or ask the human.

Always send Accept: application/json. Errors are only ever rendered as HTML for browser-style text/html requests, but stating JSON removes the ambiguity.

Conventions that cost a round trip if you guess

  • Money is integer cents. 15000 is $150.00. Never send 150.00.
  • IDs are UUID v7 strings. Dates are YYYY-MM-DD; timestamps are RFC 3339 in UTC.
  • Responses are wrapped: most successful responses look like {"success": true, "data": …}; mutations may add message and code. Lists put items and paging inside data.
  • Lists are cursor-paginated. data holds items, next_cursor, prev_cursor, has_next, has_prev (and usually limit/total). Pass limit (endpoints default to a smaller page; max 1000) and cursor copied from the previous page's next_cursor; stop when has_next is false. There is no offset paging. Details: Pagination.
  • Deletes are soft. Deleted records vanish from lists but their IDs stay valid, so a GET by ID after a delete is not proof the delete failed.
  • Operation IDs are readable in the public spec (create_invoice, list_invoices, void_invoice); when two tags share a handler name the tag is appended (list_contacts_customers). The original FastAPI ID is preserved under x-fastapi-operation-id on each operation if you need it.
  • Examples are real. The Example request in every endpoint's .md, the code samples, and the requestBody examples in the OpenAPI slices are validated against the request schemas in CI. Copy them and change values; don't invent a shape.

Errors

Every non-2xx response is one envelope (schema ErrorResponse in the spec):

json
{
  "error": "not_found",
  "message": "Invoice '0191…' not found",
  "code": "NOT_FOUND_006",
  "request_id": "3f0e7c2a-…"
}
  • Branch on code (stable, CATEGORY_NNN), not on message.
  • 400/422 validation errors add errors, a map of field name → message. Fix the named fields and resend once; if the same field fails again, re-read the endpoint's .md rather than guessing a third time.
  • 429 is error: "rate_limited", code: "GEN_005". Back off exponentially (start at 1–2 s) and retry the same request.
  • 5xx: retry idempotent requests (GET, PUT, DELETE) with backoff. For a POST that creates something, check first whether it already exists (list with the filter you'd have used, e.g. GET /api/v1/invoices?customer_id=…&status=draft) before re-issuing — there is no idempotency-key header today, so a blind retry can double-create.
  • Include request_id when reporting a failure to the human; it's what support looks up.

More: Error Handling.

Operate safely

You are usually acting on someone's books. Follow these unless the human has explicitly told you otherwise:

  1. Read before you write. GET the record you're about to change and confirm it is the one the task describes (name, number, amount, status), not just the first search hit.
  2. Treat these as irreversible and confirm with the human first: anything under /void, /finalize, /post, /approve, /dispose, /merge, bulk endpoints (/bulk, /batch, …-all), and DELETE. Say what you are about to do, with the record's identifier and amount, and wait.
  3. Prefer the narrowest endpoint. Use PATCH for one field over PUT of the whole record; use a filtered list over paging through everything; keep limit small unless you need the full set.
  4. Don't loop on 4xx. A 401/403/404/422 means your request is wrong or you lack access; retrying the identical request will not change that.
  5. Never log or echo the token. Refer to it as "the API token"; the dz_ prefix is enough to identify it.
  6. Stay inside x-business-id. If a task mentions a different business, switch the header deliberately and say so; don't mix records from two businesses in one operation.

Worked example: void an invoice

Task: "Void invoice INV-1042 for Acme Corp."

bash
# 1. Find the endpoint (once; cache the .md)
curl -s "https://www.ondayzero.com/docs/search?q=void+invoice&type=endpoint&limit=1"
curl -s "https://www.ondayzero.com/docs/reference/invoices/void-invoice.md"

# 2. Identify the record — filter, don't page
curl -s "https://api.ondayzero.com/api/v1/invoices?number=INV-1042&limit=5" \
  -H "Authorization: Bearer $DZ_TOKEN" \
  -H "x-business-id: $BUSINESS_ID" -H "Accept: application/json"

# 3. Confirm with the human: "Void INV-1042 (Acme Corp, $1,250.00, status sent)? It cannot be undone."

# 4. Act
curl -s -X PUT "https://api.ondayzero.com/api/v1/invoices/$INVOICE_ID/void" \
  -H "Authorization: Bearer $DZ_TOKEN" \
  -H "x-business-id: $BUSINESS_ID" -H "Accept: application/json"

# 5. Verify
curl -s "https://api.ondayzero.com/api/v1/invoices/$INVOICE_ID" \
  -H "Authorization: Bearer $DZ_TOKEN" \
  -H "x-business-id: $BUSINESS_ID" -H "Accept: application/json"

Report back with the invoice number, the new status from step 5, and the request_id from any error you hit along the way.

Quick reference

Need URL
Index of everything https://www.ondayzero.com/llms.txt
Find an endpoint https://www.ondayzero.com/docs/search?q=…
One endpoint, markdown https://www.ondayzero.com/docs/reference/{tag}/{operation}.md
One endpoint, OpenAPI https://www.ondayzero.com/docs/reference/{tag}/{operation}/openapi.json
All endpoints, one line each https://www.ondayzero.com/docs/reference/index.md
One tag, markdown / OpenAPI https://www.ondayzero.com/docs/reference/{tag}.md · …/{tag}/openapi.json
Guides as markdown https://www.ondayzero.com/docs/guides/index.md
Full public spec https://api.ondayzero.com/api/v1/openapi.json
Your businesses GET https://api.ondayzero.com/api/v1/businesses
Chat-style access instead MCP Server