> This page is for version v6.0 (default).
> For other versions, use one of these documentation indexes:
> - v6.0 (default): https://docs.zip.tax/v-6-0/llms.txt
> - v5.0: https://docs.zip.tax/v-5-0/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.zip.tax/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.zip.tax/_mcp/server.

# Create Nexus Locations

POST https://api.zip-tax.com/merchant/nexus/create
Content-Type: application/json

Available on Pro and Enterprise PlansRecords one or more physical locations for a merchant. A merchant's physical locations are what establish its nexus, and nexus is what decides whether a sale is sourced at its origin or its destination, so this is the data a self-managed cart calculation depends on.Each address is geocoded as it is written, and the normalized result is what every response returns; expect the address you get back to differ from the one you sent. If any address in the request cannot be resolved to a US state the whole request is rejected with 422 and nothing is stored, so a retry cannot duplicate the locations that would otherwise have succeeded.Address resolution for the whole request is budgeted at 10 seconds. A batch that exceeds it returns 504 and stores nothing; send fewer locations per call if you hit this. Geocoding that had already completed is still billed, because the lookups were still performed.Available to self-managed merchants only. A TaxCloud-connected merchant's nexus is held in TaxCloud, so this returns 403 for them.

Reference: https://docs.zip.tax/api-reference/merchant-nexus/create

## Authentication

- `X-API-KEY` header (required) — API Key authentication via header

## Request

### Body (application/json)

This endpoint expects an object.

- `locations` (list of NexusLocationInput, required) — The locations to record. Up to 25 per call; each one is geocoded as it is written, which is what bounds the batch.
- `merchantId` (string, required) — UUID of the merchant these locations belong to. Must be owned by the calling account and must be self-managed.
- `nexusType` ("physical", optional) — The kind of nexus being recorded. Only 'physical' can be created: economic nexus is derived from a merchant's sales activity rather than declared, so sending 'economic' is rejected rather than silently stored as physical.

## Response

### 200

OK

- `merchantId` (string, required) — UUID of the merchant the locations were recorded for.
- `locations` (list of NexusLocationOutput, optional) — The stored locations, in the order submitted, each with its server-issued locationId and normalized address.

## Errors

### 400 Merchant Nexus Create Body Bad Request Error

Bad Request

- `detail` (string, optional) — A human-readable explanation specific to this occurrence of the problem.
- `errors` (list of ErrorDetail, optional) — List of individual error details
- `instance` (string, optional) — A URI reference that identifies the specific occurrence of the problem.
- `status` (long, optional) — HTTP status code
- `title` (string, optional) — A short, human-readable summary of the problem type. This value should not change between occurrences of the error.
- `type` (string, optional, default: about:blank) — A URI reference to human-readable documentation for the error.

### 401 Merchant Nexus Create Body Unauthorized Error

Unauthorized

- `detail` (string, optional) — A human-readable explanation specific to this occurrence of the problem.
- `errors` (list of ErrorDetail, optional) — List of individual error details
- `instance` (string, optional) — A URI reference that identifies the specific occurrence of the problem.
- `status` (long, optional) — HTTP status code
- `title` (string, optional) — A short, human-readable summary of the problem type. This value should not change between occurrences of the error.
- `type` (string, optional, default: about:blank) — A URI reference to human-readable documentation for the error.

### 403 Merchant Nexus Create Body Forbidden Error

Forbidden

- `detail` (string, optional) — A human-readable explanation specific to this occurrence of the problem.
- `errors` (list of ErrorDetail, optional) — List of individual error details
- `instance` (string, optional) — A URI reference that identifies the specific occurrence of the problem.
- `status` (long, optional) — HTTP status code
- `title` (string, optional) — A short, human-readable summary of the problem type. This value should not change between occurrences of the error.
- `type` (string, optional, default: about:blank) — A URI reference to human-readable documentation for the error.

### 404 Merchant Nexus Create Body Not Found Error

Not Found

- `detail` (string, optional) — A human-readable explanation specific to this occurrence of the problem.
- `errors` (list of ErrorDetail, optional) — List of individual error details
- `instance` (string, optional) — A URI reference that identifies the specific occurrence of the problem.
- `status` (long, optional) — HTTP status code
- `title` (string, optional) — A short, human-readable summary of the problem type. This value should not change between occurrences of the error.
- `type` (string, optional, default: about:blank) — A URI reference to human-readable documentation for the error.

