Skip to content

Orders

8 operations

GET/orders#

List orders

orders:read

Parameters

NameTypeDescription
cursorquerystring
limitqueryinteger
Default:50
statusqueryOrderStatus

Order lifecycle state. Transitions follow the server matrix; money-bearing states are reachable only through refunds.

Values:placedapprovedprocessingshippeddelivereddelivered_failedreturnedcancelledcompletedpartially_refundedrefunded
created_at_minquerystring
updated_at_minquerystring

Incremental sync for status/payment changes (cursor stays keyed on created_at)

tagquerystring

Only orders carrying this tag (case-insensitive)

Responses

200

Cursor page of PII-free orders

NameTypeDescription
dataRequiredOrder[]
next_cursorRequirednullablestring

Pass back as cursor to fetch the next page; null on the last page.

  • 401

    Missing, invalid, expired, or revoked token

  • 403

    Required live scope is missing

  • 429

    Token budget exhausted (180 requests/minute, 60 writes/minute per install)

Request
curl -X GET "https://dukkan.one/platform-api/v1/orders?limit=50" \
  -H "Authorization: Bearer $DUKKAN_ACCESS_TOKEN"
Response
{
  "data": [
    {
      "id": "6f1d2c3b-4a59-4e8f-9b70-2d1c3e4f5a6b",
      "order_number": "1042",
      "status": "placed",
      "payment_status": "not_required",
      "source": "online",
      "line_pricing": "net",
      "subtotal": {
        "amount_minor": 275000,
        "currency": "SYP",
        "decimals": 0
      },
      "discount": {
        "amount_minor": 275000,
        "currency": "SYP",
        "decimals": 0
      },
      "shipping": {
        "amount_minor": 275000,
        "currency": "SYP",
        "decimals": 0
      },
      "tax": {
        "amount_minor": 275000,
        "currency": "SYP",
        "decimals": 0
      },
      "total": {
        "amount_minor": 275000,
        "currency": "SYP",
        "decimals": 0
      },
      "paid": {
        "amount_minor": 275000,
        "currency": "SYP",
        "decimals": 0
      },
      "refunded": {
        "amount_minor": 275000,
        "currency": "SYP",
        "decimals": 0
      },
      "exchange_rate": {
        "scaled": 1300000,
        "scale": 4
      },
      "tags": [
        "string"
      ],
      "created_at": "2026-08-18T16:00:00Z",
      "updated_at": "2026-08-18T16:00:00Z"
    }
  ],
  "next_cursor": "eyJjcmVhdGVkX2F0IjoiMjAyNi0wOC0xOFQxNjowMDowMFoifQ"
}

POST/orders#

Create an order with the prices the merchant agreed

orders:createIdempotent

Lines carry the agreed unit price (catalog variants or custom lines with no variant); totals are recomputed server-side (subtotal = Σ quantity × unit_price_minor, total = subtotal − discount + shipping, tax 0) and every side effect of a storefront order follows: stock decrement obeying policy (409 insufficient_stock with details.lines[] and nothing written), CRM link by phone, merchant push and email, order.created with source: app, and a timeline row naming the app. Specific codes: 422 currency_not_allowed, 404 variant_not_found, 409 variant_unavailable, 409 payment_method_disabled. The response echoes the customer details the app supplied regardless of clients:read.

Parameters

NameTypeDescription
Idempotency-KeyheaderRequiredstring

Unique per logical write, at most 200 characters, remembered for 24 hours. Replaying the same key with the same body returns the recorded response; the same key with a different body answers 409.

Request body Required

Create an order with app-set prices. Totals are recomputed server-side: subtotal = Σ quantity × unit_price_minor, total = subtotal − discount + shipping, tax 0.

NameTypeDescription
currencyRequiredstring

One of the store's allowed storefront currencies; otherwise 422 currency_not_allowed.

statusstring

placed (default) lets the merchant review; approved records an explicit customer acceptance the app collected.

