x0 Home Contacts & Invoices write

Contacts & Invoices write API

Create / update / archive / delete Contacts and draft Invoices via x0 → Xero Accounting API. Read paths remain OData / cache tables.

Scopes

Scope Use
xero.contacts.write PUT/POST/DELETE /v1/contacts… and OData Contacts writes
xero.invoices.write PUT/POST/DELETE /v1/invoices… and OData Invoices writes

Demo customers: writes rejected (CustomerAccessDenied). Successful mutations mark contacts / invoices (+ *_table) cache dirty.

Upstream Xero OAuth on the connected app still needs accounting.contacts / accounting.transactions (not only the x0 API-key scopes).

REST routes (primary)

Contacts

Method Path Behaviour
POST /v1/contacts/preflight {action, contact_id?, payload?}
PUT /v1/contacts Create — require Name
POST /v1/contacts/{contact_id} Update (field allow-list)
POST /v1/contacts/{contact_id}/archive ContactStatus=ARCHIVED
DELETE /v1/contacts/{contact_id} Delete after rules

Invoices (draft-first)

Method Path Behaviour
POST /v1/invoices/preflight {action, invoice_id?, payload?}
PUT /v1/invoices Create — require Type, Contact, ≥1 LineItems; default Status=DRAFT
POST /v1/invoices/{invoice_id} Update draft fields
DELETE /v1/invoices/{invoice_id} Delete drafts only

Not in v1: payment, allocation — use credit-notes-payments-write.md for authorise/void/payments.

x0 REST uses PUT for create (Accounts-style). Upstream Xero: Contacts use PUT create / POST update; Invoices use POST for both create and update.

OData aliases

Method Path Maps to
POST /odata/v1/Contacts create
PATCH / PUT /odata/v1/Contacts/{id} update
DELETE /odata/v1/Contacts/{id} delete
Same for Invoices

Require matching xero.*.write scopes. Line tables (Contacts_Table, Invoices_Table) return 405. No $batch / deep insert this wave.

Preflight / write rules

evaluate_write_rules seeds cover Contacts and Invoices required fields. Call /v1/.../preflight before delete/archive.

Implementation

Piece Where
Shared helpers portal/services/write_common.py
Contacts portal/services/contacts_write.py · api/routers/contacts.py
Invoices portal/services/invoices_write.py · api/routers/invoices.py
OData api/odata/writes.py
Accounts (existing) accounts-write.md

Simulator

xerosim accepts PUT/POST/DELETE for Contacts and Invoices only (upsert SimResource). Other resources stay 403.

Follow-ups

Related: odata.md · accounts-write.md · items-purchase-orders-write.md · xero-simulator.md

Sign in to see connection status