On this page
- Endpoints
- List draft orders
- Query parameters
- Request
- Response 200
- Create a draft order
- Request body
- Request
- Response 201
- Get a draft order
- Query parameters
- Request
- Response 200
- Update a draft order
- Request body
- Request
- Response 200
- Delete a draft order
- Request
- Response 204
- Add items to a draft order
- Request body
- Request
- Response 201
- Update a line item
- Request body
- Request
- Response 200
- Remove a line item
- Request
- Response 204
- Complete a draft order
- Request
- Response 201
- Error 400 – validation failure
- Send payment request
- Request body (optional)
- Request
- Response 200
- Webhooks
- The draft order object
- The draft order line item object
Draft Orders
Draft orders are merchant-initiated orders that haven’t been finalized. The merchant builds them incrementally — adding items, setting a customer, adjusting pricing — then completes the draft, which creates a real order with inventory deduction and order number assignment.
Draft orders support both variant-based items (resolved from your product catalog) and custom items (freeform title and price with no variant reference).
Base URL: https://api.hydrajs.dev
Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/v1/draft-orders |
Secret | List draft orders |
POST |
/v1/draft-orders |
Secret | Create a draft order |
GET |
/v1/draft-orders/{id} |
Secret | Get a draft order |
PATCH |
/v1/draft-orders/{id} |
Secret | Update a draft order |
DELETE |
/v1/draft-orders/{id} |
Secret | Delete a draft order |
POST |
/v1/draft-orders/{id}/items |
Secret | Add line items |
PATCH |
/v1/draft-orders/{id}/items/{item_id} |
Secret | Update a line item |
DELETE |
/v1/draft-orders/{id}/items/{item_id} |
Secret | Remove a line item |
POST |
/v1/draft-orders/{id}/complete |
Secret | Complete draft into a real order |
POST |
/v1/draft-orders/{id}/send |
Secret | Send payment request to customer |
List draft orders
GET /v1/draft-orders
Returns a paginated list of draft orders. Supports filtering by status and customer email.
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
limit |
integer | 25 |
Results per page (1–100) |
cursor |
string | – | Pagination cursor from a previous response |
sort |
string | created_at |
Sort field: created_at, updated_at |
order |
string | desc |
Sort direction: asc, desc |
status |
string | – | Filter by status: open, sent, completed |
customer_email |
string | – | Filter by customer email |
expand |
string | – | Comma-separated: items |
fields |
string | – | Comma-separated fields to return |
Request
curl https://api.hydrajs.dev/v1/draft-orders?status=open&limit=10 \
-H "Authorization: Bearer sk_live_YOUR_KEY"
Response 200
{
"data": [
{
"id": "dord_abc123",
"status": "open",
"customer_id": null,
"customer_email": null,
"subtotal": 5998,
"tax": 0,
"tax_data": null,
"tax_inclusive": false,
"shipping_cost": 0,
"discount": 0,
"total": 5998,
"currency": "USD",
"order_id": null,
"completed_at": null,
"item_count": 2,
"notes": null,
"metadata": {},
"created_at": "2026-08-20T10:00:00Z",
"updated_at": "2026-08-20T10:05:00Z"
}
],
"pagination": {
"cursor": "eyJ0IjoiMjAyNi...",
"has_more": false,
"total": 1
}
}
Create a draft order
POST /v1/draft-orders
Creates a new empty draft order. Line items are added separately via the add-items endpoint.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
currency |
string | Yes | 3-letter ISO currency code |
customer_id |
string | No | Link to an existing customer |
customer_email |
string | No | Customer email address |
shipping_address |
object | No | Shipping address |
billing_address |
object | No | Billing address |
notes |
string | No | Internal notes (max 5,000 chars) |
metadata |
object | No | Arbitrary key-value pairs (max 50 keys) |
Request
curl -X POST https://api.hydrajs.dev/v1/draft-orders \
-H "Authorization: Bearer sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"currency": "USD",
"customer_email": "jane@example.com"
}'
Response 201
{
"data": {
"id": "dord_abc123",
"draft_number": 1,
"status": "open",
"customer_id": null,
"customer_email": "jane@example.com",
"subtotal": 0,
"tax": 0,
"tax_data": null,
"tax_inclusive": false,
"shipping_cost": 0,
"discount": 0,
"total": 0,
"currency": "USD",
"shipping_address": null,
"billing_address": null,
"notes": null,
"payment_terms": "due_on_receipt",
"payment_due_date": null,
"order_id": null,
"completed_at": null,
"item_count": 0,
"metadata": {},
"created_at": "2026-08-20T10:00:00Z",
"updated_at": "2026-08-20T10:00:00Z"
}
}
Get a draft order
GET /v1/draft-orders/{id}
Returns a single draft order. Use ?expand=items to include line items inline.
Query parameters
| Parameter | Type | Description |
|---|---|---|
expand |
string | Comma-separated: items |
fields |
string | Comma-separated fields to return |
Request
curl https://api.hydrajs.dev/v1/draft-orders/dord_abc123?expand=items \
-H "Authorization: Bearer sk_live_YOUR_KEY"
Response 200
{
"data": {
"id": "dord_abc123",
"status": "open",
"customer_id": "cus_xyz789",
"customer_email": "jane@example.com",
"subtotal": 5998,
"tax": 480,
"tax_data": null,
"tax_inclusive": false,
"shipping_cost": 599,
"discount": 0,
"total": 7077,
"currency": "USD",
"shipping_address": null,
"billing_address": null,
"order_id": null,
"completed_at": null,
"item_count": 2,
"notes": "Phone order for Jane",
"metadata": {},
"items": [
{
"id": "doli_aaa111",
"draft_order_id": "dord_abc123",
"product_id": "prod_abc123",
"variant_id": "var_def456",
"title": "Classic T-Shirt",
"variant_title": "Medium / Black",
"sku": "TS-MD-BLK",
"quantity": 2,
"unit_price": 2999,
"total": 5998,
"is_custom": false,
"note": null,
"created_at": "2026-08-20T10:01:00Z"
}
],
"created_at": "2026-08-20T10:00:00Z",
"updated_at": "2026-08-20T10:05:00Z"
}
}
Update a draft order
PATCH /v1/draft-orders/{id}
Updates draft order fields. Recalculates the total when tax, shipping, or discount change.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
customer_id |
string | null | No | Customer ID (null to clear) |
customer_email |
string | null | No | Customer email (null to clear) |
currency |
string | No | 3-letter ISO currency code (only changeable when item_count=0) |
shipping_address |
object | null | No | Shipping address (null to clear) |
billing_address |
object | null | No | Billing address (null to clear) |
tax |
integer | No | Tax amount in cents (ignored when tax calculation is enabled) |
shipping_cost |
integer | No | Shipping cost in cents |
discount |
integer | No | Discount amount in cents |
notes |
string | null | No | Internal notes (null to clear) |
metadata |
object | No | Arbitrary key-value pairs |
Request
curl -X PATCH https://api.hydrajs.dev/v1/draft-orders/dord_abc123 \
-H "Authorization: Bearer sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"tax": 480,
"shipping_cost": 599,
"notes": "Phone order for Jane"
}'
Response 200
Returns the updated draft order object.
Delete a draft order
DELETE /v1/draft-orders/{id}
Permanently deletes a draft order and its line items. Completed drafts cannot be deleted.
Request
curl -X DELETE https://api.hydrajs.dev/v1/draft-orders/dord_abc123 \
-H "Authorization: Bearer sk_live_YOUR_KEY"
Response 204
No response body.
Add items to a draft order
POST /v1/draft-orders/{id}/items
Adds one or more line items. Supports two types: variant-based items (price resolved from the variant) and custom items (freeform title and price).
Request body
| Field | Type | Required | Description |
|---|---|---|---|
items |
object[] | Yes | Array of items (1–100) |
Each item is one of:
Variant-based item:
| Field | Type | Required | Description |
|---|---|---|---|
variant_id |
string | Yes | Variant to add |
quantity |
integer | Yes | Quantity (1–999) |
Custom item:
| Field | Type | Required | Description |
|---|---|---|---|
title |
string | Yes | Custom item name |
unit_price |
integer | Yes | Price in cents |
quantity |
integer | Yes | Quantity (1–999) |
Request
curl -X POST https://api.hydrajs.dev/v1/draft-orders/dord_abc123/items \
-H "Authorization: Bearer sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"items": [
{ "variant_id": "var_def456", "quantity": 2 },
{ "title": "Gift wrapping", "unit_price": 500, "quantity": 1 }
]
}'
Response 201
{
"data": [
{
"id": "doli_aaa111",
"draft_order_id": "dord_abc123",
"product_id": "prod_abc123",
"variant_id": "var_def456",
"title": "Classic T-Shirt",
"variant_title": "Medium / Black",
"sku": "TS-MD-BLK",
"quantity": 2,
"unit_price": 2999,
"total": 5998,
"is_custom": false,
"note": null,
"created_at": "2026-08-20T10:01:00Z"
},
{
"id": "doli_bbb222",
"draft_order_id": "dord_abc123",
"product_id": null,
"variant_id": null,
"title": "Gift wrapping",
"variant_title": "",
"sku": null,
"quantity": 1,
"unit_price": 500,
"total": 500,
"is_custom": true,
"note": null,
"created_at": "2026-08-20T10:01:00Z"
}
]
}
ℹSubtotal recalculation
Adding items automatically recalculates the draft order’s subtotal and total. You don’t need to update these values manually.
Update a line item
PATCH /v1/draft-orders/{id}/items/{item_id}
Updates a line item’s quantity, note, and (for custom items only) price and title. Variant-based items only allow quantity and note changes — use the order-level discount field for price adjustments.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
quantity |
integer | No | New quantity (1–999) |
unit_price |
integer | No | New price in cents (custom items only) |
title |
string | No | New title (custom items only) |
note |
string | null | No | Per-item note (max 1,000 chars) |
Request
curl -X PATCH https://api.hydrajs.dev/v1/draft-orders/dord_abc123/items/doli_aaa111 \
-H "Authorization: Bearer sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "quantity": 3 }'
Response 200
Returns the updated line item object.
⚠Variant item restrictions
Attempting to update unit_price or title on a variant-based line item returns a 400 error.
Variant prices are resolved from the product catalog and cannot be overridden on individual items.
Remove a line item
DELETE /v1/draft-orders/{id}/items/{item_id}
Removes a line item and recalculates the draft order’s subtotal and total.
Request
curl -X DELETE https://api.hydrajs.dev/v1/draft-orders/dord_abc123/items/doli_aaa111 \
-H "Authorization: Bearer sk_live_YOUR_KEY"
Response 204
No response body.
Complete a draft order
POST /v1/draft-orders/{id}/complete
Completes a draft order by creating a real order. This is the key operation — it:
- Validates the draft has a customer email and at least one line item
- Creates a real order via the order creation pipeline (advisory-locked order numbering, platform fee)
- Deducts inventory for variant-based items (custom items have no inventory impact)
- Sets the draft’s status to
completedand links it to the new order - Dispatches
draft_order.completedandorder.createdwebhook events
⚠Irreversible
Completing a draft order cannot be undone. Inventory is deducted and an order number is assigned permanently.
Request
curl -X POST https://api.hydrajs.dev/v1/draft-orders/dord_abc123/complete \
-H "Authorization: Bearer sk_live_YOUR_KEY"
Response 201
Returns the created order object (same shape as POST /v1/orders).
Error 400 – validation failure
{
"error": {
"code": "invalid_request",
"message": "Draft order must have a customer email before completing."
}
}
Send payment request
POST /v1/draft-orders/{id}/send
Sends a payment request email to the customer and marks the draft order’s status as sent. The email includes the full order details (line items, totals, addresses) and a “Pay now” button linking to checkout if the store has a verified domain.
The draft must be open with a customer email and at least one line item.
Request body (optional)
| Field | Type | Description |
|---|---|---|
subject |
string | Override the default email subject line. Max 200 characters. |
message |
string | Custom message displayed above the order summary. Max 5,000 characters. |
cc |
string[] | CC recipients (up to 5 email addresses). Visible to all recipients. |
bcc |
string[] | BCC recipients (up to 5 email addresses). Hidden from other recipients. |
All fields are optional. If omitted, the default subject (“Order #{draft_number} from {store}”) and body are used.
Request
curl -X POST https://api.hydrajs.dev/v1/draft-orders/dord_abc123/send \
-H "Authorization: Bearer sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"subject": "Your order from My Store",
"message": "Here are the details of the order we discussed.",
"cc": ["sales@example.com"]
}'
Response 200
Returns the updated draft order with status: "sent".
Webhooks
Draft order changes fire the following webhook events:
| Event | Trigger |
|---|---|
draft_order.created |
Draft order created |
draft_order.updated |
Draft order fields or line items changed |
draft_order.completed |
Draft completed into a real order |
draft_order.deleted |
Draft order deleted |
Completing a draft also fires order.created and potentially inventory.low for the resulting order.
See Webhooks for subscription setup.
The draft order object
| Field | Type | Description |
|---|---|---|
id |
string | Unique ID (prefix: dord_) |
status |
string | open, sent, completed |
customer_id |
string | null | Linked customer ID |
customer_email |
string | null | Customer email (required before completion) |
subtotal |
integer | Sum of line item totals, in cents |
tax |
integer | Tax amount in cents (auto-calculated when tax calculation is enabled) |
tax_data |
object | null | Tax breakdown (total_tax, tax_inclusive, source, tax_lines[]) |
tax_inclusive |
boolean | Whether tax is included in item prices |
shipping_cost |
integer | Shipping cost in cents |
discount |
integer | Discount amount in cents |
total |
integer | Grand total in cents (subtotal + tax + shipping - discount) |
currency |
string | 3-letter ISO currency code |
shipping_address |
object | null | Shipping address |
billing_address |
object | null | Billing address |
order_id |
string | null | Linked order ID (set when completed) |
completed_at |
string | null | ISO 8601 timestamp of completion |
item_count |
integer | Number of line items |
notes |
string | null | Internal notes |
metadata |
object | Arbitrary key-value pairs |
items |
object[] | Expanded with ?expand=items |
created_at |
string | ISO 8601 timestamp |
updated_at |
string | ISO 8601 timestamp |
The draft order line item object
| Field | Type | Description |
|---|---|---|
id |
string | Unique ID (prefix: doli_) |
draft_order_id |
string | Parent draft order ID |
product_id |
string | null | Product ID (null for custom items) |
variant_id |
string | null | Variant ID (null for custom items) |
title |
string | Product or custom item title |
variant_title |
string | Variant title (empty string for custom items) |
sku |
string | null | SKU at time of addition |
quantity |
integer | Item quantity |
unit_price |
integer | Price per unit in cents |
total |
integer | quantity x unit_price |
is_custom |
boolean | true for freeform items with no variant |
note |
string | null | Per-item note |
created_at |
string | ISO 8601 timestamp |