Values:placedapproved
Default:"placed"
itemsRequiredCreateOrderItem[]
discountnullableobject

Order-level discount; must not exceed the sum of the lines.

Default:null
amount_minorRequiredinteger
titlenullablestring
Default:null
shippingRequiredobject
amount_minorRequiredinteger
methodRequiredstring
Values:deliverypickup
customerRequiredobject
nameRequiredstring
phoneRequiredstring

Full international number with country code; stored normalised.

emailnullablestring

Optional. Never invented when absent.

Default:null
shipping_addressnullableobject

Required when shipping.method is delivery.

Default:null
addressRequiredstring
provinceRequiredstring

Syrian province value, e.g. damascus (see GET /store provinces).

citynullablestring
Default:null
notesnullablestring
Default:null
payment_methodRequiredstring

Must be enabled in the store; otherwise 409 payment_method_disabled.

Values:codshamcash_manual
exchange_ratenullableobject

Required when currency differs from the store's pricing currency, forbidden otherwise. rate = scaled / 10^scale, oriented 1 pricing-currency unit = rate order-currency units (same as GET /store fx).

Default:null
scaledRequiredinteger
scaleRequiredinteger
notenullablestring
Default:null
tagsstring[]

At most 10 tags after case-insensitive dedupe.

attributesOrderAttributes

Up to 20 keys ([a-z0-9_.-]{1,64}), scalar values up to 1000 UTF-8 bytes, 8192 bytes in total. Private to the calling app.

Default:{}
inventorystring
Values:decrementskip
Default:"decrement"

Responses

201

Order created (or the recorded response on an idempotent replay)

NameTypeDescription
dataRequiredOrderDetail

Order with its immutable line snapshots and reconciliation collections.

  • 400

    Invalid request

  • 401

    Missing, invalid, expired, or revoked token

  • 403

    Required live scope is missing

  • 404

    Resource not found in the token-bound store

  • 409

    State transition, inventory, refund, or idempotency conflict

  • 422

    Well-formed body that fails the contract; details.fields[] names the paths

  • 429

    Token budget exhausted (180 requests/minute, 60 writes/minute per install)

