Orders

View and manage orders, update status, tracking, and shipments

GET /admin/api/orders

List orders with pagination, filtering, sorting, and search.

GET /admin/api/orders/{id}

Fetch a single order by its numeric ID, including line items with custom fields.

PATCH /admin/api/orders/{id}/status

Update the fulfilment status of an order. When set to "delivered", download tokens are generated for any digital products.

PATCH /admin/api/orders/{id}/payment-status

Update the payment status of an order.

PATCH /admin/api/orders/{id}/shipping

Update the tracking number and optionally the fulfilment status of an order.

GET /admin/api/orders/{id}/shipments

List all shipments attached to an order.

POST /admin/api/orders/{id}/shipments

Create a shipment for an order and fetch courier rate options from Easyship. No label is bought yet — call the buy-label endpoint with a chosen courier_id next.

POST /admin/api/orders/{id}/shipments/{sid}/buy-label

Purchase a shipping label from the selected courier. Charges the Easyship account and stores the tracking number + label PDF URL on the shipment.

POST /admin/api/orders/{id}/shipments/{sid}/refresh

Refresh the delivery status of a shipment from Easyship. Updates tracking events and the shipment status (e.g. in_transit, delivered).

DELETE /admin/api/orders/{id}/shipments/{sid}

Cancel a shipment. If a label was purchased, requests a refund from Easyship. If only rates were fetched, simply removes the shipment.

PATCH /admin/api/orders/{id}/delivery-date

Set or clear the expected delivery date for an order. Send null to clear. Successful updates write an admin_logs entry (`admin.orders.update_delivery_date`).

PATCH /admin/api/orders/{id}/test-flag

Mark or unmark an order as a test order. Test orders are excluded from dashboard stats and the default admin list view.

POST /admin/api/orders/{id}/edit/preview

Dry-run an order edit. Recomputes totals, returns the payment delta, stock warnings, an auto-generated diff summary, and a flag for shipped/delivered orders. No DB writes.

PATCH /admin/api/orders/{id}/edit

Apply an in-place edit to an order. Recomputes totals, updates line items / customer / shipping / discount fields, and writes an `order_edits` audit row. Optionally queues an "order updated" email to the customer. Use the preview endpoint to compute the payment delta and detect stock or shipped-order warnings before calling this.

POST /admin/api/orders/preview

Validate a phone-order payload and return a totals breakdown without persisting. Used by the admin create-order form's live summary panel.

POST /admin/api/orders

Persist a phone / walk-in order. Returns the new order's `id` and `public_id`. When `send_confirmation_email` is true, the customer confirmation email is queued.

GET /admin/api/orders/calendar

Per-day order counts for a Mon–Sun calendar grid covering the requested month, plus the count of orders without a delivery date. Cancelled and refunded orders are excluded by default; pass an explicit `status=cancelled|refunded` to override.

PATCH /admin/api/orders/{id}/internal-status

Assign an internal (workflow) status to an order, or clear it by passing null. The internal_status_id must reference an existing internal order status.

POST /admin/api/orders/{id}/activate-subscription

Manually activate a subscription for a paid order whose Stripe webhook never arrived. Links the supplied Stripe subscription and customer IDs to the order's subscription line item and creates the local subscription record.

GET /admin/api/orders/{order_id}/payments

List the partial payment records for an order, in sort order. Works for any order; a non-manual (e.g. Stripe) order simply returns an empty list.

POST /admin/api/orders/{order_id}/payments

Create a partial payment record on a manual-payment order. After the write, the order's payment_status is recomputed from the sum of paid rows.

POST /admin/api/orders/{order_id}/payments/reorder

Bulk-update the sort order of an order's partial payment records. Send the full list of (id, sort_order) pairs to apply.

PATCH /admin/api/orders/{order_id}/payments/{id}

Partial update of a payment record. Any field may be omitted to leave it unchanged. For `note`, send null to explicitly clear it. The order's payment_status is recomputed after the write.

DELETE /admin/api/orders/{order_id}/payments/{id}

Delete a partial payment record. The order's payment_status is recomputed after the delete.

POST /admin/api/orders/{order_id}/shipments/boxnow

Create a BoxNow shipment row for an order from a manually supplied parcel ID. The row is set to status `created`. Fails if a shipment already exists for the order.

GET /admin/api/orders

