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 aPOST /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.
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’ssource_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
- 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_RESALEon the line, as above, works in both modes.
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.
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.
2. Read the per-customer results
Each customer succeeds or fails on its own, and the request returns200 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:- Splits your customers into batches of up to 1000 (de-duplicate them first).
- Upserts each batch with
POST /customers/batch, sendingsource_updated_atso replays and out-of-order runs are safe. - Retries on
429and5xx, honoringRetry-After. - Collects per-customer failures instead of stopping, and prints a summary.