Request
curl -X POST "https://dukkan.one/platform-api/v1/orders" \
  -H "Authorization: Bearer $DUKKAN_ACCESS_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "currency": "SYP",
  "status": "placed",
  "items": [
    {
      "variant_id": "6f1d2c3b-4a59-4e8f-9b70-2d1c3e4f5a6b",
      "name": "Olive oil 1 L",
      "quantity": 2,
      "unit_price_minor": 1
    }
  ],
  "discount": {
    "amount_minor": 275000,
    "title": null
  },
  "shipping": {
    "amount_minor": 275000,
    "method": "delivery"
  },
  "customer": {
    "name": "Olive oil 1 L",
    "phone": "string",
    "email": null
  },
  "shipping_address": {
    "address": "string",
    "province": "string",
    "city": null,
    "notes": null
  },
  "payment_method": "cod",
  "exchange_rate": {
    "scaled": 1300000,
    "scale": 4
  },
  "note": null,
  "tags": [
    "string"
  ],
  "attributes": {},
  "inventory": "decrement"
}'
Response
{
  "data": {
    "id": "6f1d2c3b-4a59-4e8f-9b70-2d1c3e4f5a6b",
    "order_number": "1042",
    "status": "placed",
    "payment_status": "not_required",
    "source": "online",
    "line_pricing": "net",
    "subtotal": {
      "amount_minor": 275000,
      "currency": "SYP",
      "decimals": 0
    },
    "discount": {
      "amount_minor": 275000,
      "currency": "SYP",
      "decimals": 0
    },
    "shipping": {
      "amount_minor": 275000,
      "currency": "SYP",
      "decimals": 0
    },
    "tax": {
      "amount_minor": 275000,
      "currency": "SYP",
      "decimals": 0
    },
    "total": {
      "amount_minor": 275000,
      "currency": "SYP",
      "decimals": 0
    },
    "paid": {
      "amount_minor": 275000,
      "currency": "SYP",
      "decimals": 0
    },
    "refunded": {
      "amount_minor": 275000,
      "currency": "SYP",
      "decimals": 0
    },
    "exchange_rate": {
      "scaled": 1300000,
      "scale": 4
    },
    "tags": [
      "string"
    ],
    "created_at": "2026-08-18T16:00:00Z",
    "updated_at": "2026-08-18T16:00:00Z",
    "items": [
      {
        "id": "6f1d2c3b-4a59-4e8f-9b70-2d1c3e4f5a6b",
        "variant_id": "6f1d2c3b-4a59-4e8f-9b70-2d1c3e4f5a6b",
        "kind": "variant",
        "name": "Olive oil 1 L",
        "quantity": 2,
        "unit_price": {
          "amount_minor": 275000,
          "currency": "SYP",
          "decimals": 0
        },
        "total": {
          "amount_minor": 275000,
          "currency": "SYP",
          "decimals": 0
        }
      }
    ],
    "fulfillments": [
      {
        "id": "6f1d2c3b-4a59-4e8f-9b70-2d1c3e4f5a6b",
        "provider": "Aramex",
        "tracking_number": "RX123456789SY",
        "status": "pending",
        "created_at": "2026-08-18T16:00:00Z",
        "updated_at": "2026-08-18T16:00:00Z",
        "lines": [
          {
            "order_item_id": "6f1d2c3b-4a59-4e8f-9b70-2d1c3e4f5a6b",
            "quantity": 2
          }
        ]
      }
    ],
    "refunds": [
      {
        "id": "6f1d2c3b-4a59-4e8f-9b70-2d1c3e4f5a6b",
        "amount": {
          "amount_minor": 275000,
          "currency": "SYP",
          "decimals": 0
        },
        "reason": "correction",
        "created_at": "2026-08-18T16:00:00Z",
        "lines": [
          {
            "order_item_id": "6f1d2c3b-4a59-4e8f-9b70-2d1c3e4f5a6b",
            "quantity": 2,
            "amount_minor": 275000
          }
        ]
      }
    ],
    "note": "Stock count 2026-08-18",
    "attributes": {},
    "customer": {
      "first_name": "string",
      "last_name": "string",
      "email": "string",
      "phone": "string"
    },
    "shipping_address": {}
  }
}

GET/orders/{id}#

Get an order and immutable line snapshots

orders:read

customer and shipping_address are present ONLY when the install holds the DPA-gated clients:read scope; without it the keys are absent, not null.

Parameters

NameTypeDescription
idpathRequiredstring

Responses

200

Order detail

NameTypeDescription
dataRequiredOrderDetail

Order with its immutable line snapshots and reconciliation collections.

  • 401

    Missing, invalid, expired, or revoked token

  • 403

    Required live scope is missing

  • 404

    Resource not found in the token-bound store

  • 429

    Token budget exhausted (180 requests/minute, 60 writes/minute per install)

Request
curl -X GET "https://dukkan.one/platform-api/v1/orders/ORDER_ID" \
  -H "Authorization: Bearer $DUKKAN_ACCESS_TOKEN"
