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

FieldSample ValueReq/OptDescription
source{}requiredSource of the sale. See source object below.
state"closed"requiredState of the sale. One of: parked, pending, closed, voided. More about states and attributes.
date"2016-05-05T23:35:34Z"optionalSale timestamp in RFC3339 format. Defaults to the time the request is received.
customer_id"06e35f89-..."optionalID of the customer associated with this sale.
attributes["delivery"]optionalArray of sale attributes. Valid values: onaccount, layby, delivery, pickup, service. More about states and attributes.
note"VIP customer"optionalA note on the sale entered by the cashier.
short_code"mlzs94"optionalShort unique code used for loyalty tracking purposes. Must be unique if provided.
invoice_number"MR-1484-NZ"optionalInvoice number. If omitted, one will be assigned automatically.
pricing{}optionalSale-level pricing including adjustments.
line_items[]optionalArray 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[]optionalArray of payments. See payment object below.
fulfillment_details[]optionalFulfillment details for DISPATCH or PICKUP sales. See fulfillment details below.
_metadata{}optionalAdditional metadata. See metadata object below.

The source object

FieldSample ValueReq/OptDescription
author_id"020b2c2a-..."requiredID of the user (cashier) who created the sale. Retrieve from /api/2026-01/users.
register_id"b1e198a9-..."optionalID of the register where the sale was created.
id"EXT-001"optionalID of the sale in an external system.
type"Magento"optionalIdentifier of the external system the id belongs to.

The line item object

FieldSample ValueReq/OptDescription
product.id"5d4fcfa8-..."requiredID of the product.
quantity1requiredQuantity of the product.
pricing.price22requiredUnit price of the line item, tax exclusive.
pricing.cost20optionalUnit cost used for margin calculations.
pricing.discount0optionalDiscount value for the line item.
pricing.loyalty_amount2.0optionalLoyalty value to be added to the customer's balance.
tax.id"b1d192bc-..."requiredID of the tax. Retrieve from /api/2026-01/taxes. For tax-free items use the ID of the tax named "No Tax".
tax.amount3.3requiredUnit tax value for the line item.
status"CONFIRMED"optionalSet to CONFIRMED to make the line item read-only for pending sales.
source.author_id"b1ed6158-..."optionalID of the salesperson for this line item. Only needed when different from the sale author.
source.register_id"b1e198a9-..."optionalID of the register used to add this line item.

The payment object

FieldSample ValueReq/OptDescription
type.config_id"dd4d174f-..."requiredPayment type ID. Retrieve from /api/2026-01/payment_types.
amount25.3requiredPayment amount.
date"2016-05-05T23:35:34Z"optionalPayment timestamp in RFC3339 format. Defaults to the time of the request.
source.register_id"b1e198a9-..."optionalID of the register where the payment was accepted.

Fulfillment details

Required for dispatch (delivery attribute) or pickup (pickup attribute) sales.

FieldSample ValueReq/OptDescription
type"DISPATCH"optionalFulfillment type. One of: DISPATCH, PICKUP.
note"Leave at door"optionalA note for the fulfillment.
shipping_address_id"2031472964637822976"optionalID of the shipping address for DISPATCH fulfillments.
shipping_address_token"CB3K47K3ZZ8g..."optionalToken of a newly created shipping address. Use instead of shipping_address_id when the address was just created.

Metadata

FieldSample ValueReq/OptDescription
_metadata.xero_reference"INV-001"optionalXero invoice reference ID. Only editable for onaccount sales.
_metadata.invoice.sequence1484optionalNumeric part of the invoice number.
_metadata.invoice.resolve_numbertrueoptionalWhether 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 1 to 2) — identified by its id.
  • The second line item is new — no id, so it will be appended.
  • The payment is updated (amount changed from 25.3 to 50.6) — identified by its id.