List orders with pagination, filtering, sorting, and search.

Parameters

Name Type Required Description
page integer optional Page number, 1-indexed (default: 1)
per_page integer optional Items per page, 1-100 (default: 20)
search string optional Text search on customer name or email
status string optional Filter by fulfilment status (e.g. "pending", "shipped", "delivered")
payment_status string optional Filter by payment status (e.g. "paid", "pending", "refunded")
total_min string optional Minimum total as decimal string (e.g. "10.00")
total_max string optional Maximum total as decimal string (e.g. "50.00")
created_from string optional Earliest creation date (inclusive), as YYYY-MM-DD
created_to string optional Latest creation date (inclusive), as YYYY-MM-DD
sort string optional Sort field with optional - prefix for descending. Valid: customer_name, total, status, created_at. Default: -created_at

Response 200

{
  "data": [
    {
      "id": 1,
      "status": "processing",
      "payment_status": "paid",
      "customer_name": "Jane Doe",
      "customer_email": "jane@example.com",
      "total": 5498,
      "created_at": "2025-12-01T09:30:00Z"
    },
    {
      "id": 2,
      "status": "pending",
      "payment_status": "pending",
      "customer_name": "John Smith",
      "customer_email": "john@example.com",
      "total": 2999,
      "created_at": "2025-11-30T14:15:00Z"
    }
  ],
  "page": 1,
  "per_page": 20,
  "total": 87,
  "total_pages": 5
}

Example

curl "https://yourshop.zeroshop.io/admin/api/orders?page=1&per_page=20&status=processing&sort=-created_at" \
  -H "Authorization: Bearer zspat_..."
GET /admin/api/orders/{id}

Fetch a single order by its numeric ID, including line items with custom fields.

Response 200

{
  "id": 1,
  "status": "processing",
  "payment_status": "paid",
  "customer_name": "Jane Doe",
  "customer_email": "jane@example.com",
  "customer_phone": "+1 503 555 0142",
  "shipping_line1": "123 Main Street",
  "shipping_line2": "Apt 4B",
  "shipping_city": "Portland",
  "shipping_state": "OR",
  "shipping_postal_code": "97201",
  "shipping_country": "US",
  "notes": "Please leave at front door",
  "subtotal": 4499,
  "total": 5498,
  "tax_amount": 500,
  "shipping_method": "Standard",
  "shipping_cost": 499,
  "payment_provider": "stripe",
  "pickup_location_id": 3,
  "pickup_location_name": "Downtown Portland Storefront",
  "tracking_number": "1Z999AA10123456784",
  "ip_address": "203.0.113.42",
  "invoice_url": "https://invoice.stripe.com/i/acct_123/inv_abc",
  "created_at": "2025-12-01T09:30:00Z",
  "updated_at": "2025-12-02T11:00:00Z",
  "items": [
    {
      "id": 1,
      "product_id": 1,
      "product_name": "Classic Cotton Tee",
      "product_sku": "CCT-001",
      "unit_price": 2999,
      "quantity": 1,
      "subtotal": 2999,
      "tax_rate": 2000,
      "tax_amount": 300,
      "variant_label": "Size: L / Color: Navy",
      "custom_fields": [
        {
          "field_name": "Size",
          "field_value": "L"
        },
        {
          "field_name": "Color",
          "field_value": "Navy"
        }
      ]
    },
    {
      "id": 2,
      "product_id": 5,
      "product_name": "Organic Coffee Beans",
      "product_sku": "OCB-500",
      "unit_price": 1500,
      "quantity": 1,
      "subtotal": 1500,
      "tax_rate": 2000,
      "tax_amount": 200,
      "variant_label": "Weight: 500g",
      "custom_fields": []
    }
  ]
}

Example

curl "https://yourshop.zeroshop.io/admin/api/orders/1" \
  -H "Authorization: Bearer zspat_..."
PATCH /admin/api/orders/{id}/status

Update the fulfilment status of an order. When set to "delivered", download tokens are generated for any digital products.

Request Body

{
  "status": "shipped"
}

Response 204

Example

curl -X PATCH "https://yourshop.zeroshop.io/admin/api/orders/1/status" \
  -H "Authorization: Bearer zspat_..." \
  -H "Content-Type: application/json" \
  -d '{"status": "shipped"}'
PATCH /admin/api/orders/{id}/payment-status