Response
{
  "data": {
    "id": "6f1d2c3b-4a59-4e8f-9b70-2d1c3e4f5a6b",
    "order_number": "1042",
    "status": "placed",
    "payment_status": "not_required",
    "source": "online",
    "line_pricing": "net",
    "subtotal": {
      "amount_minor": 275000,
      "currency": "SYP",
      "decimals": 0
    },
    "discount": {
      "amount_minor": 275000,
      "currency": "SYP",
      "decimals": 0
    },
    "shipping": {
      "amount_minor": 275000,
      "currency": "SYP",
      "decimals": 0
    },
    "tax": {
      "amount_minor": 275000,
      "currency": "SYP",
      "decimals": 0
    },
    "total": {
      "amount_minor": 275000,
      "currency": "SYP",
      "decimals": 0
    },
    "paid": {
      "amount_minor": 275000,
      "currency": "SYP",
      "decimals": 0
    },
    "refunded": {
      "amount_minor": 275000,
      "currency": "SYP",
      "decimals": 0
    },
    "exchange_rate": {
      "scaled": 1300000,
      "scale": 4
    },
    "tags": [
      "string"
    ],
    "created_at": "2026-08-18T16:00:00Z",
    "updated_at": "2026-08-18T16:00:00Z",
    "items": [
      {
        "id": "6f1d2c3b-4a59-4e8f-9b70-2d1c3e4f5a6b",
        "variant_id": "6f1d2c3b-4a59-4e8f-9b70-2d1c3e4f5a6b",
        "kind": "variant",
        "name": "Olive oil 1 L",
        "quantity": 2,
        "unit_price": {
          "amount_minor": 275000,
          "currency": "SYP",
          "decimals": 0
        },
        "total": {
          "amount_minor": 275000,
          "currency": "SYP",
          "decimals": 0
        }
      }
    ],
    "fulfillments": [
      {
        "id": "6f1d2c3b-4a59-4e8f-9b70-2d1c3e4f5a6b",
        "provider": "Aramex",
        "tracking_number": "RX123456789SY",
        "status": "pending",
        "created_at": "2026-08-18T16:00:00Z",
        "updated_at": "2026-08-18T16:00:00Z",
        "lines": [
          {
            "order_item_id": "6f1d2c3b-4a59-4e8f-9b70-2d1c3e4f5a6b",
            "quantity": 2
          }
        ]
      }
    ],
    "refunds": [
      {
        "id": "6f1d2c3b-4a59-4e8f-9b70-2d1c3e4f5a6b",
        "amount": {
          "amount_minor": 275000,
          "currency": "SYP",
          "decimals": 0
        },
        "reason": "correction",
        "created_at": "2026-08-18T16:00:00Z",
        "lines": [
          {
            "order_item_id": "6f1d2c3b-4a59-4e8f-9b70-2d1c3e4f5a6b",
            "quantity": 2,
            "amount_minor": 275000
          }
        ]
      }
    ],
    "note": "Stock count 2026-08-18",
    "attributes": {},
    "customer": {
      "first_name": "string",
      "last_name": "string",
      "email": "string",
      "phone": "string"
    },
    "shipping_address": {}
  }
}

PATCH/orders/{id}#

Update the note, add or remove tags, or merge the app's own attributes

orders:writeIdempotent

Money, lines, customer and address are immutable after creation. Tags are set operations (add/remove) so the merchant's and other apps' tags survive. attributes is the calling app's private namespace; null deletes a key; reference.url must be https on the app's registered origin.

Parameters

NameTypeDescription
idpathRequiredstring
Idempotency-KeyheaderRequiredstring

Unique per logical write, at most 200 characters, remembered for 24 hours. Replaying the same key with the same body returns the recorded response; the same key with a different body answers 409.

Request body Required

Update the note, add/remove tags, or merge the app's own attributes. Money, lines, customer and address are immutable after creation.

NameTypeDescription
notenullablestring

Replace the order note; null clears it.

tagsobject

Set operations, never a replace: the merchant's and other apps' tags survive.

addstring[]

At most 10 tags after case-insensitive dedupe.

removestring[]

Removed case-insensitively.

attributesOrderAttributesPatch

Merged into the app's namespace; a null value deletes that key.

Responses

200

The updated order

NameTypeDescription
dataRequiredOrderDetail

Order with its immutable line snapshots and reconciliation collections.

  • 400

    Invalid request

  • 401

    Missing, invalid, expired, or revoked token

  • 403

    Required live scope is missing

  • 404

    Resource not found in the token-bound store

  • 409

    State transition, inventory, refund, or idempotency conflict

  • 422

    Well-formed body that fails the contract; details.fields[] names the paths

  • 429

    Token budget exhausted (180 requests/minute, 60 writes/minute per install)

