Invoice customerMetadata on the public API
Summary
Invoices support custom metadata (key/value pairs) similar to contacts and products:
updateInvoiceMetadata— add or update an entry (max key length 40, value 500, up to 50 keys per invoice).deleteInvoiceMetadata— remove an entry by key. If the key does not exist, the mutation returns the invoice unchanged and does not return an error.Invoice.metadata— read entries as[MetadataEntry](key,value).invoices(filters: …)— optionalfilters.metadatawith a requiredkeyand an optionalvalue.
Filter behaviour matches contacts and products:
keyonly — returns invoices that have any value stored for that key.key+value— returns invoices where that key/value pair matches the same entry.
Values are matched after the same sanitisation rules as updateInvoiceMetadata.
This release is additive: existing invoice and invoices calls behave as before. filters is optional; omit it to keep current list behaviour (date range, pagination, and query options only).
Invoice mutation error codes: For updateInvoiceMetadata and deleteInvoiceMetadata, validation failures and missing invoices return HTTP 4xx responses with error populated in the GraphQL payload (for example 400 for validation problems and 404 when the invoice is not found), instead of surfacing only as GraphQL 500 errors. Validation errors include the invalid field name in messages such as invoiceId must be an ObjectId.
Metadata deletes are idempotent: deleteInvoiceMetadata only removes an entry when the key is present. If the key is absent, the mutation completes successfully, returns the invoice unchanged, and leaves error empty. Treat this as "the key is not present after the call" rather than as proof that an entry existed before the call.
Integration guidance
- Writing metadata: Call
updateInvoiceMetadatawithinvoiceId,key, andvalue. - Removing metadata: Call
deleteInvoiceMetadatawithinvoiceIdandkey. Missing keys are a successful no-op. - Reading metadata: Query
invoice(id:)orinvoicesand requestmetadata { key value }. - Listing by metadata: Use
invoices(filters: { metadata: { key: … } })to match any value for a key, or addvalue: …for an exact key/value pair. Combine withdateRange,pagination, andoptionsas today. - Discovery: Use
filters.metadatafor metadata-only lookup; do not assume other invoice fields cover custom keys.
Example
query InvoicesByExternalRef {
invoices(
dateRange: { start: "2026-01-01", end: "2026-12-31" }
pagination: { page: 1, pageSize: 50 }
filters: { metadata: { key: "external_ref", value: "INV-42" } }
) {
data {
id
invoiceNumber
metadata {
key
value
}
}
pageInfo {
page
pageSize
hasMore
}
}
}
Migration
No breaking schema changes for existing invoice / invoices clients. If you store partner references only in Semble invoice metadata today, you can now read them via metadata and find invoices with filters.metadata instead of maintaining a separate id map outside Semble.