Update the payment status of an order.

Request Body

{
  "payment_status": "paid"
}

Response 204

Example

curl -X PATCH "https://yourshop.zeroshop.io/admin/api/orders/1/payment-status" \
  -H "Authorization: Bearer zspat_..." \
  -H "Content-Type: application/json" \
  -d '{"payment_status": "paid"}'
PATCH /admin/api/orders/{id}/shipping

Update the tracking number and optionally the fulfilment status of an order.

Request Body

{
  "tracking_number": "1Z999AA10123456784",
  "status": "shipped"
}

Response 204

Example

curl -X PATCH "https://yourshop.zeroshop.io/admin/api/orders/1/shipping" \
  -H "Authorization: Bearer zspat_..." \
  -H "Content-Type: application/json" \
  -d '{"tracking_number": "1Z999AA10123456784", "status": "shipped"}'
GET /admin/api/orders/{id}/shipments

List all shipments attached to an order.

Parameters

Name Type Required Description
id integer required Order ID

Response 200

[
  {
    "id": 17,
    "order_id": 482,
    "status": "label_purchased",
    "courier_id": "dhl-express",
    "courier_name": "DHL Express",
    "tracking_number": "1Z999AA10123456784",
    "label_url": "https://cdn.zeroshop.io/tenants/abc/labels/shipment-17.pdf",
    "cost_cents": 1850,
    "created_at": "2026-04-12T10:05:00Z"
  }
]

Example

curl "https://yourshop.zeroshop.io/admin/api/orders/482/shipments" \
  -H "Authorization: Bearer zspat_..."
POST /admin/api/orders/{id}/shipments

Create a shipment for an order and fetch courier rate options from Easyship. No label is bought yet — call the buy-label endpoint with a chosen courier_id next.

Parameters

Name Type Required Description
id integer required Order ID

Response 201

{
  "shipment": {
    "id": 17,
    "order_id": 482,
    "status": "rates_fetched",
    "courier_id": null,
    "courier_name": null,
    "tracking_number": null,
    "label_url": null,
    "cost_cents": null,
    "created_at": "2026-04-12T10:05:00Z"
  },
  "courier_options": [
    {
      "courier_id": "dhl-express",
      "courier_name": "DHL Express",
      "cost": 1850,
      "delivery_estimate": "2-3 business days"
    },
    {
      "courier_id": "ups-ground",
      "courier_name": "UPS Ground",
      "cost": 1200,
      "delivery_estimate": "3-5 business days"
    }
  ]
}

Example

curl -X POST "https://yourshop.zeroshop.io/admin/api/orders/482/shipments" \
  -H "Authorization: Bearer zspat_..."
POST /admin/api/orders/{id}/shipments/{sid}/buy-label

Purchase a shipping label from the selected courier. Charges the Easyship account and stores the tracking number + label PDF URL on the shipment.

Parameters

Name Type Required Description
id integer required Order ID
sid integer required Shipment ID

Request Body

{
  "courier_id": "dhl-express",
  "courier_name": "DHL Express"
}

Response 200

{
  "id": 17,
  "order_id": 482,
  "status": "label_purchased",
  "courier_id": "dhl-express",
  "courier_name": "DHL Express",
  "tracking_number": "1Z999AA10123456784",
  "label_url": "https://cdn.zeroshop.io/tenants/abc/labels/shipment-17.pdf",
  "cost_cents": 1850,
  "created_at": "2026-04-12T10:05:00Z"
}

Example

curl -X POST "https://yourshop.zeroshop.io/admin/api/orders/482/shipments/17/buy-label" \
  -H "Authorization: Bearer zspat_..." \
  -H "Content-Type: application/json" \
  -d '{"courier_id": "dhl-express", "courier_name": "DHL Express"}'
POST /admin/api/orders/{id}/shipments/{sid}/refresh

Refresh the delivery status of a shipment from Easyship. Updates tracking events and the shipment status (e.g. in_transit, delivered).

Parameters

Name Type Required Description
id integer required Order ID
sid integer required Shipment ID

Response 200

{
  "id": 17,
  "order_id": 482,
  "status": "in_transit",
  "courier_id": "dhl-express",
  "courier_name": "DHL Express",
  "tracking_number": "1Z999AA10123456784",
  "label_url": "https://cdn.zeroshop.io/tenants/abc/labels/shipment-17.pdf",
  "cost_cents": 1850,
  "created_at": "2026-04-12T10:05:00Z"
}

