Summary
Running xero@0.0.3 against a live AU org I hit several cases where the CLI accepts a write command, returns success, but silently drops fields that the Xero API supports. Most painfully, --file is essentially ignored on contacts create/update and quotes create — only flag-supplied scalar fields make it through. There are no warnings or validation errors.
Environment
- Package:
@xeroapi/xero-command-line v0.0.3
- Platform: Linux (WSL2 Ubuntu)
- Tenant: AU organisation, AUD, single Xero profile (PKCE OAuth flow worked fine)
Reproducer 1 — contacts create --file silently drops everything except name
cat > contact.json <<'JSON'
{
"name": "Acme Pty Ltd",
"firstName": "Jane",
"lastName": "Doe",
"emailAddress": "jane@acme.example",
"phones": [
{ "phoneType": "DEFAULT", "phoneNumber": "1234 5678", "phoneAreaCode": "02", "phoneCountryCode": "61" }
],
"addresses": [
{ "addressType": "STREET", "addressLine1": "1 Test St", "city": "Sydney", "region": "NSW", "postalCode": "2000", "country": "Australia" }
],
"contactPersons": [
{ "firstName": "Jane", "lastName": "Doe", "emailAddress": "jane@acme.example", "includeInEmails": true }
],
"isCustomer": true
}
JSON
xero contacts create --file contact.json --json
# => Error: Validation errors: name: Required
# (--name flag is required even when --file contains "name")
xero contacts create --name "Acme Pty Ltd" --file contact.json --json
# => 201 success, but the resulting contact has:
# - name: "Acme Pty Ltd" OK
# - firstName/lastName/emailAddress NOT PERSISTED
# - phones[].phoneNumber NOT PERSISTED
# - addresses[].addressLine1/city/... NOT PERSISTED
# - contactPersons NOT PERSISTED (empty [])
# - isCustomer NOT PERSISTED (false)
Tested key casings: lowercase camelCase (per Xero API spec) and PascalCase — both behave identically; neither persists nested fields.
Reproducer 2 — contacts update --phone is silently ignored
xero contacts update \
--contact-id <uuid> \
--name "Acme Pty Ltd" \
--phone "+61 2 1234 5678" \
--json
# => 200 success, response echoes the call but phones[].phoneNumber remains "" on read-back
Confirmed by reading the contact back via xero contacts list --search "Acme" — the phone never persists.
Reproducer 3 — quotes create --file silently ignored entirely
cat > quote.json <<'JSON'
{
"contact": {"contactID": "<uuid>"},
"date": "2026-05-14",
"lineAmountTypes": "EXCLUSIVE",
"title": "Test Quote",
"summary": "Summary text",
"terms": "Terms text",
"lineItems": [
{ "itemCode": "ITEM-A", "description": "Day 1", "quantity": 1, "unitAmount": 1100, "accountCode": "200", "taxType": "OUTPUT" },
{ "itemCode": "ITEM-B", "description": "Project", "quantity": 1, "unitAmount": 1000, "accountCode": "200", "taxType": "OUTPUT" }
]
}
JSON
xero quotes create --file quote.json --json
# => Error: Validation errors: contactId: Required
# (file contents not used for the contactId pre-validation)
xero quotes create --contact-id <uuid> --file quote.json --json
# => Error: Validation errors: contactId: Required (same — --file still not consulted)
xero quotes create --contact-id <uuid> --date 2026-05-14 --file quote.json --json
# => Error: Validation errors: contactId: Required
I was unable to find any flag combination that lets --file provide line items. The only way to create a quote via this CLI is single-line via flags. Combined with xero quotes update having no line-item flags at all, multi-line quotes appear to be impossible via the CLI.
Reproducer 4 — contacts update --file requires --contact-id flag even when file contains contactID
xero contacts update --file update.json --json
# => Error: Validation errors: contactId: Required
# even though update.json contains: { "contactID": "...", "name": "...", ... }
Expected behaviour
--file should be the canonical way to provide structured payloads (especially line items, multi-address contacts, etc.). The Xero REST API supports all these fields — the CLI is dropping them client-side.
- If a flag must duplicate a field that's already in
--file, the CLI should either (a) read it from the file as a fallback, or (b) document the constraint clearly in --help.
- Silent drops should be hard errors, not no-ops.
Suggested fixes (in priority order)
- Honour
--file payloads end-to-end on contacts create/update and quotes create — including nested phones[], addresses[], contactPersons[], lineItems[].
- Surface dropped fields as validation errors rather than silently ignoring them.
- Remove the
--name/--contact-id flag-must-be-present-even-with-file requirement, or make the file fields satisfy the pre-validation.
- Add line-item flags to
quotes update (--line-item-description, etc.) for parity with quotes create, or accept multi-line via --file on update.
- Document the current limitations in the README until the above is fixed — particularly the "single-line only" reality for quotes.
Impact
For typical small-business use (an AUD org, weekly proposal quotes, occasional new contacts), the CLI is currently only usable for reads. Every quote with multiple line items and every new client contact with a phone or address has to be done in the Xero UI instead.
Happy to test patches if helpful.
Summary
Running
xero@0.0.3against a live AU org I hit several cases where the CLI accepts a write command, returns success, but silently drops fields that the Xero API supports. Most painfully,--fileis essentially ignored oncontacts create/updateandquotes create— only flag-supplied scalar fields make it through. There are no warnings or validation errors.Environment
@xeroapi/xero-command-linev0.0.3Reproducer 1 —
contacts create --filesilently drops everything exceptnameTested key casings: lowercase
camelCase(per Xero API spec) andPascalCase— both behave identically; neither persists nested fields.Reproducer 2 —
contacts update --phoneis silently ignoredConfirmed by reading the contact back via
xero contacts list --search "Acme"— the phone never persists.Reproducer 3 —
quotes create --filesilently ignored entirelyI was unable to find any flag combination that lets
--fileprovide line items. The only way to create a quote via this CLI is single-line via flags. Combined withxero quotes updatehaving no line-item flags at all, multi-line quotes appear to be impossible via the CLI.Reproducer 4 —
contacts update --filerequires--contact-idflag even when file containscontactIDExpected behaviour
--fileshould be the canonical way to provide structured payloads (especially line items, multi-address contacts, etc.). The Xero REST API supports all these fields — the CLI is dropping them client-side.--file, the CLI should either (a) read it from the file as a fallback, or (b) document the constraint clearly in--help.Suggested fixes (in priority order)
--filepayloads end-to-end oncontacts create/updateandquotes create— including nestedphones[],addresses[],contactPersons[],lineItems[].--name/--contact-idflag-must-be-present-even-with-file requirement, or make the file fields satisfy the pre-validation.quotes update(--line-item-description, etc.) for parity withquotes create, or accept multi-line via--fileon update.Impact
For typical small-business use (an AUD org, weekly proposal quotes, occasional new contacts), the CLI is currently only usable for reads. Every quote with multiple line items and every new client contact with a phone or address has to be done in the Xero UI instead.
Happy to test patches if helpful.