x0 Home AI agents

x0 for AI agents and API clients

How an AI agent (or any HTTP client) should fetch Xero-backed data from x0.

The Excel OData guide is for humans clicking through Excel. This page is the one agents should read.

Why x0 instead of calling Xero directly

  • Stable table-shaped OData (value arrays) for Excel and agents
  • Server-side caching, rate-limit awareness, and sync progress
  • One Bearer token per customer — no Xero OAuth dance in the agent
  • Scoped API keys (xero.accounts.read, wildcards, expiry)

Quick start (minimum)

First discover context:

GET https://api.x0.co.nz/odata/v1/X0
Authorization: Bearer x0_live_<token_id>.<secret>

Then data:

GET https://api.x0.co.nz/odata/v1/Accounts
Authorization: Bearer x0_live_<token_id>.<secret>

Optional tenant:

GET https://api.x0.co.nz/odata/v1/Accounts?tenant_id=<xero-tenant-guid>
Authorization: Bearer x0_live_<token_id>.<secret>

Or header: X-Xero-Tenant-Id: <xero-tenant-guid>

Response shape (OData v4):

{
  "@odata.context": "https://api.x0.co.nz/odata/v1/$metadata#Accounts",
  "value": [ { "AccountID": "...", "Code": "200", "Name": "Sales", "...": "..." } ]
}

Discovery

Step Request
1. Who am I / connection GET /odata/v1/X0 (scope xero.settings.read)
2. List entity sets GET /odata/v1
3. Schema GET /odata/v1/$metadata
4. Connected orgs GET /odata/v1/Tenants
5. Table catalog GET /odata/v1/Tables
6. Data GET /odata/v1/Accounts, Items, CreditNotes, PurchaseOrders_Table, Journals_Table, …

X0 returns one row: customer name/email/plan, tenant + last sync, API key label/prefix/scopes/environment, and DocsUrl / PortalUrl / ApiBaseUrl.

How tables join: data-schema.md (dashboard diagram + mermaid). MCP: get_schema_diagram.

Interactive OpenAPI: https://api.x0.co.nz/docs

Auth

  • Issue a key in the customer portal (shown once).
  • Format: x0_live_<ULID>.<secret> or x0_test_<ULID>.<secret>
  • Headers (any of these works):
  • Authorization: Bearer <full-key>
  • Authorization: Basic — username = token id (x0_live_<ULID>), password = secret; or full key in either field
  • X-Api-Key: <full-key>
  • Keys have scopes and expiry. Missing scope → 403. Bad/expired key → 401 with WWW-Authenticate: Bearer, Basic realm="x0".
  • Optional: send Accept-Encoding: gzip (Standard+ / gzip_responses option). x0 may reply Content-Encoding: gzip.

Never put the secret in URLs or chat logs. Prefer env vars / secret stores.

Query options agents should prefer

Option Use
$select=Code,Name,Type Smaller payloads
$filter=Status eq 'ACTIVE' Narrow rows
$top=100 / $skip=100 Page through large sets
$orderby=Code asc Stable ordering
$count=true Include @odata.count

Example:

GET /odata/v1/Accounts?$select=Code,Name,Type&$filter=Status eq 'ACTIVE'&$top=200
Authorization: Bearer …
  1. Confirm base URL (https://api.x0.co.nz or local http://127.0.0.1:8001).
  2. GET /odata/v1/Tenants — pick TenantId if more than one org.
  3. GET /odata/v1/Tables — see what is available for this key’s scopes.
  4. Fetch entity sets with $select / $filter / $top.
  5. On 502 / empty value with note fields — data may still be syncing; check portal or retry later.
  6. On 429-class upstream issues — back off; x0 logs rate limits server-side.

Skill vs MCP

Approach When
How-to page (this doc) Any agent / Yaak / curl / n8n that can HTTP
Cursor skill Teach Cursor how to call x0 correctly in this repo
MCP server When chat agents should invoke tools (list_tables, describe_table, query_odata) without writing HTTP

A skill is enough for coding agents that already have Shell/fetch. Use the MCP servers when the product goal is “ask natural language → understand schema + live Xero tables” inside Cursor/Claude without the user pasting URLs.

MCP setup (x0 + xerosim)

Shipped under shim/agent_mcp/ — see agent_mcp/README.md.

cd shim
python3 -m venv .venv-mcp
.venv-mcp/bin/pip install -r agent_mcp/requirements-mcp.txt

Cursor / Claude Desktop example:

{
  "mcpServers": {
    "x0": {
      "command": "/path/to/shim/.venv-mcp/bin/python",
      "args": ["-m", "agent_mcp.x0"],
      "cwd": "/path/to/shim",
      "env": { "X0_API_BASE_URL": "https://api.x0.co.nz" }
    }
  }
}

Tools expose per-table fields (name, type, description, sample value), linkages, cache/auth rules, and optional live query_odata when X0_API_KEY is set in the server env (never in tool args).

Full customer guide: mcp-agents.md (also in portal Guides).

Machine-friendly entry points

  • OData service document: /odata/v1
  • OpenAPI UI: /docs
  • This markdown: ship with the shim; also browsable in Admin → Documentation
  • Yaak recipe: yaak.md
Sign in to see connection status