Example

curl -X POST "https://yourshop.zeroshop.io/admin/api/orders/482/shipments/17/refresh" \
  -H "Authorization: Bearer zspat_..."
DELETE /admin/api/orders/{id}/shipments/{sid}

Cancel a shipment. If a label was purchased, requests a refund from Easyship. If only rates were fetched, simply removes the shipment.

Parameters

Name Type Required Description
id integer required Order ID
sid integer required Shipment ID

Response 204

Example

curl -X DELETE "https://yourshop.zeroshop.io/admin/api/orders/482/shipments/17" \
  -H "Authorization: Bearer zspat_..."
PATCH /admin/api/orders/{id}/delivery-date

Set or clear the expected delivery date for an order. Send null to clear. Successful updates write an admin_logs entry (`admin.orders.update_delivery_date`).

Request Body

{
  "delivery_date": "2026-05-01"
}

Response 204

Example

curl -X PATCH "https://yourshop.zeroshop.io/admin/api/orders/482/delivery-date" \
  -H "Authorization: Bearer zspat_..." \
  -H "Content-Type: application/json" \
  -d '{ "delivery_date": "2026-05-01" }'
PATCH /admin/api/orders/{id}/test-flag

Mark or unmark an order as a test order. Test orders are excluded from dashboard stats and the default admin list view.

Request Body

{
  "is_test": true
}

Response 204

Example

curl -X PATCH "https://yourshop.zeroshop.io/admin/api/orders/482/test-flag" \
  -H "Authorization: Bearer zspat_..." \
  -H "Content-Type: application/json" \
  -d '{"is_test": true}'
POST /admin/api/orders/{id}/edit/preview

Dry-run an order edit. Recomputes totals, returns the payment delta, stock warnings, an auto-generated diff summary, and a flag for shipped/delivered orders. No DB writes.

Parameters

Name Type Required Description
id integer required Order ID

Request Body

{
  "items": [
    {
      "id": 1,
      "product_id": 1,
      "variant_id": 11,
      "quantity": 2,
      "unit_price_override_cents": null,
      "custom_field_values": []
    },
    {
      "id": null,
      "product_id": 7,
      "variant_id": 73,
      "quantity": 1,
      "unit_price_override_cents": 1999,
      "custom_field_values": []
    }
  ],
  "customer": {
    "name": "Jane Doe",
    "email": "jane@example.com",
    "phone": "+1 503 555 0142"
  },
  "shipping_address": {
    "line1": "123 Main Street",
    "line2": "Apt 4B",
    "city": "Portland",
    "state": "OR",
    "postal_code": "97201",
    "country": "US"
  },
  "shipping": {
    "method": "Express",
    "cost_cents": 999
  },
  "voucher_code": null,
  "discount_amount_cents": 0,
  "discount_reason": null,
  "delivery_date": null,
  "internal_notes": null,
  "payment_adjustment_note": "Customer added a second item by phone.",
  "stock_override": false,
  "notify_customer": false,
  "warn_acknowledged": false
}

Response 200

{
  "totals_before": {
    "subtotal": 4499,
    "tax": 500,
    "shipping": 499,
    "discount": 0,
    "total": 5498
  },
  "totals_after": {
    "subtotal": 7997,
    "tax": 800,
    "shipping": 999,
    "discount": 0,
    "total": 9796
  },
  "payment_delta_cents": 4298,
  "stock_warnings": [],
  "summary": "Added 1× Hand-thrown Mug (SKU HTM-200); shipping changed to Express (€9.99).",
  "requires_warn_acknowledged": false
}

Example

curl -X POST "https://yourshop.zeroshop.io/admin/api/orders/1/edit/preview" \
  -H "Authorization: Bearer zspat_..." \
  -H "Content-Type: application/json" \
  -d @edit-payload.json
PATCH /admin/api/orders/{id}/edit

Apply an in-place edit to an order. Recomputes totals, updates line items / customer / shipping / discount fields, and writes an `order_edits` audit row. Optionally queues an "order updated" email to the customer. Use the preview endpoint to compute the payment delta and detect stock or shipped-order warnings before calling this.

Parameters

Name Type Required Description
id integer required Order ID

Request Body

