Self-Managed Merchants

Create merchants that are active immediately, track their nexus footprint on Ziptax, and keep compliance responsibility with the merchant.
Available onProEnterprise

A self-managed merchant is created with merchantType: "self-managed". No TaxCloud invite is sent, and the merchant is active the moment the create call returns — there is no account-setup step to wait on.

Under this model, your platform tracks the merchant’s nexus footprint on Ziptax: the physical locations they operate from and the states where they have crossed economic nexus thresholds. The merchant remains responsible for their own compliance — registration, filing, and remittance. If you want TaxCloud to handle compliance end to end instead, use a TaxCloud-connected merchant.

Create a self-managed merchant

Call POST /merchant/create with merchantType set to self-managed. The API default is taxcloud, which starts the TaxCloud invite process, so you must pass self-managed explicitly to create a self-managed merchant.

cURL
$curl -X POST "https://api.zip-tax.com/merchant/create" \
> -H "X-API-KEY: YOUR_API_KEY" \
> -H "Content-Type: application/json" \
> -d '{
> "merchantName": "Acme Outfitters",
> "contactFirst": "Daniel",
> "contactLast": "Smith",
> "contactEmail": "daniel@acmeoutfitters.example",
> "referenceId": "acct-10482",
> "merchantType": "self-managed"
> }'

Only merchantName is required. referenceId is the identifier you use in your own system for this merchant. The sendTaxcloudInvite field is ignored when merchantType is self-managed — no invite is ever sent to a self-managed merchant.

A successful call returns 201 Created:

1{
2 "status": "success",
3 "message": "merchant created successfully",
4 "merchantId": "6b3c1f5e-2a8d-4c9b-9f2e-1d7a4b6c8e10"
5}

Store the merchantId (a UUID); you’ll use it in every subsequent call for this merchant.

Two error cases to plan for:

  • Company name not set. Your account must have a Company Name configured before you can create any merchant. Without one, the API returns 400 with the message Please add a Company Name in the General settings page before creating a merchant.
  • Duplicate merchant. Creating a duplicate — for example, reusing a referenceId that already belongs to another merchant in your account — returns 409 Conflict.

How self-managed merchants appear on reads

POST /merchant/get and GET /merchant/list do not return merchantType. Instead, the compliance model is visible through the status field: a self-managed merchant always reports status: "external_compliance", meaning compliance is managed outside TaxCloud.

1{
2 "merchantId": "6b3c1f5e-2a8d-4c9b-9f2e-1d7a4b6c8e10",
3 "merchantName": "Acme Outfitters",
4 "contactFirst": "Daniel",
5 "contactLast": "Smith",
6 "contactEmail": "daniel@acmeoutfitters.example",
7 "status": "external_compliance",
8 "referenceId": "acct-10482"
9}

Self-managed merchants never move through the TaxCloud lifecycle statuses (taxcloud_invited, taxcloud_connected, taxcloud_disconnected) unless you later invite them to TaxCloud.

What your platform manages

For a self-managed merchant, your platform records the merchant’s nexus footprint on Ziptax. This has two parts:

  • Physical nexus — the locations the merchant operates from: offices, stores, warehouses, inventory (including FBA), employees, property, and temporary presence such as trade shows. Manage these through the /merchant/nexus/* endpoints or the platform UI. See Nexus Management.
  • Economic thresholds — the states where the merchant has crossed an economic nexus threshold from sales activity. Economic nexus is derived from sales activity rather than declared, so it is not something you record through the nexus endpoints. See Economic Thresholds.

Ziptax does not require a minimum number of locations. If a merchant has no physical locations recorded, Ziptax does not track physical nexus for them.

Calculating tax

You have two options for a self-managed merchant, and both work with your Ziptax API key alone — no merchant credentials involved.

Cart calculation. POST /merchant/cart/calculate takes a full cart — origin, destination, and line items — and returns the tax due on each line. For a self-managed merchant, Ziptax calculates it with its own rate engine, applying sourcing rules, product taxability codes, and state freight rules. See Self-Managed Cart Calculation for the contract.

Rate lookup. The rate endpoints return the combined rate and per-jurisdiction breakdown for a single US address, coordinate pair, or postal code. Use these when you want the rate itself rather than a calculated cart.

Cart calculation does not check the merchant’s nexus footprint before calculating: it returns the rate for the sourced address whether or not the merchant has an obligation to collect there. Deciding where the merchant must collect stays with you and the merchant.

What else is not available

Cart calculation is the only Merchant Transactions endpoint a self-managed merchant can use, and it is stateless — nothing is stored, so the result cannot be turned into an order.

The remaining transaction endpoints (the order/* and cert/* operations, and refund/create) forward requests to TaxCloud using compliance credentials stored for the merchant. A self-managed merchant has no TaxCloud credentials, so each of those calls returns 403. They become available once a merchant is TaxCloud-connected with credentials set.

Inviting a self-managed merchant to TaxCloud

A self-managed merchant can later be invited to TaxCloud, either from the platform UI or through the API. This sends the TaxCloud invite email to the merchant’s contact and converts the merchant to the connected model. Because it creates a TaxCloud-connected merchant, the conversion is an Enterprise plan feature.

To convert through the API, send setMerchantType on POST /merchant/update. Nothing else is required, since the invite goes to the contactEmail already stored for the merchant:

1{
2 "merchantId": "2c0534ea-eb8a-4732-9cdb-2476f244029d",
3 "setMerchantType": "taxcloud",
4 "sendTaxcloudInvite": true
5}

The merchant’s status moves from external_compliance to taxcloud_invited.

To invite a different address, send an update block in the same request. It is applied before the invite, so the new address is the one emailed:

1{
2 "merchantId": "2c0534ea-eb8a-4732-9cdb-2476f244029d",
3 "setMerchantType": "taxcloud",
4 "update": {
5 "merchantName": "Blue Ridge Outfitters",
6 "contactEmail": "dana@blueridgeoutfitters.example"
7 }
8}

A merchant with no contact email on record cannot be invited, so give it one in the update block when converting. Set sendTaxcloudInvite to false to convert without emailing the merchant at all, for example when you plan to attach an existing TaxCloud account with Set Merchant Credentials instead.

The conversion is reversible: sending setMerchantType: "self-managed" moves the merchant back. That direction deletes any TaxCloud credentials stored for the merchant, so returning to the connected model afterwards means connecting their TaxCloud account again. Re-sending a merchant’s current type changes nothing and does not re-send the invite, so the request is safe to repeat.

Converting also changes how cart calculation behaves for that merchant: calls run through TaxCloud from then on, rates for the same cart may differ from what the Ziptax engine returned before, and taxability codes switch to TaxCloud’s vocabulary. Allow up to a minute for the routing change to take effect. See Moving a merchant between models.