Skip to main content
Save a customer, then reference it as a preset in calculations and transactions. Taxwire applies the exemption certificates on file for that buyer. Certificates are added in the Taxwire App and returned on the customer as a read-only exemption block. See Customer exemptions for how they affect tax. Customers synced by an integration (Stripe, QuickBooks, NetSuite, and so on) already exist in Taxwire. Reference them by the platform’s customer id instead of creating them here. If you do create one, match the integration’s source and source_id to avoid a duplicate.

Simple lifecycle

Use this when you manage customers one at a time, for example when a buyer signs up in your product.

1. Create the customer

Send a POST /customers with the only required field, source_id: your own identifier for the customer. Add name and email if you have them. source defaults to taxwire and source_account_id defaults to __default__, which is right for customers you manage directly through this API.
The response includes Taxwire’s stable id for the customer.
Response (201)
A customer is unique on source + source_account_id + source_id. Creating one that already exists returns 409, with meta.existing_customer_id and meta.existing_customer_path pointing at the existing record. If the customer was deleted in the Taxwire app, meta.deleted is true and there is no path.

2. Reference the customer as a preset in a calculation

Pass the customer’s source_id and source in customer.preset on a line item. Taxwire looks up the customer and derives the customer’s tax attributes from its active exemption certificates.
Line item using a customer preset
preset.id is your source_id (CUS-1042), not the cust_... id Taxwire returns. If your organization has more than one account on the source platform, also pass preset.source_account_id. Without it, an id held in several accounts matches no customer and the line is taxed.
Two settings on your organization decide whether that certificate changes the tax:
  • Exemption management must be turned on. While it is off, certificates are ignored and the line is taxed. Contact support to enable it.
  • Certificate treatment decides whether the line’s product also has to carry the matching attribute, such as _RESALE. With “Certificate only”, the certificate alone exempts every sale in the states it covers. With “Certificate and product tax code”, only products that carry the attribute are exempt. Sending _RESALE on the line, as above, works in both modes.
See Customer exemptions for the full picture.

3. Update the customer when it changes

PATCH /customers/{customer_id} is a partial update. Omit a field, or send null, to keep its current value.
source_updated_at can’t be cleared or moved to an older date. Omit it if you don’t track source-system change timestamps.

4. Check what exempts the customer

GET /customers/{customer_id} returns the customer with a read-only exemption block listing the approved certificates on file, one row per jurisdiction.
Response (excerpt)
exemption is a snapshot of what is on file, not a promise that a sale is exempt. To get the tax for a sale, run a calculation. See Reading a customer’s exemptions for what each field means, including renewed and expired certificates.

Bulk sync lifecycle

Use this when you keep customers in your own system and want Taxwire to mirror them, for example an initial import or a nightly sync.

1. Upsert in batches

POST /customers/batch takes up to 1000 customers, and up to 5 MB, in a data array. Each is matched on source + source_account_id + source_id: an existing customer is updated and a new one is created, so you can safely send the same request again. This example updates one customer, creates one, and includes a third with no source_id so you can see what a failure looks like.
If the same customer appears more than once in one request, every copy fails. De-duplicate on source + source_account_id + source_id before you send. A request over the limits returns 413.

2. Read the per-customer results

Each customer succeeds or fails on its own, and the request returns 200 even when some customers fail. data is in the same order as the request, and summary counts each outcome.
Response (200, excerpt)

3. Walk the full list when you need to reconcile

GET /customers returns customers newest first, with no filters. Page with limit and starting_after, passing the last customer’s id, until has_more is false.
There is no way to look a customer up by source_id yet. To find one, page through the whole list and filter on your side, or keep the id from the create or batch response.

Deleting a customer

DELETE /customers/{customer_id} removes the customer and its exemption certificates, and returns 204 with no body. It also returns 204 when the customer was already deleted, so a retry is safe. A deleted customer keeps its source, source_account_id and source_id, so creating it again returns 409 with meta.deleted: true, and a batch upsert reports it as deleted. Restore it in the Taxwire App instead.

Key concepts


Putting it all together

Complete nightly sync of customers from your own system. The script:
  1. Splits your customers into batches of up to 1000 (de-duplicate them first).
  2. Upserts each batch with POST /customers/batch, sending source_updated_at so replays and out-of-order runs are safe.
  3. Retries on 429 and 5xx, honoring Retry-After.
  4. Collects per-customer failures instead of stopping, and prints a summary.