{
  "items": [
    {
      "id": 1,
      "product_id": 1,
      "variant_id": 11,
      "quantity": 2,
      "unit_price_override_cents": null,
      "custom_field_values": []
    },
    {
      "id": null,
      "product_id": 7,
      "variant_id": 73,
      "quantity": 1,
      "unit_price_override_cents": 1999,
      "custom_field_values": []
    }
  ],
  "shipping": {
    "method": "Express",
    "cost_cents": 999
  },
  "payment_adjustment_note": "Customer paid the difference in cash.",
  "stock_override": false,
  "notify_customer": true,
  "warn_acknowledged": false
}

Response 200

{
  "id": 1,
  "status": "processing",
  "payment_status": "paid",
  "customer_name": "Jane Doe",
  "customer_email": "jane@example.com",
  "customer_phone": "+1 503 555 0142",
  "shipping_line1": "123 Main Street",
  "shipping_line2": "Apt 4B",
  "shipping_city": "Portland",
  "shipping_state": "OR",
  "shipping_postal_code": "97201",
  "shipping_country": "US",
  "subtotal": 7997,
  "total": 9796,
  "tax_amount": 800,
  "shipping_method": "Express",
  "shipping_cost": 999,
  "payment_provider": "stripe",
  "pickup_location_id": null,
  "pickup_location_name": null,
  "created_at": "2025-12-01T09:30:00Z",
  "updated_at": "2026-05-13T14:22:10Z",
  "items": [
    {
      "id": 1,
      "product_id": 1,
      "product_name": "Classic Cotton Tee",
      "product_sku": "CCT-001",
      "unit_price": 2999,
      "quantity": 2,
      "subtotal": 5998,
      "tax_rate": 2000,
      "tax_amount": 600,
      "variant_label": "Size: L / Color: Navy",
      "custom_fields": []
    },
    {
      "id": 14,
      "product_id": 7,
      "product_name": "Hand-thrown Mug",
      "product_sku": "HTM-200",
      "unit_price": 1999,
      "quantity": 1,
      "subtotal": 1999,
      "tax_rate": 2000,
      "tax_amount": 200,
      "variant_label": "Color: Charcoal",
      "custom_fields": []
    }
  ],
  "edit": {
    "id": 42,
    "order_id": 1,
    "edited_at": "2026-05-13T14:22:10Z",
    "edited_by_shop_owner_id": 8,
    "edit_source": "admin_ui",
    "summary": "Added 1× Hand-thrown Mug (SKU HTM-200); shipping changed to Express (€9.99).",
    "total_before_cents": 5498,
    "total_after_cents": 9796,
    "payment_delta_cents": 4298,
    "payment_adjustment_note": "Customer paid the difference in cash.",
    "customer_notified": true,
    "stock_override_used": false
  }
}

Example

curl -X PATCH "https://yourshop.zeroshop.io/admin/api/orders/1/edit" \
  -H "Authorization: Bearer zspat_..." \
  -H "Content-Type: application/json" \
  -d @edit-payload.json
POST /admin/api/orders/preview

Validate a phone-order payload and return a totals breakdown without persisting. Used by the admin create-order form's live summary panel.

Request Body

{
  "customer": {
    "name": "Marta Müller",
    "email": "marta@example.com",
    "phone": "+49 30 1234567"
  },
  "shipping_address": {
    "line1": "Hauptstraße 1",
    "city": "Berlin",
    "postal_code": "10115",
    "country": "DE"
  },
  "items": [
    {
      "variant_id": 91,
      "quantity": 1
    }
  ],
  "shipping": {
    "kind": "configured",
    "method_id": 2
  },
  "payment_status": "none"
}

Response 200

{
  "subtotal_cents": 9999,
  "discount_cents": 0,
  "shipping_cents": 599,
  "tax_cents": 1900,
  "total_cents": 12498,
  "resulting_status": "pending",
  "resulting_payment_status": "none"
}

Example

curl -X POST "https://yourshop.zeroshop.io/admin/api/orders/preview" \
  -H "Authorization: Bearer zspat_..." \
  -H "Content-Type: application/json" \
  -d @phone-order.json
POST /admin/api/orders

Persist a phone / walk-in order. Returns the new order's `id` and `public_id`. When `send_confirmation_email` is true, the customer confirmation email is queued.

Request Body