Request
curl -X PATCH "https://dukkan.one/platform-api/v1/orders/ORDER_ID" \
  -H "Authorization: Bearer $DUKKAN_ACCESS_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "note": "Stock count 2026-08-18",
  "tags": {
    "add": [
      "string"
    ],
    "remove": [
      "string"
    ]
  },
  "attributes": {}
}'
Response
{
  "data": {
    "id": "6f1d2c3b-4a59-4e8f-9b70-2d1c3e4f5a6b",
    "order_number": "1042",
    "status": "placed",
    "payment_status": "not_required",
    "source": "online",
    "line_pricing": "net",
    "subtotal": {
      "amount_minor": 275000,
      "currency": "SYP",
      "decimals": 0
    },
    "discount": {
      "amount_minor": 275000,
      "currency": "SYP",
      "decimals": 0
    },
    "shipping": {
      "amount_minor": 275000,
      "currency": "SYP",
      "decimals": 0
    },
    "tax": {
      "amount_minor": 275000,
      "currency": "SYP",
      "decimals": 0
    },
    "total": {
      "amount_minor": 275000,
      "currency": "SYP",
      "decimals": 0
    },
    "paid": {
      "amount_minor": 275000,
      "currency": "SYP",
      "decimals": 0
    },
    "refunded": {
      "amount_minor": 275000,
      "currency": "SYP",
      "decimals": 0
    },
    "exchange_rate": {
      "scaled": 1300000,
      "scale": 4
    },
    "tags": [
      "string"
    ],
    "created_at": "2026-08-18T16:00:00Z",
    "updated_at": "2026-08-18T16:00:00Z",
    "items": [
      {
        "id": "6f1d2c3b-4a59-4e8f-9b70-2d1c3e4f5a6b",
        "variant_id": "6f1d2c3b-4a59-4e8f-9b70-2d1c3e4f5a6b",
        "kind": "variant",
        "name": "Olive oil 1 L",
        "quantity": 2,
        "unit_price": {
          "amount_minor": 275000,
          "currency": "SYP",
          "decimals": 0
        },
        "total": {
          "amount_minor": 275000,
          "currency": "SYP",
          "decimals": 0
        }
      }
    ],
    "fulfillments": [
      {
        "id": "6f1d2c3b-4a59-4e8f-9b70-2d1c3e4f5a6b",
        "provider": "Aramex",
        "tracking_number": "RX123456789SY",
        "status": "pending",
        "created_at": "2026-08-18T16:00:00Z",
        "updated_at": "2026-08-18T16:00:00Z",
        "lines": [
          {
            "order_item_id": "6f1d2c3b-4a59-4e8f-9b70-2d1c3e4f5a6b",
            "quantity": 2
          }
        ]
      }
    ],
    "refunds": [
      {
        "id": "6f1d2c3b-4a59-4e8f-9b70-2d1c3e4f5a6b",
        "amount": {
          "amount_minor": 275000,
          "currency": "SYP",
          "decimals": 0
        },
        "reason": "correction",
        "created_at": "2026-08-18T16:00:00Z",
        "lines": [
          {
            "order_item_id": "6f1d2c3b-4a59-4e8f-9b70-2d1c3e4f5a6b",
            "quantity": 2,
            "amount_minor": 275000
          }
        ]
      }
    ],
    "note": "Stock count 2026-08-18",
    "attributes": {},
    "customer": {
      "first_name": "string",
      "last_name": "string",
      "email": "string",
      "phone": "string"
    },
    "shipping_address": {}
  }
}

PATCH/orders/{id}/status#

Transition order status through the server matrix

orders:writeIdempotent

Money-bearing statuses (completed, partially_refunded, refunded) are reachable only through the refund writers. A transition the matrix does not allow answers 409 with current_status in the details.

Parameters

NameTypeDescription
idpathRequiredstring
Idempotency-KeyheaderRequiredstring

Unique per logical write, at most 200 characters, remembered for 24 hours. Replaying the same key with the same body returns the recorded response; the same key with a different body answers 409.