### 422 Merchant Nexus Create Body Unprocessable Entity Error

Unprocessable Entity

- `detail` (string, optional) — A human-readable explanation specific to this occurrence of the problem.
- `errors` (list of ErrorDetail, optional) — List of individual error details
- `instance` (string, optional) — A URI reference that identifies the specific occurrence of the problem.
- `status` (long, optional) — HTTP status code
- `title` (string, optional) — A short, human-readable summary of the problem type. This value should not change between occurrences of the error.
- `type` (string, optional, default: about:blank) — A URI reference to human-readable documentation for the error.

### 429 Merchant Nexus Create Body Too Many Requests Error

Too Many Requests

- `detail` (string, optional) — A human-readable explanation specific to this occurrence of the problem.
- `errors` (list of ErrorDetail, optional) — List of individual error details
- `instance` (string, optional) — A URI reference that identifies the specific occurrence of the problem.
- `status` (long, optional) — HTTP status code
- `title` (string, optional) — A short, human-readable summary of the problem type. This value should not change between occurrences of the error.
- `type` (string, optional, default: about:blank) — A URI reference to human-readable documentation for the error.

### 500 Merchant Nexus Create Body Internal Server Error

Internal Server Error

- `detail` (string, optional) — A human-readable explanation specific to this occurrence of the problem.
- `errors` (list of ErrorDetail, optional) — List of individual error details
- `instance` (string, optional) — A URI reference that identifies the specific occurrence of the problem.
- `status` (long, optional) — HTTP status code
- `title` (string, optional) — A short, human-readable summary of the problem type. This value should not change between occurrences of the error.
- `type` (string, optional, default: about:blank) — A URI reference to human-readable documentation for the error.

### 503 Merchant Nexus Create Body Service Unavailable Error

Service Unavailable

- `detail` (string, optional) — A human-readable explanation specific to this occurrence of the problem.
- `errors` (list of ErrorDetail, optional) — List of individual error details
- `instance` (string, optional) — A URI reference that identifies the specific occurrence of the problem.
- `status` (long, optional) — HTTP status code
- `title` (string, optional) — A short, human-readable summary of the problem type. This value should not change between occurrences of the error.
- `type` (string, optional, default: about:blank) — A URI reference to human-readable documentation for the error.

### 504 Merchant Nexus Create Body Gateway Timeout Error

Gateway Timeout

- `detail` (string, optional) — A human-readable explanation specific to this occurrence of the problem.
- `errors` (list of ErrorDetail, optional) — List of individual error details
- `instance` (string, optional) — A URI reference that identifies the specific occurrence of the problem.
- `status` (long, optional) — HTTP status code
- `title` (string, optional) — A short, human-readable summary of the problem type. This value should not change between occurrences of the error.
- `type` (string, optional, default: about:blank) — A URI reference to human-readable documentation for the error.

## Types

### NexusLocationInput

- `address` (string, required) — The location's street address as a single line. It is geocoded when you send it, and the normalized result is what every response returns, so the value you get back will usually differ from the one you sent. US addresses only. An address that cannot be resolved to a state is rejected with 422 rather than stored.
- `locationType` (enum, required) — What kind of presence this location represents. 'office', 'store', and 'warehouse' are premises you occupy; 'inventory_fba' covers inventory held in a third-party fulfilment network; 'employee' covers staff or contractors working in a state; 'property' covers inventory or equipment held there; 'temporary' covers short-term presence such as a trade show.
  - Allowed values: `office`, `store`, `warehouse`, `inventory_fba`, `employee`, `property`, `temporary`
- `isFulfillmentOrigin` (boolean, optional) — Whether goods actually ship from this location. This is the field origin-sourcing consults, so set it explicitly for anything unusual, such as an office that also ships or a warehouse that does not. When omitted it defaults by locationType: true for 'warehouse', 'inventory_fba', and 'store'; false for the rest.
- `name` (string, optional) — Your own label for this location. Shown back to you on every response and never used in a calculation.
- `referenceId` (string, optional) — The ID you use in your own system to identify this location.
- `registered` (boolean, optional) — Whether the merchant is registered to collect sales tax in this location's state. Defaults to false when omitted.

### NexusLocationOutput

