View and manage orders, update status, tracking, and shipments
/admin/api/orders
List orders with pagination, filtering, sorting, and search.
/admin/api/orders/{id}
Fetch a single order by its numeric ID, including line items with custom fields.
/admin/api/orders/{id}/status
Update the fulfilment status of an order. When set to "delivered", download tokens are generated for any digital products.
/admin/api/orders/{id}/payment-status
Update the payment status of an order.
/admin/api/orders/{id}/shipping
Update the tracking number and optionally the fulfilment status of an order.
/admin/api/orders/{id}/shipments
List all shipments attached to an order.
/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.
/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.
/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).
/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.
/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`).
/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.
/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.
/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.
/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.
/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.
/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.
/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.
/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.
/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.
/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.
/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.
/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.
/admin/api/orders/{order_id}/payments/{id}
Delete a partial payment record. The order's payment_status is recomputed after the delete.
/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.
/admin/api/orders
List orders with pagination, filtering, sorting, and search.
| 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 |
{
"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
}
curl "https://yourshop.zeroshop.io/admin/api/orders?page=1&per_page=20&status=processing&sort=-created_at" \
-H "Authorization: Bearer zspat_..."
import requests
resp = requests.get(
"https://yourshop.zeroshop.io/admin/api/orders",
params={"page": 1, "per_page": 20, "status": "processing", "sort": "-created_at"},
headers={"Authorization": "Bearer zspat_..."}
)
orders = resp.json()
const params = new URLSearchParams({ page: 1, per_page: 20, status: "processing", sort: "-created_at" });
const resp = await fetch(
`https://yourshop.zeroshop.io/admin/api/orders?${params}`,
{ headers: { "Authorization": "Bearer zspat_..." } }
);
const data = await resp.json();
require "net/http"
require "json"
uri = URI("https://yourshop.zeroshop.io/admin/api/orders?page=1&per_page=20&status=processing")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer zspat_..."
resp = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(resp.body)
/admin/api/orders/{id}
Fetch a single order by its numeric ID, including line items with custom fields.
{
"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": []
}
]
}
curl "https://yourshop.zeroshop.io/admin/api/orders/1" \
-H "Authorization: Bearer zspat_..."
import requests
resp = requests.get(
"https://yourshop.zeroshop.io/admin/api/orders/1",
headers={"Authorization": "Bearer zspat_..."}
)
order = resp.json()
const resp = await fetch("https://yourshop.zeroshop.io/admin/api/orders/1", {
headers: { "Authorization": "Bearer zspat_..." }
});
const order = await resp.json();
require "net/http"
require "json"
uri = URI("https://yourshop.zeroshop.io/admin/api/orders/1")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer zspat_..."
resp = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
order = JSON.parse(resp.body)
/admin/api/orders/{id}/status
Update the fulfilment status of an order. When set to "delivered", download tokens are generated for any digital products.
{
"status": "shipped"
}
curl -X PATCH "https://yourshop.zeroshop.io/admin/api/orders/1/status" \
-H "Authorization: Bearer zspat_..." \
-H "Content-Type: application/json" \
-d '{"status": "shipped"}'
import requests
resp = requests.patch(
"https://yourshop.zeroshop.io/admin/api/orders/1/status",
headers={"Authorization": "Bearer zspat_..."},
json={"status": "shipped"}
)
# 204 No Content on success
const resp = await fetch("https://yourshop.zeroshop.io/admin/api/orders/1/status", {
method: "PATCH",
headers: {
"Authorization": "Bearer zspat_...",
"Content-Type": "application/json"
},
body: JSON.stringify({ status: "shipped" })
});
// 204 No Content on success
require "net/http"
require "json"
uri = URI("https://yourshop.zeroshop.io/admin/api/orders/1/status")
req = Net::HTTP::Patch.new(uri)
req["Authorization"] = "Bearer zspat_..."
req["Content-Type"] = "application/json"
req.body = { status: "shipped" }.to_json
resp = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
# 204 No Content on success
/admin/api/orders/{id}/payment-status
Update the payment status of an order.
{
"payment_status": "paid"
}
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"}'
import requests
resp = requests.patch(
"https://yourshop.zeroshop.io/admin/api/orders/1/payment-status",
headers={"Authorization": "Bearer zspat_..."},
json={"payment_status": "paid"}
)
# 204 No Content on success
const resp = await fetch("https://yourshop.zeroshop.io/admin/api/orders/1/payment-status", {
method: "PATCH",
headers: {
"Authorization": "Bearer zspat_...",
"Content-Type": "application/json"
},
body: JSON.stringify({ payment_status: "paid" })
});
// 204 No Content on success
require "net/http"
require "json"
uri = URI("https://yourshop.zeroshop.io/admin/api/orders/1/payment-status")
req = Net::HTTP::Patch.new(uri)
req["Authorization"] = "Bearer zspat_..."
req["Content-Type"] = "application/json"
req.body = { payment_status: "paid" }.to_json
resp = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
# 204 No Content on success
/admin/api/orders/{id}/shipping
Update the tracking number and optionally the fulfilment status of an order.
{
"tracking_number": "1Z999AA10123456784",
"status": "shipped"
}
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"}'
import requests
resp = requests.patch(
"https://yourshop.zeroshop.io/admin/api/orders/1/shipping",
headers={"Authorization": "Bearer zspat_..."},
json={"tracking_number": "1Z999AA10123456784", "status": "shipped"}
)
# 204 No Content on success
const resp = await fetch("https://yourshop.zeroshop.io/admin/api/orders/1/shipping", {
method: "PATCH",
headers: {
"Authorization": "Bearer zspat_...",
"Content-Type": "application/json"
},
body: JSON.stringify({ tracking_number: "1Z999AA10123456784", status: "shipped" })
});
// 204 No Content on success
require "net/http"
require "json"
uri = URI("https://yourshop.zeroshop.io/admin/api/orders/1/shipping")
req = Net::HTTP::Patch.new(uri)
req["Authorization"] = "Bearer zspat_..."
req["Content-Type"] = "application/json"
req.body = { tracking_number: "1Z999AA10123456784", status: "shipped" }.to_json
resp = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
# 204 No Content on success
/admin/api/orders/{id}/shipments
List all shipments attached to an order.
| Name | Type | Required | Description |
|---|---|---|---|
| id | integer | required | Order ID |
[
{
"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"
}
]
curl "https://yourshop.zeroshop.io/admin/api/orders/482/shipments" \
-H "Authorization: Bearer zspat_..."
import requests
resp = requests.get(
"https://yourshop.zeroshop.io/admin/api/orders/482/shipments",
headers={"Authorization": "Bearer zspat_..."}
)
shipments = resp.json()
const resp = await fetch(
"https://yourshop.zeroshop.io/admin/api/orders/482/shipments",
{ headers: { "Authorization": "Bearer zspat_..." } }
);
const shipments = await resp.json();
require "net/http"
require "json"
uri = URI("https://yourshop.zeroshop.io/admin/api/orders/482/shipments")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer zspat_..."
resp = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
shipments = JSON.parse(resp.body)
/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.
| Name | Type | Required | Description |
|---|---|---|---|
| id | integer | required | Order ID |
{
"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"
}
]
}
curl -X POST "https://yourshop.zeroshop.io/admin/api/orders/482/shipments" \
-H "Authorization: Bearer zspat_..."
import requests
resp = requests.post(
"https://yourshop.zeroshop.io/admin/api/orders/482/shipments",
headers={"Authorization": "Bearer zspat_..."}
)
data = resp.json()
options = data["courier_options"]
const resp = await fetch(
"https://yourshop.zeroshop.io/admin/api/orders/482/shipments",
{
method: "POST",
headers: { "Authorization": "Bearer zspat_..." }
}
);
const { shipment, courier_options } = await resp.json();
require "net/http"
require "json"
uri = URI("https://yourshop.zeroshop.io/admin/api/orders/482/shipments")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer zspat_..."
resp = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(resp.body)
/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.
| Name | Type | Required | Description |
|---|---|---|---|
| id | integer | required | Order ID |
| sid | integer | required | Shipment ID |
{
"courier_id": "dhl-express",
"courier_name": "DHL Express"
}
{
"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"
}
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"}'
import requests
resp = requests.post(
"https://yourshop.zeroshop.io/admin/api/orders/482/shipments/17/buy-label",
headers={"Authorization": "Bearer zspat_..."},
json={"courier_id": "dhl-express", "courier_name": "DHL Express"}
)
shipment = resp.json()
const resp = await fetch(
"https://yourshop.zeroshop.io/admin/api/orders/482/shipments/17/buy-label",
{
method: "POST",
headers: {
"Authorization": "Bearer zspat_...",
"Content-Type": "application/json"
},
body: JSON.stringify({ courier_id: "dhl-express", courier_name: "DHL Express" })
}
);
const shipment = await resp.json();
require "net/http"
require "json"
uri = URI("https://yourshop.zeroshop.io/admin/api/orders/482/shipments/17/buy-label")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer zspat_..."
req.content_type = "application/json"
req.body = { courier_id: "dhl-express", courier_name: "DHL Express" }.to_json
resp = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
shipment = JSON.parse(resp.body)
/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).
| Name | Type | Required | Description |
|---|---|---|---|
| id | integer | required | Order ID |
| sid | integer | required | Shipment ID |
{
"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"
}
curl -X POST "https://yourshop.zeroshop.io/admin/api/orders/482/shipments/17/refresh" \
-H "Authorization: Bearer zspat_..."
import requests
resp = requests.post(
"https://yourshop.zeroshop.io/admin/api/orders/482/shipments/17/refresh",
headers={"Authorization": "Bearer zspat_..."}
)
shipment = resp.json()
const resp = await fetch(
"https://yourshop.zeroshop.io/admin/api/orders/482/shipments/17/refresh",
{
method: "POST",
headers: { "Authorization": "Bearer zspat_..." }
}
);
const shipment = await resp.json();
require "net/http"
require "json"
uri = URI("https://yourshop.zeroshop.io/admin/api/orders/482/shipments/17/refresh")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer zspat_..."
resp = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
shipment = JSON.parse(resp.body)
/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.
| Name | Type | Required | Description |
|---|---|---|---|
| id | integer | required | Order ID |
| sid | integer | required | Shipment ID |
curl -X DELETE "https://yourshop.zeroshop.io/admin/api/orders/482/shipments/17" \
-H "Authorization: Bearer zspat_..."
import requests
resp = requests.delete(
"https://yourshop.zeroshop.io/admin/api/orders/482/shipments/17",
headers={"Authorization": "Bearer zspat_..."}
)
assert resp.status_code == 204
const resp = await fetch(
"https://yourshop.zeroshop.io/admin/api/orders/482/shipments/17",
{
method: "DELETE",
headers: { "Authorization": "Bearer zspat_..." }
}
);
// 204 No Content
require "net/http"
uri = URI("https://yourshop.zeroshop.io/admin/api/orders/482/shipments/17")
req = Net::HTTP::Delete.new(uri)
req["Authorization"] = "Bearer zspat_..."
resp = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
# 204 No Content
/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`).
{
"delivery_date": "2026-05-01"
}
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" }'
import requests
resp = requests.patch(
"https://yourshop.zeroshop.io/admin/api/orders/482/delivery-date",
headers={"Authorization": "Bearer zspat_..."},
json={"delivery_date": "2026-05-01"}
)
# 204 No Content on success
await fetch("https://yourshop.zeroshop.io/admin/api/orders/482/delivery-date", {
method: "PATCH",
headers: {
"Authorization": "Bearer zspat_...",
"Content-Type": "application/json"
},
body: JSON.stringify({ delivery_date: "2026-05-01" })
});
// 204 No Content on success
require "net/http"
require "json"
uri = URI("https://yourshop.zeroshop.io/admin/api/orders/482/delivery-date")
req = Net::HTTP::Patch.new(uri)
req["Authorization"] = "Bearer zspat_..."
req["Content-Type"] = "application/json"
req.body = { delivery_date: "2026-05-01" }.to_json
resp = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
# 204 No Content on success
/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.
{
"is_test": true
}
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}'
import requests
requests.patch(
"https://yourshop.zeroshop.io/admin/api/orders/482/test-flag",
headers={"Authorization": "Bearer zspat_..."},
json={"is_test": True}
)
await fetch("https://yourshop.zeroshop.io/admin/api/orders/482/test-flag", {
method: "PATCH",
headers: {
"Authorization": "Bearer zspat_...",
"Content-Type": "application/json"
},
body: JSON.stringify({ is_test: true })
});
require "net/http"
require "json"
uri = URI("https://yourshop.zeroshop.io/admin/api/orders/482/test-flag")
req = Net::HTTP::Patch.new(uri)
req["Authorization"] = "Bearer zspat_..."
req["Content-Type"] = "application/json"
req.body = { is_test: true }.to_json
Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
/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.
| Name | Type | Required | Description |
|---|---|---|---|
| id | integer | required | Order ID |
{
"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
}
{
"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
}
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
import requests
payload = {
"items": [
{"id": 1, "product_id": 1, "variant_id": 11, "quantity": 2, "custom_field_values": []},
{"id": None, "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 added a second item by phone.",
}
resp = requests.post(
"https://yourshop.zeroshop.io/admin/api/orders/1/edit/preview",
headers={"Authorization": "Bearer zspat_..."},
json=payload
)
preview = resp.json()
delta = preview["payment_delta_cents"]
const resp = await fetch("https://yourshop.zeroshop.io/admin/api/orders/1/edit/preview", {
method: "POST",
headers: {
"Authorization": "Bearer zspat_...",
"Content-Type": "application/json"
},
body: JSON.stringify({
items: [
{ id: 1, product_id: 1, variant_id: 11, quantity: 2, 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 added a second item by phone."
})
});
const preview = await resp.json();
require "net/http"
require "json"
uri = URI("https://yourshop.zeroshop.io/admin/api/orders/1/edit/preview")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer zspat_..."
req["Content-Type"] = "application/json"
req.body = {
items: [
{ id: 1, product_id: 1, variant_id: 11, quantity: 2, custom_field_values: [] },
{ id: nil, 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 added a second item by phone."
}.to_json
resp = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
preview = JSON.parse(resp.body)
/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.
| Name | Type | Required | Description |
|---|---|---|---|
| id | integer | required | Order ID |
{
"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
}
{
"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
}
}
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
import requests
payload = {
"items": [
{"id": 1, "product_id": 1, "variant_id": 11, "quantity": 2, "custom_field_values": []},
{"id": None, "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.",
"notify_customer": True,
}
resp = requests.patch(
"https://yourshop.zeroshop.io/admin/api/orders/1/edit",
headers={"Authorization": "Bearer zspat_..."},
json=payload
)
result = resp.json()
audit_row = result["edit"]
const resp = await fetch("https://yourshop.zeroshop.io/admin/api/orders/1/edit", {
method: "PATCH",
headers: {
"Authorization": "Bearer zspat_...",
"Content-Type": "application/json"
},
body: JSON.stringify({
items: [
{ id: 1, product_id: 1, variant_id: 11, quantity: 2, 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.",
notify_customer: true
})
});
const { edit, ...order } = await resp.json();
require "net/http"
require "json"
uri = URI("https://yourshop.zeroshop.io/admin/api/orders/1/edit")
req = Net::HTTP::Patch.new(uri)
req["Authorization"] = "Bearer zspat_..."
req["Content-Type"] = "application/json"
req.body = {
items: [
{ id: 1, product_id: 1, variant_id: 11, quantity: 2, custom_field_values: [] },
{ id: nil, 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.",
notify_customer: true
}.to_json
resp = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
result = JSON.parse(resp.body)
/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.
{
"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"
}
{
"subtotal_cents": 9999,
"discount_cents": 0,
"shipping_cents": 599,
"tax_cents": 1900,
"total_cents": 12498,
"resulting_status": "pending",
"resulting_payment_status": "none"
}
curl -X POST "https://yourshop.zeroshop.io/admin/api/orders/preview" \
-H "Authorization: Bearer zspat_..." \
-H "Content-Type: application/json" \
-d @phone-order.json
/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.
{
"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
}
{
"id": 487,
"public_id": "ORD-2026-0487"
}
curl -X POST "https://yourshop.zeroshop.io/admin/api/orders" \
-H "Authorization: Bearer zspat_..." \
-H "Content-Type: application/json" \
-d @phone-order.json
import requests
payload = {
"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": "paid",
"send_confirmation_email": True
}
resp = requests.post(
"https://yourshop.zeroshop.io/admin/api/orders",
headers={"Authorization": "Bearer zspat_..."},
json=payload
)
created = resp.json()
const resp = await fetch("https://yourshop.zeroshop.io/admin/api/orders", {
method: "POST",
headers: {
"Authorization": "Bearer zspat_...",
"Content-Type": "application/json"
},
body: JSON.stringify({
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: "paid",
send_confirmation_email: true
})
});
const created = await resp.json();
require "net/http"
require "json"
uri = URI("https://yourshop.zeroshop.io/admin/api/orders")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer zspat_..."
req["Content-Type"] = "application/json"
req.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: "paid",
send_confirmation_email: true
}.to_json
resp = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
created = JSON.parse(resp.body)
/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.
| 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. |
{
"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
}
curl "https://yourshop.zeroshop.io/admin/api/orders/calendar?month=2026-05" \
-H "Authorization: Bearer zspat_..."
/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.
| Name | Type | Required | Description |
|---|---|---|---|
| id | integer | required | Order ID |
{
"internal_status_id": 3
}
{
"id": 482,
"internal_status_id": 3
}
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}'
import requests
resp = requests.patch(
"https://yourshop.zeroshop.io/admin/api/orders/482/internal-status",
headers={"Authorization": "Bearer zspat_..."},
json={"internal_status_id": 3}
)
result = resp.json()
const resp = await fetch("https://yourshop.zeroshop.io/admin/api/orders/482/internal-status", {
method: "PATCH",
headers: {
"Authorization": "Bearer zspat_...",
"Content-Type": "application/json"
},
body: JSON.stringify({ internal_status_id: 3 })
});
const result = await resp.json();
require "net/http"
require "json"
uri = URI("https://yourshop.zeroshop.io/admin/api/orders/482/internal-status")
req = Net::HTTP::Patch.new(uri)
req["Authorization"] = "Bearer zspat_..."
req["Content-Type"] = "application/json"
req.body = { internal_status_id: 3 }.to_json
resp = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
result = JSON.parse(resp.body)
/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.
| Name | Type | Required | Description |
|---|---|---|---|
| id | integer | required | Order ID |
{
"external_subscription_id": "sub_1NQabcXYZ0123",
"external_customer_id": "cus_1NQabcXYZ0123"
}
{
"id": 51,
"public_id": "SUB-2026-0051"
}
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"}'
import requests
resp = requests.post(
"https://yourshop.zeroshop.io/admin/api/orders/482/activate-subscription",
headers={"Authorization": "Bearer zspat_..."},
json={
"external_subscription_id": "sub_1NQabcXYZ0123",
"external_customer_id": "cus_1NQabcXYZ0123"
}
)
subscription = resp.json()
const resp = await fetch("https://yourshop.zeroshop.io/admin/api/orders/482/activate-subscription", {
method: "POST",
headers: {
"Authorization": "Bearer zspat_...",
"Content-Type": "application/json"
},
body: JSON.stringify({
external_subscription_id: "sub_1NQabcXYZ0123",
external_customer_id: "cus_1NQabcXYZ0123"
})
});
const subscription = await resp.json();
require "net/http"
require "json"
uri = URI("https://yourshop.zeroshop.io/admin/api/orders/482/activate-subscription")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer zspat_..."
req["Content-Type"] = "application/json"
req.body = {
external_subscription_id: "sub_1NQabcXYZ0123",
external_customer_id: "cus_1NQabcXYZ0123"
}.to_json
resp = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
subscription = JSON.parse(resp.body)
/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.
| Name | Type | Required | Description |
|---|---|---|---|
| order_id | integer | required | Order ID |
[
{
"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"
}
]
curl "https://yourshop.zeroshop.io/admin/api/orders/482/payments" \
-H "Authorization: Bearer zspat_..."
import requests
resp = requests.get(
"https://yourshop.zeroshop.io/admin/api/orders/482/payments",
headers={"Authorization": "Bearer zspat_..."}
)
payments = resp.json()
const resp = await fetch("https://yourshop.zeroshop.io/admin/api/orders/482/payments", {
headers: { "Authorization": "Bearer zspat_..." }
});
const payments = await resp.json();
require "net/http"
require "json"
uri = URI("https://yourshop.zeroshop.io/admin/api/orders/482/payments")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer zspat_..."
resp = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
payments = JSON.parse(resp.body)
/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.
| Name | Type | Required | Description |
|---|---|---|---|
| order_id | integer | required | Order ID |
{
"label": "Deposit",
"amount_cents": 5000,
"paid": true,
"note": "Paid in cash at counter",
"sort_order": 0
}
{
"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"
}
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"}'
import requests
resp = requests.post(
"https://yourshop.zeroshop.io/admin/api/orders/482/payments",
headers={"Authorization": "Bearer zspat_..."},
json={"label": "Deposit", "amount_cents": 5000, "paid": True, "note": "Paid in cash at counter"}
)
payment = resp.json()
const resp = await fetch("https://yourshop.zeroshop.io/admin/api/orders/482/payments", {
method: "POST",
headers: {
"Authorization": "Bearer zspat_...",
"Content-Type": "application/json"
},
body: JSON.stringify({ label: "Deposit", amount_cents: 5000, paid: true, note: "Paid in cash at counter" })
});
const payment = await resp.json();
require "net/http"
require "json"
uri = URI("https://yourshop.zeroshop.io/admin/api/orders/482/payments")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer zspat_..."
req["Content-Type"] = "application/json"
req.body = { label: "Deposit", amount_cents: 5000, paid: true, note: "Paid in cash at counter" }.to_json
resp = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
payment = JSON.parse(resp.body)
/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.
| Name | Type | Required | Description |
|---|---|---|---|
| order_id | integer | required | Order ID |
{
"items": [
{
"id": 10,
"sort_order": 0
},
{
"id": 9,
"sort_order": 1
}
]
}
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}]}'
import requests
resp = requests.post(
"https://yourshop.zeroshop.io/admin/api/orders/482/payments/reorder",
headers={"Authorization": "Bearer zspat_..."},
json={"items": [{"id": 10, "sort_order": 0}, {"id": 9, "sort_order": 1}]}
)
# 204 No Content on success
await fetch("https://yourshop.zeroshop.io/admin/api/orders/482/payments/reorder", {
method: "POST",
headers: {
"Authorization": "Bearer zspat_...",
"Content-Type": "application/json"
},
body: JSON.stringify({ items: [{ id: 10, sort_order: 0 }, { id: 9, sort_order: 1 }] })
});
// 204 No Content on success
require "net/http"
require "json"
uri = URI("https://yourshop.zeroshop.io/admin/api/orders/482/payments/reorder")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer zspat_..."
req["Content-Type"] = "application/json"
req.body = { items: [{ id: 10, sort_order: 0 }, { id: 9, sort_order: 1 }] }.to_json
Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
# 204 No Content on success
/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.
| Name | Type | Required | Description |
|---|---|---|---|
| order_id | integer | required | Order ID |
| id | integer | required | Payment record ID |
{
"paid": true
}
{
"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"
}
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}'
import requests
resp = requests.patch(
"https://yourshop.zeroshop.io/admin/api/orders/482/payments/10",
headers={"Authorization": "Bearer zspat_..."},
json={"paid": True}
)
payment = resp.json()
const resp = await fetch("https://yourshop.zeroshop.io/admin/api/orders/482/payments/10", {
method: "PATCH",
headers: {
"Authorization": "Bearer zspat_...",
"Content-Type": "application/json"
},
body: JSON.stringify({ paid: true })
});
const payment = await resp.json();
require "net/http"
require "json"
uri = URI("https://yourshop.zeroshop.io/admin/api/orders/482/payments/10")
req = Net::HTTP::Patch.new(uri)
req["Authorization"] = "Bearer zspat_..."
req["Content-Type"] = "application/json"
req.body = { paid: true }.to_json
resp = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
payment = JSON.parse(resp.body)
/admin/api/orders/{order_id}/payments/{id}
Delete a partial payment record. The order's payment_status is recomputed after the delete.
| Name | Type | Required | Description |
|---|---|---|---|
| order_id | integer | required | Order ID |
| id | integer | required | Payment record ID |
curl -X DELETE "https://yourshop.zeroshop.io/admin/api/orders/482/payments/10" \
-H "Authorization: Bearer zspat_..."
import requests
resp = requests.delete(
"https://yourshop.zeroshop.io/admin/api/orders/482/payments/10",
headers={"Authorization": "Bearer zspat_..."}
)
assert resp.status_code == 204
await fetch("https://yourshop.zeroshop.io/admin/api/orders/482/payments/10", {
method: "DELETE",
headers: { "Authorization": "Bearer zspat_..." }
});
// 204 No Content
require "net/http"
uri = URI("https://yourshop.zeroshop.io/admin/api/orders/482/payments/10")
req = Net::HTTP::Delete.new(uri)
req["Authorization"] = "Bearer zspat_..."
Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
# 204 No Content
/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.
| Name | Type | Required | Description |
|---|---|---|---|
| order_id | integer | required | Order ID |
{
"provider_shipment_id": "BN-1234567890"
}
{
"id": 17
}
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"}'
import requests
resp = requests.post(
"https://yourshop.zeroshop.io/admin/api/orders/482/shipments/boxnow",
headers={"Authorization": "Bearer zspat_..."},
json={"provider_shipment_id": "BN-1234567890"}
)
shipment = resp.json()
const resp = await fetch("https://yourshop.zeroshop.io/admin/api/orders/482/shipments/boxnow", {
method: "POST",
headers: {
"Authorization": "Bearer zspat_...",
"Content-Type": "application/json"
},
body: JSON.stringify({ provider_shipment_id: "BN-1234567890" })
});
const shipment = await resp.json();
require "net/http"
require "json"
uri = URI("https://yourshop.zeroshop.io/admin/api/orders/482/shipments/boxnow")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer zspat_..."
req["Content-Type"] = "application/json"
req.body = { provider_shipment_id: "BN-1234567890" }.to_json
resp = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
shipment = JSON.parse(resp.body)
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.