Sales 101
Sales 101
Sales can be created by making a POST request to the /api/2026-01/sales endpoint. This guide covers the payloads that can be used to create a sale.
The endpoint returns the id of the created sale. To update an existing sale, use PUT /api/2026-01/sales/{id}.
Minimal payload
Here's a minimal payload to create a valid closed sale:
{
"source": {
"author_id": "020b2c2a-4661-11f0-e88b-1afde45e0728"
},
"state": "closed",
"line_items": [{
"product": {
"id": "5d4fcfa8-0ac1-4a6a-adc2-da1d66f4b8f7"
},
"quantity": 1,
"pricing": {
"price": "12"
},
"tax": {
"id": "b1d192bc-f019-11e3-a0f5-b8ca3a64f8f4",
"amount": "1.8"
}
}]
}Full payload with explanation
{
"source": {
"register_id": "b1e198a9-f019-11e3-a0f5-b8ca3a64f8f4",
"author_id": "020b2c2a-4661-11f0-e88b-1afde45e0728"
},
"date": "2016-05-05T23:35:34Z",
"customer_id": "06e35f89-3783-11e6-ec7e-13193f7bd2ed",
"state": "closed",
"attributes": [],
"note": "",
"short_code": "mlzs94",
"invoice_number": "MR-1484-NZ",
"line_items": [{
"product": {
"id": "5d4fcfa8-0ac1-4a6a-adc2-da1d66f4b8f7"
},
"quantity": 1,
"pricing": {
"price": "22",
"cost": "20",
"discount": "0",
"loyalty_amount": "0"
},
"tax": {
"id": "b1d192bc-f019-11e3-a0f5-b8ca3a64f8f4",
"amount": "3.3"
},
"status": "CONFIRMED"
}],
"payments": [{
"type": {
"config_id": "dd4d174f-669d-4483-972a-1484242e1227"
},
"date": "2016-05-05T23:35:34Z",
"amount": "25.3"
}]
}Definitions
The sale object
| Field | Sample Value | Req/Opt | Description |
|---|---|---|---|
source | {} | required | Source of the sale. See source object below. |
state | "closed" | required | State of the sale. One of: parked, pending, closed, voided. More about states and attributes. |
date | "2016-05-05T23:35:34Z" | optional | Sale timestamp in RFC3339 format. Defaults to the time the request is received. |
customer_id | "06e35f89-..." | optional | ID of the customer associated with this sale. |
attributes | ["delivery"] | optional | Array of sale attributes. Valid values: onaccount, layby, delivery, pickup, service. More about states and attributes. |
note | "VIP customer" | optional | A note on the sale entered by the cashier. |
short_code | "mlzs94" | optional | Short unique code used for loyalty tracking purposes. Must be unique if provided. |
invoice_number | "MR-1484-NZ" | optional | Invoice number. If omitted, one will be assigned automatically. |
pricing | {} | optional | Sale-level pricing including adjustments. |
line_items | [] | optional | Array of line items. See line item object below. When updating a sale, all existing line items must be included or they will be deleted. |
payments | [] | optional | Array of payments. See payment object below. |
fulfillment_details | [] | optional | Fulfillment details for DISPATCH or PICKUP sales. See fulfillment details below. |
_metadata | {} | optional | Additional metadata. See metadata object below. |
The source object
| Field | Sample Value | Req/Opt | Description |
|---|---|---|---|
author_id | "020b2c2a-..." | required | ID of the user (cashier) who created the sale. Retrieve from /api/2026-01/users. |
register_id | "b1e198a9-..." | optional | ID of the register where the sale was created. |
id | "EXT-001" | optional | ID of the sale in an external system. |
type | "Magento" | optional | Identifier of the external system the id belongs to. |
The line item object
| Field | Sample Value | Req/Opt | Description |
|---|---|---|---|
product.id | "5d4fcfa8-..." | required | ID of the product. |
quantity | 1 | required | Quantity of the product. |
pricing.price | 22 | required | Unit price of the line item, tax exclusive. |
pricing.cost | 20 | optional | Unit cost used for margin calculations. |
pricing.discount | 0 | optional | Discount value for the line item. |
pricing.loyalty_amount | 2.0 | optional | Loyalty value to be added to the customer's balance. |
tax.id | "b1d192bc-..." | required | ID of the tax. Retrieve from /api/2026-01/taxes. For tax-free items use the ID of the tax named "No Tax". |
tax.amount | 3.3 | required | Unit tax value for the line item. |
status | "CONFIRMED" | optional | Set to CONFIRMED to make the line item read-only for pending sales. |
source.author_id | "b1ed6158-..." | optional | ID of the salesperson for this line item. Only needed when different from the sale author. |
source.register_id | "b1e198a9-..." | optional | ID of the register used to add this line item. |
The payment object
| Field | Sample Value | Req/Opt | Description |
|---|---|---|---|
type.config_id | "dd4d174f-..." | required | Payment type ID. Retrieve from /api/2026-01/payment_types. |
amount | 25.3 | required | Payment amount. |
date | "2016-05-05T23:35:34Z" | optional | Payment timestamp in RFC3339 format. Defaults to the time of the request. |
source.register_id | "b1e198a9-..." | optional | ID of the register where the payment was accepted. |
Fulfillment details
Required for dispatch (delivery attribute) or pickup (pickup attribute) sales.
| Field | Sample Value | Req/Opt | Description |
|---|---|---|---|
type | "DISPATCH" | optional | Fulfillment type. One of: DISPATCH, PICKUP. |
note | "Leave at door" | optional | A note for the fulfillment. |
shipping_address_id | "2031472964637822976" | optional | ID of the shipping address for DISPATCH fulfillments. |
shipping_address_token | "CB3K47K3ZZ8g..." | optional | Token of a newly created shipping address. Use instead of shipping_address_id when the address was just created. |
Metadata
| Field | Sample Value | Req/Opt | Description |
|---|---|---|---|
_metadata.xero_reference | "INV-001" | optional | Xero invoice reference ID. Only editable for onaccount sales. |
_metadata.invoice.sequence | 1484 | optional | Numeric part of the invoice number. |
_metadata.invoice.resolve_number | true | optional | Whether to resolve the invoice number automatically. |
Taxes
The tax.amount and tax.id must always be provided for each line item.
Tax IDs can be retrieved from /api/2026-01/taxes. All retailers have a special tax named "No Tax" for tax-free items — use its id with "amount": 0.
Response
The endpoint returns the id of the created sale:
{
"data": {
"id": "506e5602-0a02-a9f1-11ec-d53d3e8661a6"
}
}Use GET /api/2026-01/sales/{id} to retrieve the full sale object.
Updating a sale
To update an existing sale, use PUT /api/2026-01/sales/{id}. The payload is identical to the POST request but without the sale id in the body — it is provided in the URL instead.
Updating line items and payments
To update an existing line item or payment, you must include its id in the payload. Without the id, a new line item or payment will be appended to the sale instead.
To get the id values of existing line items and payments, first call GET /api/2026-01/sales/{id}.
{
"source": {
"register_id": "b1e198a9-f019-11e3-a0f5-b8ca3a64f8f4",
"author_id": "020b2c2a-4661-11f0-e88b-1afde45e0728"
},
"state": "closed",
"line_items": [
{
"id": "506e5602-0a02-a9f1-11ec-d53d576e4448",
"product": { "id": "5d4fcfa8-0ac1-4a6a-adc2-da1d66f4b8f7" },
"quantity": 2,
"pricing": { "price": "22", "cost": "20", "discount": "0", "loyalty_amount": "0" },
"tax": { "id": "b1d192bc-f019-11e3-a0f5-b8ca3a64f8f4", "amount": "3.3" },
"status": "CONFIRMED"
},
{
"product": { "id": "5d4fcfa8-0ac1-4a6a-adc2-da1d66f4b8f7" },
"quantity": 1,
"pricing": { "price": "22", "cost": "20", "discount": "0", "loyalty_amount": "0" },
"tax": { "id": "b1d192bc-f019-11e3-a0f5-b8ca3a64f8f4", "amount": "3.3" },
"status": "CONFIRMED"
}
],
"payments": [
{
"id": "506e5602-0a02-a9f1-11ec-d53d81003442",
"type": { "config_id": "dd4d174f-669d-4483-972a-1484242e1227" },
"date": "2016-05-05T23:35:34Z",
"amount": "50.6"
}
]
}In the example above:
- The first line item is updated (quantity changed from
1to2) — identified by itsid. - The second line item is new — no
id, so it will be appended. - The payment is updated (amount changed from
25.3to50.6) — identified by itsid.
Updated 12 days ago
