Create invoices, quotes, and receipts, manage clients and items, and generate share links from one API. Every request is a plain HTTPS call with a JSON body — no SDK required.
https://api.xqivo.comcurl -X POST "https://api.xqivo.com/v1/documents" \
-H "Authorization: Bearer xq_live_<key>" \
-H "Content-Type: application/json" \
-d '{
"type": "receipt",
"client": { "name": "Acme Corp", "email": "billing@acme.com" },
"items": [
{ "description": "Design work", "quantity": 2, "unitPrice": 150 }
],
"include_share_link": true
}'Documents are auto-numbered across all types (INV-… / QUT-… / RPT-…) so no two documents ever share a number.
Every request carries your API key in the Authorization header:
Authorization: Bearer xq_live_<key>| Setting | What it does |
|---|---|
| Keep it server-side | Anyone holding your key can create documents and use your quota. Never put it in a mobile app, a browser page, or a public repository. |
| One key per environment | Hold several keys on one account, for example one live and one test. You can disable or delete any of them individually. |
| Revocation | Disabling or deleting a key takes effect immediately — the next request with that key is refused with 403. |
| Setting | What it does |
|---|---|
| Monthly document quota | A ceiling on documents created through this key — Free developers: 50/month, Pro: 1,000, Scale: 10,000. A key at its cap is refused with 429. Quotas are per key, not per account. |
| Rate limit | 120 requests per minute per key, 300 per minute per IP. Exceeding either returns 429. |
| Idempotency | Send an Idempotency-Key header on document creation to retry safely without duplicates. |
| Scopes | Keys currently get full access to documents, clients, and items. Finer scope control is coming. |
Check GET /v1/limits for your live quota and usage.
Test keys are a safe way to build. Use the sandbox-friendly flow below until you're ready to go live. Live keys are the only key type today; keep them secret and only use them when you intend to send real documents.
When your API sends SMS through /v1/notifications/send, the message shows a sender name. By default that is Xqivo. Pro/Scale developers can attach a custom sender name to a specific API key — approved by SasuSync before it goes live.
409 sender_active — wait for its result before changing it.SMS is metered from your prepaid credits (1 credit = 1 segment, ~160 chars). Top up packs on the Billing tab; when the balance hits zero, outbound SMS pauses until credits are added.
A successful call returns { data: ... }:
{
"data": {
"id": "7m6lbqA0nXyrVksUAnkW",
"type": "receipt",
"number": "RPT-0001",
"status": "issued",
"client": "Acme Corp",
"amount": 300,
"currency": "USD",
"shareLink": "https://xqivo.com/view-invoice?token=..."
}
}A failure returns the matching HTTP status and a message written for a person to read.
{
"error": {
"status": 401,
"code": "invalid_key",
"message": "API key not found or revoked."
}
}Every failure returns an HTTP status plus a JSON body: { error: { status, code, message } }. The message is written for a person to read; the code is for your code.
| HTTP | Code | Meaning | What to do |
|---|---|---|---|
| 400 | invalid_body / invalid_json | The request body isn't a JSON object or isn't valid JSON. | Send a valid JSON body with Content-Type: application/json. |
| 400 | invalid_type | type must be invoice, quote, or receipt. | Use one of the three document types. |
| 400 | invalid_status | The status doesn't belong to this document type. | Check the per-type status list (invoice: draft/sent/paid/overdue; quote: draft/sent/accepted/declined/converted; receipt: issued/void). |
| 401 | unauthorized | Missing or malformed Authorization header. | Send 'Authorization: Bearer xq_live_<key>'. |
| 401 | invalid_key | Key unknown or revoked. | Check the key in Developers — create a new one if needed. |
| 403 | key_disabled | This key was disabled in the portal. | Re-enable the key or create a new one. |
| 403 | ip_not_allowed | Request came from an IP outside the key's allowlist. | Add your server IP/CIDR to the key's IP allowlist. |
| 403 | insufficient_scope | Key lacks permission for this call. | Use a key with the needed scope. |
| 404 | not_found | The document/client/item id doesn't exist. | Check the id — GET /v1/documents to list valid ids. |
| 413 | payload_too_large | Request body exceeds 512 KB. | Smaller payloads only — paginate lists instead. |
| 429 | quota_exceeded | Monthly document cap for this key reached. | Raise the limit in the portal or wait for the next month. |
| 429 | rate_limit_exceeded | Too many requests (120/min per key, 300/min per IP). | Back off with exponential delay; retry later. |
| 500 | internal_error | Server-side fault. | Retry with backoff; if persistent, contact support. |
Retry rules: 429 and 5xx may be retried with backoff. 400/401/403/404 are permanent — fix the request instead. If a response comes back as an HTML error page (Cloudflare code 1101) rather than JSON, that is a backend fault: retry with backoff; it is prevented internally for known paths.
Get the brief — pick your language and download one markdown file. Hand it to Claude Code, Cursor, Copilot, or whatever you build with, and it has the whole integration — no docs to crawl, nothing to guess.
Get the brief
Which language is your agent writing?
Downloads as xqivo-curl.md — about cURL, ready to attach to a chat. The file is generated from this API and stamped with the correct base URL — no placeholder to find and replace.
What to say to your agent
Attach the file, then paste this. It names the parts agents most often skip.
I am integrating Xqivo for invoices, quotes, and receipts. The attached file (xqivo-curl.md) is the complete integration brief. Read all of it before writing any code. Requirements: 1. Use the reference client from the file rather than writing your own HTTP calls. 2. Read the API key from the XQIVO_API_KEY environment variable. Never put it in source. 3. Build against the sandbox endpoint first, and tell me the one line to change to go live. 4. Follow the retry rules exactly: only 429 and 5xx, with backoff. On a timeout, check the document status instead of resending. 5. Send an Idempotency-Key header on every document creation. 6. Do not invent clients, items, or document numbers. Ask me when a value is missing. When you are done, fill in the checklist at the end of the file and show me anything you could not tick.
What is in the file
| Section | Why it is there |
|---|---|
| Rules | The ten things that break integrations, written as instructions for a machine acting on them. |
| Document model | Three types, unique numbering, per-type statuses. An agent that does not know this writes documents with the wrong statuses. |
| Reference client | A complete working client in your language — retries, timeouts, and idempotency already correct. Agents given a snippet invent the rest, and invent it wrong. |
| Endpoints | Every call with its exact method and path. |
| Errors | Which codes to retry and which are permanent. This is the single most common source of duplicate documents. |
| Checklist | Tick-list your agent can work through and you can review against. |
Checking your agent's work
Whatever it writes, these four are worth reading yourself before you go live.
The last section of the file is a checklist. Ask your agent to fill it in and you have a review in thirty seconds instead of a code read.
Everything you can call, in one table.
/v1/documentsCreate an invoice, quote, or receipt. Auto-numbered and unique across all types. Returns id, number, and optionally a share link.
/v1/documentsList documents. Filters: ?type=invoice|quote|receipt, ?status=..., ?limit= (max 200).
/v1/documents/{id}Fetch one document by id (any type).
/v1/documents/{id}Update fields or status. Statuses must match the document type.
/v1/documents/{id}Delete a document.
/v1/documents/{id}/share-linkGenerate a public view link (view-invoice?token=...).
/v1/previewRender a live preview without creating a document — returns a view link + number. Uses no quota and saves nothing.
/v1/clientsCreate a client.
/v1/clientsList clients.
/v1/clients/{id}Update a client.
/v1/clients/{id}Delete a client.
/v1/itemsCreate a saved item.
/v1/itemsList saved items.
/v1/items/{id}Update an item.
/v1/items/{id}Delete an item.
/v1/templatesList the 8 templates.
/v1/limitsYour quota and usage.
Invoice
draft, sent, paid, overdue
Quote
draft, sent, accepted, declined, converted
Receipt
issued, void