> For the complete documentation index, see [llms.txt](https://help.dollarlabs.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://help.dollarlabs.io/dollarlabs-b2b-custom-pricing/developer-tools/api-for-bulk-update-pricing.md).

# Pricing API

Read and write price list data over REST — push prices from an ERP or PIM, and poll the job until it lands.

A REST API for reading and writing your price list. Use it to sync pricing from an ERP, PIM, inventory system or internal tool.

Writes are **asynchronous**: you submit a batch, receive a job ID, and poll it. That keeps large updates consistent and prevents concurrent writes from racing each other.

## Base URL

```
https://pricelist-app.dollarlabs.io/api/v1/
```

## Authentication

Every request needs both headers:

| Header             | Value                                |
| ------------------ | ------------------------------------ |
| `X-API-Key`        | Your API key, prefixed `dlb_`        |
| `X-Signing-Secret` | Your signing secret, prefixed `sec_` |

Create them under **API Keys** — see [API keys](/dollarlabs-b2b-custom-pricing/developer-tools/api-keys.md). They are shown only once.

## Endpoints

<table><thead><tr><th width="90">Method</th><th width="250">Path</th><th>Purpose</th></tr></thead><tbody><tr><td><code>GET</code></td><td><code>/api/v1/pricing</code></td><td>Read the price list, paginated</td></tr><tr><td><code>GET</code></td><td><code>/api/v1/pricing/:variantId</code></td><td>Read one variant, by Shopify GID</td></tr><tr><td><code>POST</code></td><td><code>/api/v1/pricing</code></td><td>Submit a batch of upserts and removals</td></tr><tr><td><code>GET</code></td><td><code>/api/v1/jobs/:jobId</code></td><td>Poll a submitted batch</td></tr></tbody></table>

## Reading pricing

```bash
curl https://pricelist-app.dollarlabs.io/api/v1/pricing \
  -H "X-API-Key: dlb_..." \
  -H "X-Signing-Secret: sec_..."
```

Returns `priceListId`, a `rows` array, and `pageInfo` carrying `limit` and `nextCursor`. Follow `nextCursor` until it is absent to page through the catalog.

A single variant, by GID:

```bash
curl https://pricelist-app.dollarlabs.io/api/v1/pricing/gid://shopify/ProductVariant/123456789 \
  -H "X-API-Key: dlb_..." \
  -H "X-Signing-Secret: sec_..."
```

## Writing pricing

`POST /api/v1/pricing` with a body containing `updates`, `remove`, or both.

```json
{
  "updates": [
    {
      "variantId": "gid://shopify/ProductVariant/123456789",
      "productId": "gid://shopify/Product/987654321",
      "prices":        { "wholesale": "10.00" },
      "caseMultiples": { "wholesale": 6 },
      "loosePrices":   { "wholesale": "2.00" },
      "discountModes": { "wholesale": "fixed_amount" }
    }
  ],
  "remove": []
}
```

### Fields on an update

| Field           | Meaning                                                   |
| --------------- | --------------------------------------------------------- |
| `variantId`     | Shopify variant GID. Required.                            |
| `productId`     | Shopify product GID.                                      |
| `prices`        | Price per tag                                             |
| `volumeTiers`   | Tier ladder per tag                                       |
| `caseMultiples` | Case multiple per tag                                     |
| `loosePrices`   | Loose unit price per tag                                  |
| `discountModes` | `specific_price`, `percentage` or `fixed_amount`, per tag |

Every pricing object is **keyed by customer tag**, using `"__default__"` for the Default column. Tag keys must match your price list columns exactly, including case.

**Money values** are a string or number with up to two decimal places — `"10.00"` or `9.5`. Passing `null` clears that value.

`remove` takes an array of variant GIDs to strip pricing from entirely.

### The response

You get `202 Accepted` and a job ID. The write has not happened yet.

## Polling the job

```bash
curl https://pricelist-app.dollarlabs.io/api/v1/jobs/<jobId> \
  -H "X-API-Key: dlb_..." \
  -H "X-Signing-Secret: sec_..."
```

Status is one of `pending`, `processing`, `completed` or `failed`.

Poll at a sensible interval — every few seconds, not every 100ms — and always confirm `completed` before treating a sync as done.

## Limits and concurrency

<table><thead><tr><th width="200">Limit</th><th>Behaviour</th></tr></thead><tbody><tr><td><strong>100 requests / minute</strong> per API key, sliding window</td><td>Exceeding it returns <code>429</code> with a <code>Retry-After</code> header. Honour it.</td></tr><tr><td><strong>One job per shop at a time</strong></td><td>Submitting while a job is running returns <code>409 in_progress</code>. Wait for the current job, then retry.</td></tr></tbody></table>

{% hint style="warning" %}
The `409` also fires when a merchant is running a [CSV import](/dollarlabs-b2b-custom-pricing/price-list/csv-import-and-export.md) in the admin. Treat it as retryable rather than as an error — back off and try again.
{% endhint %}

## Writing a reliable sync

1. **Batch.** Send many variants per request rather than one each — you have 100 requests per minute, not 100 variants.
2. **Send only changes.** Diff against your last successful sync. Most nightly runs change a fraction of the catalog.
3. **Handle `409` by waiting.** It means someone else is writing, not that you failed.
4. **Honour `Retry-After` on `429`.** Do not hammer.
5. **Poll to completion.** A `202` means accepted, not applied.
6. **Log the job ID.** It is how support traces what your integration did.

## Deprecated endpoints

`POST /api/update-pricing` and `GET /api/jobs/:jobId` still work but are superseded by the `/api/v1/` endpoints above. New integrations should use `/api/v1/`; existing ones should migrate when convenient.

## Related

* [API keys](/dollarlabs-b2b-custom-pricing/developer-tools/api-keys.md) — credentials and IP restrictions
* [Jobs & history](/dollarlabs-b2b-custom-pricing/price-list/jobs-and-history.md) — what merchants see for the jobs you submit
* [CSV import & export](/dollarlabs-b2b-custom-pricing/price-list/csv-import-and-export.md) — the no-code equivalent