Request body Required

Transition an order through the server matrix.

NameTypeDescription
statusRequiredSettableOrderStatus

Statuses an app may set through PATCH /orders/{id}/status. Money-bearing statuses are reachable only through refunds.

Values:placedapprovedprocessingshippeddelivereddelivered_failedreturnedcancelled

Responses

200

Status transitioned

No response body.

  • 400

    Invalid request

  • 401

    Missing, invalid, expired, or revoked token

  • 403

    Required live scope is missing

  • 404

    Resource not found in the token-bound store

  • 409

    State transition, inventory, refund, or idempotency conflict

  • 429

    Token budget exhausted (180 requests/minute, 60 writes/minute per install)

Request
curl -X PATCH "https://dukkan.one/platform-api/v1/orders/ORDER_ID/status" \
  -H "Authorization: Bearer $DUKKAN_ACCESS_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "status": "placed"
}'
Response
{
  "error": {
    "code": "invalid_request",
    "message": "A human-readable explanation",
    "request_id": "req_01J8Z1K5X9",
    "details": {}
  }
}

POST/orders/{id}/fulfillments#

Fulfill selected line quantities; ship the order once every line is fulfilled

fulfillments:writeIdempotent

Quantities above the still-unfulfilled amount of a line answer 409. Emits fulfillment.created, plus fulfillment.requested when the fulfillment is created as pending (a pickup waiting to be booked).

Parameters

NameTypeDescription
idpathRequiredstring
Idempotency-KeyheaderRequiredstring

Unique per logical write, at most 200 characters, remembered for 24 hours. Replaying the same key with the same body returns the recorded response; the same key with a different body answers 409.

Request body Required

Fulfill selected line quantities. Each order item may appear once.

NameTypeDescription
providernullablestring
tracking_numbernullablestring
statusstring

"pending" reserves the quantities without auto-shipping the order (carrier booked, pickup not yet made); move to "shipped" via PATCH when the parcel leaves.

Values:pendingshipped
Default:"shipped"
linesRequiredobject[]
order_item_idRequiredstring
quantityRequiredinteger

Responses

201

Fulfillment created; the order auto-ships only when every line is fulfilled AND the fulfillment was created as "shipped"

No response body.

  • 400

    Invalid request

  • 401

    Missing, invalid, expired, or revoked token

  • 403

    Required live scope is missing

  • 404

    Resource not found in the token-bound store

  • 409

    State transition, inventory, refund, or idempotency conflict

  • 429

    Token budget exhausted (180 requests/minute, 60 writes/minute per install)

Request
curl -X POST "https://dukkan.one/platform-api/v1/orders/ORDER_ID/fulfillments" \
  -H "Authorization: Bearer $DUKKAN_ACCESS_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "provider": "Aramex",
  "tracking_number": "RX123456789SY",
  "status": "shipped",
  "lines": [
    {
      "order_item_id": "6f1d2c3b-4a59-4e8f-9b70-2d1c3e4f5a6b",
      "quantity": 2
    }
  ]
}'
Response
{
  "error": {
    "code": "invalid_request",
    "message": "A human-readable explanation",
    "request_id": "req_01J8Z1K5X9",
    "details": {}
  }
}

PATCH/orders/{id}/fulfillments/{fulfillmentId}#

Update tracking, mark delivered, or cancel a fulfillment

fulfillments:writeIdempotent

Identity and lines are immutable. Legal transitions are pending → shipped → delivered and pending|shipped → cancelled. Cancelling releases the quantity the fulfillment consumed, so the line can be fulfilled again. Terminal (delivered/cancelled) fulfillments reject further edits with 409.

Parameters

NameTypeDescription
idpathRequiredstring
fulfillmentIdpathRequiredstring
Idempotency-KeyheaderRequiredstring

Unique per logical write, at most 200 characters, remembered for 24 hours. Replaying the same key with the same body returns the recorded response; the same key with a different body answers 409.

Request body Required

