Merchant Transactions

Calculate cart tax, record orders, manage exemption certificates, and issue refunds on behalf of your connected merchants.

This capability is in active development. Endpoints, request bodies, and responses may change before general availability. Contact support@zip.tax for early access.

Merchant Transactions extend Merchant Management with the day-to-day tax operations your merchants need: calculating tax on a cart, recording and updating orders, storing exemption certificates, and issuing refunds. Every operation runs against a single merchant you have already connected, so your platform can drive full transaction-level compliance without asking each merchant to integrate separately.

Before you begin

You need two things:

  1. A Ziptax API key. See Authentication for where to get one and how to send it.
  2. A connected merchant with compliance credentials on file. Create the merchant and store its credentials with the Merchant Management endpoints. A merchant without valid credentials returns 404 (credentials not found) on every transaction call.

Common conventions

All Merchant Transactions endpoints share the same shape.

ConventionDetail
MethodPOST for every endpoint, including reads and deletes. Parameters travel in the JSON body, not the URL.
Base URLhttps://api.zip-tax.com
AuthenticationX-API-KEY header only. Unlike the rate-lookup endpoints, these routes do not accept a ?key= query parameter.
Merchant targetEvery request body includes a merchantId (UUID) identifying the connected merchant to act on.
Content typeapplication/json on any request that sends a body.
EnvironmentRuns against the merchant’s Live environment by default. Set the X-ENV: TEST header to use the Test (sandbox) environment instead. See Test vs Live environments.

You never send compliance credentials in the request. Ziptax resolves them server-side from the connected merchant, so your integration only ever handles your own Ziptax API key.

Test vs Live environments

Each connected merchant has two environments: Live (production) and Test (sandbox). By default, every request runs against Live. To run a request against the merchant’s Test environment instead — for example, to validate your integration without creating real orders or affecting tax filings — set the X-ENV header to TEST.

cURL
$curl -X POST "https://api.zip-tax.com/merchant/cart/calculate" \
> -H "X-API-KEY: YOUR_API_KEY" \
> -H "X-ENV: TEST" \
> -H "Content-Type: application/json" \
> -d '{
> "merchantId": "6b3c1f5e-2a8d-4c9b-9f2e-1d7a4b6c8e10",
> "items": [
> {
> "customerId": "customer-453",
> "currency": { "currencyCode": "USD" },
> "origin": { "line1": "1 Market St", "city": "San Francisco", "state": "CA", "zip": "94105" },
> "destination": { "line1": "200 Spectrum Center Dr", "city": "Irvine", "state": "CA", "zip": "92618" },
> "lineItems": [ { "index": 0, "itemId": "sku-1001", "price": 49.99, "quantity": 2 } ]
> }
> ]
> }'

X-ENV accepts LIVE (the default) or TEST, and applies to every Merchant Transactions endpoint. Omit it to run against Live.

The Test environment is isolated from Live: carts, orders, refunds, and certificates created with X-ENV: TEST never affect Live data and are never filed. Make sure the merchant’s Test environment is configured before you use it.

Operations

The full set of endpoints:

OperationMethod & path
Calculate cart taxPOST /merchant/cart/calculate
Create order from cartPOST /merchant/order/create-from-cart
Create orderPOST /merchant/order/create
Get orderPOST /merchant/order/get
Update orderPOST /merchant/order/update
Create exemption certificatePOST /merchant/cert/create
Get exemption certificatePOST /merchant/cert/get
List exemption certificatesPOST /merchant/cert/list
Delete exemption certificatePOST /merchant/cert/delete
Create refundPOST /merchant/refund/create

Responses and errors

A successful call returns the requested resource as JSON (a cart calculation, an order, a certificate, or a refund).

Errors come in two shapes:

Ziptax-level errors are returned before the operation runs, when the request can’t be authorized or routed to a valid merchant. They use a simple envelope:

1{
2 "status": "error",
3 "message": "merchant not found"
4}

Operation-level errors are returned when the request reaches the compliance service but fails validation or processing. They carry more structured detail:

1{
2 "status": 422,
3 "title": "Unprocessable Entity",
4 "detail": "One or more line items are invalid.",
5 "error": []
6}
HTTP statusWhen it happens
400Malformed JSON, or a missing/invalid merchantId or resource id.
401Missing, invalid, or inactive API key.
403Merchant not found, or not owned by your account.
404Merchant has no compliance credentials on file.
429Rate limit exceeded (response code 108).
422 and other 4xx/5xxOperation-level validation or processing error (see the structured shape above).
502 / 504The compliance service was unreachable or the request timed out.

Usage and rate limits

Merchant Transactions are metered separately from your tax-lookup (rate request) usage. Each transaction call counts as one merchant request against your plan’s merchant allowance, and every call is subject to per-key rate limiting. Exceeding your rate returns 429 with response code 108, the same as the rest of the API. See Rate Limiting & Errors for backoff guidance.

Only requests that reach the compliance service are metered. Requests rejected up front (bad key, unknown merchant, missing credentials, malformed body, rate limit) do not count against your merchant usage.

Retries and idempotency

Read operations are safe to retry. Write operations are not retried automatically, and you should not blindly retry them either: a retried create can produce a duplicate order, certificate, or refund.

OperationSafe to retry?
order/get, cert/get, cert/listYes, these are reads.
cart/calculateRecalculates; retry only if you did not receive a response.
order/create-from-cart, order/create, order/update, cert/create, cert/deleteNo, may duplicate or clobber.
refund/createNo. A duplicate refund is a financial incident.

If a write call times out (504) or the service is briefly unavailable (502), don’t immediately retry. First confirm whether the operation succeeded, for example by fetching the order with order/get, then retry only if it did not.