- `address` (string, required) — The normalized address resolved when the location was written, not the string you sent.
- `isFulfillmentOrigin` (boolean, required) — Whether goods ship from this location.
- `locationId` (string, required) — Server-issued identifier for this location. Use it with /merchant/nexus/update and /merchant/nexus/delete.
- `locationType` (enum, required) — What kind of presence this location represents.
  - Allowed values: `office`, `store`, `warehouse`, `inventory_fba`, `employee`, `property`, `temporary`
- `name` (string, required) — Your own label for this location. Empty when none was supplied.
- `referenceId` (string, required) — The ID you use in your own system to identify this location. Empty when none was supplied.
- `registered` (boolean, required) — Whether the merchant is registered to collect sales tax in this location's state.

### ErrorDetail

- `location` (string, optional) — Where the error occurred, e.g. 'body.items[3].tags' or 'path.thing-id'
- `message` (string, optional) — Error message text
- `value` (any, optional) — The value at the given location

## Examples

**Request**

```json
{
  "locations": [
    {
      "address": "1401 Lavaca St Austin TX 78701",
      "locationType": "office"
    }
  ],
  "merchantId": "merchantId"
}
```

**Response**

```json
{
  "merchantId": "merchantId",
  "locations": [
    {
      "address": "1401 Lavaca St, Austin, TX 78701-1634, United States",
      "isFulfillmentOrigin": true,
      "locationId": "6dc371de-00a4-44bf-8a88-2bcab2f15041",
      "locationType": "office",
      "name": "TestCo Texas Distribution Center",
      "referenceId": "warehouse-123",
      "registered": true
    }
  ]
}
```

**SDK Code**

```python
import requests

url = "https://api.zip-tax.com/merchant/nexus/create"

payload = {
    "locations": [
        {
            "address": "1401 Lavaca St Austin TX 78701",
            "locationType": "office"
        }
    ],
    "merchantId": "merchantId"
}
headers = {
    "X-API-KEY": "<apiKey>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript
const url = 'https://api.zip-tax.com/merchant/nexus/create';
const options = {
  method: 'POST',
  headers: {'X-API-KEY': '<apiKey>', 'Content-Type': 'application/json'},
  body: '{"locations":[{"address":"1401 Lavaca St Austin TX 78701","locationType":"office"}],"merchantId":"merchantId"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.zip-tax.com/merchant/nexus/create"

	payload := strings.NewReader("{\n  \"locations\": [\n    {\n      \"address\": \"1401 Lavaca St Austin TX 78701\",\n      \"locationType\": \"office\"\n    }\n  ],\n  \"merchantId\": \"merchantId\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("X-API-KEY", "<apiKey>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://api.zip-tax.com/merchant/nexus/create")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["X-API-KEY"] = '<apiKey>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"locations\": [\n    {\n      \"address\": \"1401 Lavaca St Austin TX 78701\",\n      \"locationType\": \"office\"\n    }\n  ],\n  \"merchantId\": \"merchantId\"\n}"

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.zip-tax.com/merchant/nexus/create")
  .header("X-API-KEY", "<apiKey>")
  .header("Content-Type", "application/json")
  .body("{\n  \"locations\": [\n    {\n      \"address\": \"1401 Lavaca St Austin TX 78701\",\n      \"locationType\": \"office\"\n    }\n  ],\n  \"merchantId\": \"merchantId\"\n}")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.zip-tax.com/merchant/nexus/create', [
  'body' => '{
  "locations": [
    {
      "address": "1401 Lavaca St Austin TX 78701",
      "locationType": "office"
    }
  ],
  "merchantId": "merchantId"
}',
  'headers' => [
    'Content-Type' => 'application/json',
    'X-API-KEY' => '<apiKey>',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api.zip-tax.com/merchant/nexus/create");
var request = new RestRequest(Method.POST);
request.AddHeader("X-API-KEY", "<apiKey>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"locations\": [\n    {\n      \"address\": \"1401 Lavaca St Austin TX 78701\",\n      \"locationType\": \"office\"\n    }\n  ],\n  \"merchantId\": \"merchantId\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "X-API-KEY": "<apiKey>",
  "Content-Type": "application/json"
]
let parameters = [
  "locations": [
    [
      "address": "1401 Lavaca St Austin TX 78701",
      "locationType": "office"
    ]
  ],
  "merchantId": "merchantId"
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.zip-tax.com/merchant/nexus/create")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```