# Customers

The customer lifecycle QuickBooks applies: create, read, sparse and full update, deactivate and reactivate, with SyncToken checks, name rules and stored sub-customers.

Customers are the entity the simulator models in the most depth: you create, read, update, deactivate and reactivate them, and every write is checked against the customer's current `SyncToken` and the company's name rules.

The shipped scenarios seed their customers from `Id` `1`. Creating a customer stores it under the next `Id` after the highest one stored, so creating one never takes a seeded customer's `Id`.

### Create a customer

A `POST …/customer` with no `Id` creates a customer. The block below resets to an empty company first, so the new customer gets `Id` `1`, then creates one and tries its name again:

```bash
R=4620816365320737870
curl -s -X POST "$RYSTIC_URL/_rystic/reset"
curl -s "$RYSTIC_URL/v3/company/$R/customer" -H 'Authorization: Bearer placeholder' -H 'Content-Type: application/json' -d '{"GivenName":"Maple","FamilyName":"Cafe"}' | jq -c '.Customer | {Id, DisplayName, SyncToken, Active}'
# -> {"Id":"1","DisplayName":"Maple Cafe","SyncToken":"0","Active":true}
curl -s "$RYSTIC_URL/v3/company/$R/customer" -H 'Authorization: Bearer placeholder' -H 'Content-Type: application/json' -d '{"DisplayName":" MAPLE CAFE "}' | jq -c '.Fault.Error[0] | {code, Message}'
# -> {"code":"6240","Message":"Duplicate Name Exists Error"}
```

The simulator assigns the `Id`, sets `SyncToken` to `"0"` and fills each field you leave out:

| Field | Default |
|---|---|
| `Active` | true |
| `Taxable` | true |
| `PreferredDeliveryMethod` | `Print` |
| `CurrencyRef` | USD |
| `Balance` | 0 |

Creating a customer needs a `DisplayName` or at least one name part. The name parts are `Title`, `GivenName`, `MiddleName`, `FamilyName` and `Suffix`. The simulator joins the parts you send with spaces into the display name. With neither, it returns 400 `6080`.

### Update a customer

Send the same route with `Id` and the customer's current `SyncToken`, and its `SyncToken` goes up by one:

```bash
curl -s "$RYSTIC_URL/v3/company/$R/customer" -H 'Authorization: Bearer placeholder' -H 'Content-Type: application/json' -d '{"Id":"1","SyncToken":"0","sparse":true,"Notes":"Net 30"}' | jq -c '.Customer | {Id, Notes, SyncToken}'
# -> {"Id":"1","Notes":"Net 30","SyncToken":"1"}
```

With `"sparse": true` only the fields you send change; without it, every writable field the body leaves out is cleared. A `SyncToken` that is not current is refused ([Idempotency](https://www.rystic.ai/docs/simulators/quickbooks.md#idempotency)), and so is an `Id` that matches no customer ([Error format](https://www.rystic.ai/docs/simulators/quickbooks.md#error-format)).

### Deactivate and reactivate a customer

A sparse update with `"Active": false` deactivates the customer, and `"Active": true` reactivates it. There is no delete, and a deactivated customer still reads by `Id`:

```bash
curl -s "$RYSTIC_URL/v3/company/$R/customer" -H 'Authorization: Bearer placeholder' -H 'Content-Type: application/json' -d '{"Id":"1","SyncToken":"1","sparse":true,"Active":false}' | jq -c '.Customer | {Id, Active, SyncToken}'
# -> {"Id":"1","Active":false,"SyncToken":"2"}
curl -s "$RYSTIC_URL/v3/company/$R/customer/1" -H 'Authorization: Bearer placeholder' | jq -c '.Customer | {Id, DisplayName, Active}'
# -> {"Id":"1","DisplayName":"Maple Cafe","Active":false}
```

### Names

`DisplayName` is unique among active customers, ignoring case and surrounding spaces. A clash returns 400 `6240`. A deactivated customer's name is free to reuse.

The check runs only on a name you send. An update that sends no `DisplayName`, such as a reactivation, is not checked. So reactivating a customer whose name another customer has since taken leaves two active customers with one name. Whether QuickBooks refuses that reactivation is unconfirmed.

### Read

`GET …/customer/{customerId}` reads a customer, active or not. [Error format](https://www.rystic.ai/docs/simulators/quickbooks.md#error-format) lists how a read refuses an `Id`.

### Sub-customers

Creating or updating a customer keeps the `ParentRef`, `Job` and `BillWithParent` you send. The simulator doesn't check that the parent exists and sets no `RootCustomerRef`; whether QuickBooks does either is unconfirmed.

**Differs from QuickBooks:** the simulator sets no `Level` and keeps `FullyQualifiedName` as the customer's own name, where QuickBooks sets `Level` and builds `FullyQualifiedName` as `Parent:Child`.

**Differs from QuickBooks:** an update sets `BalanceWithJobs` to the customer's own `Balance`, so updating `quickbooks_job_hierarchy`'s parent drops its jobs' balances from it. QuickBooks' `BalanceWithJobs` includes every sub-job's open balance.

### Request ids

A customer write stores its `requestid` but never replays it ([Idempotency](https://www.rystic.ai/docs/simulators/quickbooks.md#idempotency)).

### Tax codes

A customer you create has no `DefaultTaxCodeRef`. [What the scenarios do not hold](https://www.rystic.ai/docs/simulators/quickbooks.md#what-the-scenarios-do-not-hold) names the tax code and rate each scenario seeds.

---

Source: https://www.rystic.ai/docs/simulators/quickbooks/features/customers · Markdown: https://www.rystic.ai/docs/simulators/quickbooks/features/customers.md
