> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dekhq.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Place an order

> Upload art, price an order, place it, and check what became of it, with the DEKHQ Partner REST API. Four steps, with real requests and answers.

This guide places one order through the REST API in four steps: **upload** your art, **preview** the price, **place** the order, then **poll** for its status. PromoStandards SOAP doesn't place orders; ordering is REST only.

Replace `YOUR_ID` and `YOUR_PASSWORD` with your partner credential. Every call uses HTTP Basic authentication, except the file upload in step 1.

> [!NOTE]
>
> Your credential needs the `assets_write` scope to upload art and the `orders_write` scope to preview and place orders. See [Scopes](https://docs.dekhq.com/api/authentication.md#scopes).

> [!WARNING]
>
> Today, `partners.dekhq.com` is a **sandbox**. Orders you place there are test orders, so use test data. Your decorator tells you when your integration moves to a live environment.

## Before you start

* **Garment ids.** An order line names its garment either by catalog ids (`styleId` and `colorId`) or by `brand`, `styleNumber` and `colorName`. There is no catalog endpoint yet, so ask your decorator for the ids or the exact names of the styles you may order.
* **What's supported.** Only screen print (`SP`) decorations and garments you supply yourself (`suppliedBy: "customer"`) are taken today. Fields the API doesn't take yet, such as `rush`, are refused with `not_supported_yet`.
* **Art.** PNG, JPG, GIF, WebP, TIFF, SVG, PDF, AI, EPS or PSD, up to 100 MB.

**1. Upload your art**

Start the upload with the file name and size in bytes:

```bash theme={null}
curl -u "YOUR_ID:YOUR_PASSWORD" -X POST \
  https://partners.dekhq.com/api/partners/v1/uploads \
  -H "Content-Type: application/json" \
  -d '{"filename":"front-logo.png","sizeBytes":482113}'
```

The answer holds an `upload.uploadId` and a signed `uploadUrl`:

```json theme={null}
{
  "upload": { "uploadId": "upl_7Hq2Xk9Lm3Np8Rs4Tv6Wy1Za5Bc0De2F", "status": "pending", "filename": "front-logo.png" },
  "uploadUrl": "https://uploads.example.com/quarantine/...",
  "uploadMethod": "PUT",
  "uploadHeaders": { "Content-Type": "image/png" }
}
```

`PUT` the file's bytes to `uploadUrl` with exactly the `uploadHeaders`. The URL is on a **different host** from the API and is already signed, so send **no Basic authentication** with this request. It expires after a few minutes.

```bash theme={null}
curl -X PUT "UPLOAD_URL" -H "Content-Type: image/png" --data-binary @front-logo.png
```

Then finalize the upload so DEKHQ checks and stores the file:

```bash theme={null}
curl -u "YOUR_ID:YOUR_PASSWORD" -X POST \
  https://partners.dekhq.com/api/partners/v1/uploads/upl_7Hq2Xk9Lm3Np8Rs4Tv6Wy1Za5Bc0De2F/finalize \
  -H "Content-Type: application/json" -d '{}'
```

The `upload.status` is now `finalized`. You can use the same `uploadId` on later orders.

**2. Preview the price**

Send the order you plan to place to `POST /api/partners/v1/order-submissions/preview`. Nothing is created.

```json theme={null}
{
  "orderName": "Spring staff shirts",
  "purchaseOrderNumber": "PO-12345",
  "shippingMethod": "ship",
  "lines": [
    {
      "ref": "L1",
      "garment": { "styleId": "YOUR_STYLE_ID", "colorId": "YOUR_COLOR_ID" },
      "suppliedBy": "customer",
      "sizes": [ { "size": "M", "quantity": 6 }, { "size": "L", "quantity": 6 } ]
    }
  ],
  "decorations": [
    {
      "method": "SP",
      "locationCode": "FF",
      "size": { "width": 10, "height": 10 },
      "inks": [ { "name": "White", "pms": "WHITE" } ],
      "artUploadId": "upl_7Hq2Xk9Lm3Np8Rs4Tv6Wy1Za5Bc0De2F",
      "lineRefs": [ "L1" ]
    }
  ],
  "shipTo": {
    "company": "Example Co", "firstName": "Sam", "lastName": "Sample",
    "address1": "200 Sample St", "city": "Riverton", "region": "WY",
    "postalCode": "82501", "country": "US"
  }
}
```

```json theme={null}
{ "total": "116.92", "currency": "USD" }
```

For a pickup order, send `"shippingMethod": "pickup"` and leave out `shipTo`.

> [!NOTE]
>
> A priced preview can still be refused when you place the order. Some checks, such as an unrecognized size or a print location that doesn't fit the garment, run only at placement.

**3. Place the order**

Send the same body to `POST /api/partners/v1/order-submissions`, with two additions: `expectedTotal` set to the preview's `total`, and an `Idempotency-Key` header you make up (a unique string per order).

```bash theme={null}
curl -u "YOUR_ID:YOUR_PASSWORD" -X POST \
  https://partners.dekhq.com/api/partners/v1/order-submissions \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: spring-shirts-001" \
  -d @order.json
```

The answer is always HTTP `202` with a submission. Usually it is already decided:

```json theme={null}
{
  "submissionId": "sub_5bc814821cecf43b6b75ee3f9a5f94db",
  "status": "accepted",
  "order": { "orderId": "ord_bfaf246443f60efcfa44ca25c3", "orderNumber": "00067842", "status": "pending_approval" }
}
```

Keep the `submissionId` and the `orderId`. If you send the same key and body again you get this first answer, never a second order, so it is safe to retry after a timeout. The same key with a different body returns `409` [`idempotency_conflict`](https://docs.dekhq.com/api/partners/errors#idempotency_conflict).

**4. Poll for the outcome**

The submission `status` is one of:

* `accepted`: the order exists. The answer includes `order`.
* `refused`: the order wasn't created. See [If an order is refused](#if-an-order-is-refused).
* `received`: still processing. Call `GET /api/partners/v1/order-submissions/{submissionId}` again after a moment until it changes.

After that, follow the order itself with `GET /api/partners/v1/orders/{orderId}`; see [Order Status](https://docs.dekhq.com/api/services/order-status.md).

## What `pending_approval` means

A new order is accepted with status `pending_approval`. DEKHQ has the order and its price, but it is **not in production yet**: it waits for approval on the DEKHQ side. Once approved it moves on to `approved`, `in_production`, `shipped` and `delivered`; `cancelled` is final. Check `GET /api/partners/v1/orders/{orderId}` to see where it is.

## If an order is refused

A refused submission or preview returns a problem with `code` `order_refused` and an `errors[]` list naming each field. Fix the fields and submit again with a **new** `Idempotency-Key`. These are the refusals seen while testing the sandbox:

| What happened | `errors[].code` and `field` | Notes |
| - | - | - |
| The `expectedTotal` no longer matches | `total_changed`, `expectedTotal` | The problem includes `currentTotal`. Preview again, then place the order with the new total. |
| A garment id isn't in the catalog | `not_in_catalog`, `lines.0.garment.styleId` | Check the ids with your decorator. |
| A field the API doesn't take yet | `not_supported_yet`, for example `rush` | Remove the field. |
| Same `Idempotency-Key`, different body | HTTP `409` `idempotency_conflict` | Not a refusal of the order: use a new key for a different order. |

An upload that can't be taken returns HTTP `422` [`upload_refused`](https://docs.dekhq.com/api/partners/errors#upload_refused) when you start it or finalize it, for example for an unsupported file type, a file over 100 MB, or a finalize before the bytes arrived. Every error lists its `requestId`; quote it if you contact your decorator. See [Rate limits and errors](https://docs.dekhq.com/api/errors.md) for the full list.

<sub>Verified against DEKHQ cbe1264 on 2026-11-12</sub>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.