Update tracking, mark delivered, cancel, or propose a COD remittance. At least one field is required.

NameTypeDescription
tracking_numbernullablestring
statusstring
Values:shippeddeliveredcancelled
cod_collected_minorinteger

COD remittance PROPOSAL: the cash the courier reports collecting (minor units; may be less than the order total). Moves no money. The merchant confirms in admin, and that confirmation writes the cod_collection ledger row which updates payment status and fires order.paid. One open proposal per order; re-sending updates it.

cod_collected_notestring

Responses

200

Fulfillment updated. When the last outstanding fulfillment is delivered and every line is covered, the order transitions to "delivered" (order_status: "delivered" in the response); order_status_skipped is true when that transition was refused by the order's current state. COD payment status is untouched — order.paid rides the payments ledger.

No response body.

  • 400

    Invalid request

  • 401

    Missing, invalid, expired, or revoked token

  • 403

    Required live scope is missing

  • 404

    Resource not found in the token-bound store

  • 409

    State transition, inventory, refund, or idempotency conflict

  • 429

    Token budget exhausted (180 requests/minute, 60 writes/minute per install)

Request
curl -X PATCH "https://dukkan.one/platform-api/v1/orders/ORDER_ID/fulfillments/FULFILLMENT_ID" \
  -H "Authorization: Bearer $DUKKAN_ACCESS_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "tracking_number": "RX123456789SY",
  "status": "shipped",
  "cod_collected_minor": 275000,
  "cod_collected_note": "string"
}'
Response
{
  "error": {
    "code": "invalid_request",
    "message": "A human-readable explanation",
    "request_id": "req_01J8Z1K5X9",
    "details": {}
  }
}

POST/orders/{id}/refunds#

Append a refund against captured funds

refunds:writeIdempotent

amount_minor may not exceed paid minus already refunded. POS orders are refunded at the point of sale and answer 409 here. restock additionally requires the inventory:write scope.

Parameters

NameTypeDescription
idpathRequiredstring
Idempotency-KeyheaderRequiredstring

Unique per logical write, at most 200 characters, remembered for 24 hours. Replaying the same key with the same body returns the recorded response; the same key with a different body answers 409.

Request body Required

Append a refund against captured funds.

NameTypeDescription
amount_minorRequiredinteger
currencystring

Optional confirmation guard; 409 when it differs from the order's currency.

reasonnullablestring
linesobject[]

Optional line breakdown; amounts must sum to amount_minor.

order_item_idRequiredstring
quantityRequiredinteger
amount_minorRequiredinteger
restockobject

Return the refunded quantities to stock. Requires lines and the inventory:write scope. Untracked products are skipped.

location_idRequiredstring

Responses

201

Refund created. Refundability is gated on remaining captured funds, not order status; when the status matrix has no refund edge (e.g. a terminal cancelled) the money still moves and order_status_skipped reports that the status was left untouched.

No response body.

  • 400

    Invalid request

  • 401

    Missing, invalid, expired, or revoked token

  • 403

    Required live scope is missing

  • 404

    Resource not found in the token-bound store

  • 409

    State transition, inventory, refund, or idempotency conflict

  • 429

    Token budget exhausted (180 requests/minute, 60 writes/minute per install)

Request
curl -X POST "https://dukkan.one/platform-api/v1/orders/ORDER_ID/refunds" \
  -H "Authorization: Bearer $DUKKAN_ACCESS_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "amount_minor": 275000,
  "currency": "SYP",
  "reason": "correction",
  "lines": [
    {
      "order_item_id": "6f1d2c3b-4a59-4e8f-9b70-2d1c3e4f5a6b",
      "quantity": 2,
      "amount_minor": 275000
    }
  ],
  "restock": {
    "location_id": "6f1d2c3b-4a59-4e8f-9b70-2d1c3e4f5a6b"
  }
}'
Response
{
  "error": {
    "code": "invalid_request",
    "message": "A human-readable explanation",
    "request_id": "req_01J8Z1K5X9",
    "details": {}
  }
}