{
  "customer": {
    "name": "Marta Müller",
    "email": "marta@example.com",
    "phone": "+49 30 1234567"
  },
  "shipping_address": {
    "line1": "Hauptstraße 1",
    "city": "Berlin",
    "postal_code": "10115",
    "country": "DE"
  },
  "billing_address": null,
  "items": [
    {
      "variant_id": 91,
      "quantity": 1
    }
  ],
  "shipping": {
    "kind": "configured",
    "method_id": 2
  },
  "payment_status": "paid",
  "voucher_code": null,
  "discount": null,
  "delivery_date": "2026-05-15",
  "notes": "Customer prefers afternoon delivery.",
  "register_customer": false,
  "send_confirmation_email": true
}

Response 201

{
  "id": 487,
  "public_id": "ORD-2026-0487"
}

Example

curl -X POST "https://yourshop.zeroshop.io/admin/api/orders" \
  -H "Authorization: Bearer zspat_..." \
  -H "Content-Type: application/json" \
  -d @phone-order.json
GET /admin/api/orders/calendar

Per-day order counts for a Mon–Sun calendar grid covering the requested month, plus the count of orders without a delivery date. Cancelled and refunded orders are excluded by default; pass an explicit `status=cancelled|refunded` to override.

Parameters

Name Type Required Description
month string optional Month in YYYY-MM form. Defaults to the current month when absent or malformed.
search string optional Text search on customer name or email.
status string optional Filter by fulfilment status. When set, the default exclusion of cancelled/refunded is disabled.
payment_status string optional Filter by payment status.
total_min string optional Minimum total as decimal string.
total_max string optional Maximum total as decimal string.

Response 200

{
  "grid_start": "2026-04-27",
  "grid_end": "2026-05-31",
  "days": [
    {
      "date": "2026-05-01",
      "count": 3
    },
    {
      "date": "2026-05-02",
      "count": 1
    }
  ],
  "no_delivery_date_count": 2
}

Example

curl "https://yourshop.zeroshop.io/admin/api/orders/calendar?month=2026-05" \
  -H "Authorization: Bearer zspat_..."
PATCH /admin/api/orders/{id}/internal-status

Assign an internal (workflow) status to an order, or clear it by passing null. The internal_status_id must reference an existing internal order status.

Parameters

Name Type Required Description
id integer required Order ID

Request Body

{
  "internal_status_id": 3
}

Response 200

{
  "id": 482,
  "internal_status_id": 3
}

Example

curl -X PATCH "https://yourshop.zeroshop.io/admin/api/orders/482/internal-status" \
  -H "Authorization: Bearer zspat_..." \
  -H "Content-Type: application/json" \
  -d '{"internal_status_id": 3}'
POST /admin/api/orders/{id}/activate-subscription

Manually activate a subscription for a paid order whose Stripe webhook never arrived. Links the supplied Stripe subscription and customer IDs to the order's subscription line item and creates the local subscription record.

Parameters

Name Type Required Description
id integer required Order ID

Request Body

{
  "external_subscription_id": "sub_1NQabcXYZ0123",
  "external_customer_id": "cus_1NQabcXYZ0123"
}

Response 201

{
  "id": 51,
  "public_id": "SUB-2026-0051"
}

Example

curl -X POST "https://yourshop.zeroshop.io/admin/api/orders/482/activate-subscription" \
  -H "Authorization: Bearer zspat_..." \
  -H "Content-Type: application/json" \
  -d '{"external_subscription_id": "sub_1NQabcXYZ0123", "external_customer_id": "cus_1NQabcXYZ0123"}'
GET /admin/api/orders/{order_id}/payments

List the partial payment records for an order, in sort order. Works for any order; a non-manual (e.g. Stripe) order simply returns an empty list.

Parameters

Name Type Required Description
order_id integer required Order ID

Response 200

[
  {
    "id": 9,
    "order_id": 482,
    "label": "Deposit",
    "amount_cents": 5000,
    "paid": true,
    "paid_at": "2026-05-20T09:00:00Z",
    "note": "Paid in cash at counter",
    "sort_order": 0,
    "created_at": "2026-05-18T10:00:00Z",
    "updated_at": "2026-05-20T09:00:00Z"
  },
  {
    "id": 10,
    "order_id": 482,
    "label": "Balance on delivery",
    "amount_cents": 7498,
    "paid": false,
    "paid_at": null,
    "note": null,
    "sort_order": 1,
    "created_at": "2026-05-18T10:00:00Z",
    "updated_at": "2026-05-18T10:00:00Z"
  }
]

Example

curl "https://yourshop.zeroshop.io/admin/api/orders/482/payments" \
  -H "Authorization: Bearer zspat_..."
POST /admin/api/orders/{order_id}/payments

Create a partial payment record on a manual-payment order. After the write, the order's payment_status is recomputed from the sum of paid rows.

Parameters

Name Type Required Description
order_id integer required Order ID

Request Body

{
  "label": "Deposit",
  "amount_cents": 5000,
  "paid": true,
  "note": "Paid in cash at counter",
  "sort_order": 0
}

Response 201

{
  "id": 9,
  "order_id": 482,
  "label": "Deposit",
  "amount_cents": 5000,
  "paid": true,
  "paid_at": "2026-05-20T09:00:00Z",
  "note": "Paid in cash at counter",
  "sort_order": 0,
  "created_at": "2026-05-20T09:00:00Z",
  "updated_at": "2026-05-20T09:00:00Z"
}

Example

curl -X POST "https://yourshop.zeroshop.io/admin/api/orders/482/payments" \
  -H "Authorization: Bearer zspat_..." \
  -H "Content-Type: application/json" \
  -d '{"label": "Deposit", "amount_cents": 5000, "paid": true, "note": "Paid in cash at counter"}'
POST /admin/api/orders/{order_id}/payments/reorder

Bulk-update the sort order of an order's partial payment records. Send the full list of (id, sort_order) pairs to apply.

Parameters

Name Type Required Description
order_id integer required Order ID

Request Body

{
  "items": [
    {
      "id": 10,
      "sort_order": 0
    },
    {
      "id": 9,
      "sort_order": 1
    }
  ]
}

Response 204

Example

curl -X POST "https://yourshop.zeroshop.io/admin/api/orders/482/payments/reorder" \
  -H "Authorization: Bearer zspat_..." \
  -H "Content-Type: application/json" \
  -d '{"items": [{"id": 10, "sort_order": 0}, {"id": 9, "sort_order": 1}]}'
PATCH /admin/api/orders/{order_id}/payments/{id}

Partial update of a payment record. Any field may be omitted to leave it unchanged. For `note`, send null to explicitly clear it. The order's payment_status is recomputed after the write.

Parameters

Name Type Required Description
order_id integer required Order ID
id integer required Payment record ID

Request Body

{
  "paid": true
}

Response 200

{
  "id": 10,
  "order_id": 482,
  "label": "Balance on delivery",
  "amount_cents": 7498,
  "paid": true,
  "paid_at": "2026-05-25T16:30:00Z",
  "note": null,
  "sort_order": 1,
  "created_at": "2026-05-18T10:00:00Z",
  "updated_at": "2026-05-25T16:30:00Z"
}

Example

curl -X PATCH "https://yourshop.zeroshop.io/admin/api/orders/482/payments/10" \
  -H "Authorization: Bearer zspat_..." \
  -H "Content-Type: application/json" \
  -d '{"paid": true}'
DELETE /admin/api/orders/{order_id}/payments/{id}

Delete a partial payment record. The order's payment_status is recomputed after the delete.

Parameters

Name Type Required Description
order_id integer required Order ID
id integer required Payment record ID

Response 204

Example

curl -X DELETE "https://yourshop.zeroshop.io/admin/api/orders/482/payments/10" \
  -H "Authorization: Bearer zspat_..."
POST /admin/api/orders/{order_id}/shipments/boxnow

Create a BoxNow shipment row for an order from a manually supplied parcel ID. The row is set to status `created`. Fails if a shipment already exists for the order.

Parameters

Name Type Required Description
order_id integer required Order ID

Request Body

{
  "provider_shipment_id": "BN-1234567890"
}

Response 201

{
  "id": 17
}

Example

curl -X POST "https://yourshop.zeroshop.io/admin/api/orders/482/shipments/boxnow" \
  -H "Authorization: Bearer zspat_..." \
  -H "Content-Type: application/json" \
  -d '{"provider_shipment_id": "BN-1234567890"}'

We value your privacy

We use cookies for essential site functionality and, with your consent, analytics to understand how our platform is used. No personal data is shared with third parties. See our Privacy Policy for details.