Zum Hauptinhalt springen
Omneya
EN
Start test system Try it
Developer docs menu

Orders

Create orders from your app, check an order without creating it, read an order of your shop or change it.

Create an order

POST /orders

Scope: orders.write

Creates an order from your app. The order is created in the shop assigned to your API client.

Duplicate protection. external_order_id is unique per API client. Sending the same number again never creates a second order, not even for two simultaneous requests. The repeat answers 200 with duplicate: true and the current state of the existing order. After a connection error, a timeout, 429 or 5xx, resend the unchanged request (doubling the wait, for example 2, 4, 8 seconds; respect Retry-After on 429). Do not resend unchanged after 422 or 409.

Customer matching.

  1. Our customer number (customer.customer_id) of an active, registered customer in your shop, or your customer ID (customer.external_id) if it was used before through your client: the order goes to that customer. Only the ID is then needed; the email comes from the stored customer, the billing address is the customer's default billing address (the one marked as default for invoices in the address book, otherwise the main customer address). A billing sent anyway applies to this order only and does not change the stored customer.
  2. Email: only if the shop operator enabled matching by email for your client and you send email_verified: true. Then a registered, active customer with this email in your shop is used. Guest and blocked customers are never matched. Send email_verified: true only for emails you actually confirmed.
  3. Otherwise a new customer is created.

Prices. A sent unit_price_gross is used as a fixed price; without it, the shop's own price applies. A customer class discount may apply to the order, also to sent prices, so the grand_total_gross in the response is authoritative. A sent shipping_cost_gross applies (also 0); without it, shipping costs are calculated by the shop's rules.

After creation. The order starts in the shop's incoming order status, or directly in the status you send as order_status_id. Stock is reserved and the shop's usual processes start (confirmation email, payment, shipping). Orders sent with a test key (omn_test_...) are created normally and marked as test orders.

Guarantee. If the response is an error, nothing was created: no order and no customer.

Request body

Field Type Required Description
external_order_id string required Your order number. Unique per API client and case-sensitive. The same number never creates a second order. max length 191
ordered_at string | null optional Time of the order. Use ISO 8601 with a time zone (Z or +02:00). Must not be in the future and at most 30 days in the past. Without it, the time of receipt is used.
payment_method_id integer required ID of a payment method from listPaymentMethods. Any other ID is rejected with payment_method_not_available (or unknown_payment_method if it is not active). For the collective invoice, the customer must also be approved for it.
referrer_id integer | null optional ID of a referrer (order origin). Must be active and assigned to the shop of your API client (see listReferrers). Without it, the default referrer of your API client is used.
order_status_id integer | null optional ID of an order status from listOrderStatuses. The order is created directly in this status; every status of the shop is accepted, including cancelled and shipped statuses. Without it, the order starts in the shop's incoming order status. Any other ID is rejected with unknown_order_status.
currency string required Currency code. Only EUR is supported. one of: EUR · min length 3 · max length 3
comment string | null optional Message of the customer about the order. max length 2000
shipping_cost_gross number | null optional Shipping costs including tax, at most 2 decimal places. If sent, it applies (also 0). If missing, shipping costs are calculated by the shop's rules. min 0 · max 999999.99 · multiple of 0.01
customer object required The customer of the order. For an existing customer, the ID alone is enough ({"external_id": "u-55871"} or {"customer_id": 9021}). For a new customer, email and billing are required.
external_id string | null optional Your customer ID. Required unless customer_id is sent. Case-sensitive; the same ID always leads to the same customer. max length 191
customer_id integer | null optional Our customer number, for example from data.customer_id of an earlier response or given to you by the shop operator. Any active, registered customer of your shop can be referenced; guest, blocked or deleted customers and customers of other shops fail with unknown_customer. Referencing a customer by number does not link your external_id to it. min 1
id integer | null optional Same as customer_id. If both are sent, they must have the same value, otherwise the request fails with invalid_value on customer.id. Errors about the customer number are reported on customer.customer_id. min 1
email string (email) | null optional Email address. Required for a new customer. max length 191
email_verified boolean | null optional true if you confirmed the email (for example by a link). Only then can the order be matched to an existing customer by email, and only if the shop operator enabled this for your client. default false
telephone string | null optional Phone number. max length 191
billing object | null optional Billing address. Required for a new customer. For a known customer it applies to this order only; the stored customer is not changed.
shipping object | null optional Delivery address. If missing, null or {}, the order is delivered to the billing address. A sent delivery address is stored in the order and added to the customer's address book (the same address only once).
items[] array of object required Order items, 1 to 200. min 1 items · max 200 items
sku string | null optional Our article number. Not case-sensitive. max length 191
article_id integer | null optional Our number of the main article. All variants of an article (for example sizes) share this number; for articles with variants use sku. min 1
quantity integer required min 1 · max 9999
unit_price_gross number | null optional Unit price including tax, at most 2 decimal places. If sent, it is used as a fixed price; if missing, the shop's price applies. min 0 · max 999999.99 · multiple of 0.01

Example request

curl -X POST "https://shop.example.com/api/v1/orders" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "external_order_id": "APP-100234",
  "ordered_at": "2026-10-14T12:05:00Z",
  "payment_method_id": 3,
  "referrer_id": 17,
  "currency": "EUR",
  "comment": "Please ring the bell",
  "shipping_cost_gross": 4.9,
  "customer": {
    "external_id": "u-55871",
    "email": "alex.sample@example.com",
    "email_verified": true,
    "telephone": "+49 30 0000000",
    "billing": {
      "salutation": "Mr",
      "first_name": "Alex",
      "last_name": "Sample",
      "street": "Sample Street",
      "house": "5",
      "additional": "2nd floor",
      "postcode": "10115",
      "city": "Berlin",
      "country": "DE"
    },
    "shipping": {
      "first_name": "Alex",
      "last_name": "Sample",
      "street": "Packstation",
      "house": "123",
      "postcode": "10117",
      "city": "Berlin",
      "country": "DE",
      "telephone": "+49 170 0000000",
      "packstation": true,
      "postnumber": "12345678"
    }
  },
  "items": [
    {
      "sku": "SAMPLE-1KG",
      "quantity": 2,
      "unit_price_gross": 29.9
    },
    {
      "article_id": 101683,
      "quantity": 1
    }
  ]
}'

Responses

200 OK An order with this external_order_id already exists. Nothing new was created; data shows the existing order with duplicate: true, and warnings is empty.

{
  "data": {
    "id": 48211,
    "order_number": "48211",
    "external_order_id": "APP-100234",
    "duplicate": true,
    "customer_id": 9021,
    "customer_created": false,
    "status_id": 1,
    "status": "Incoming order",
    "payment_method_id": 3,
    "referrer_id": 17,
    "shipping_method_id": 4,
    "shipping_method": "Parcel",
    "shipping_cost_gross": 4.9,
    "shipping_cost_source": "app",
    "items": [
      {
        "sku": "SAMPLE-1KG",
        "quantity": 2,
        "unit_price_gross": 29.9,
        "price_source": "app"
      }
    ],
    "grand_total_gross": 64.7,
    "currency": "EUR"
  },
  "warnings": []
}
Response fields
Field Type Required Description
data object required
id integer required Our order number. Store it on your side.
order_number string required Our order number as text (same value as id).
external_order_id string required Your order number.
duplicate boolean required true if the order already existed and nothing new was created.
customer_id integer required Our customer number. Can be sent as customer.customer_id in later orders.
customer_created boolean required true if a new customer was created for this order.
status_id integer required ID of the order status.
status string required Name of the order status as named in the shop.
payment_method_id integer required
referrer_id integer | null required
shipping_method_id integer | null required Shipping method chosen by the shop's rules; null if none matched (then a no_shipping_method warning is given).
shipping_method string | null required Name of the shipping method; null if none matched.
shipping_cost_gross number required Shipping costs including tax.
shipping_cost_source string required app = your value, system = calculated by the shop. one of: app, system
items[] array of object required
sku string required Our article number.
quantity integer required
unit_price_gross number required Unit price including tax.
price_source string required app = your price, system = the shop's price. one of: app, system
grand_total_gross number required Total of the order including tax. This value is authoritative.
currency string required
warnings[] array of object required Always present. Empty means everything is fine. Always empty for a duplicate.
code string required - no_shipping_method: no shipping method matched; the order was created without one and the shop operator sets it by hand. - customer_already_linked: the customer was found by email, but is already linked to a different customer ID of your app. - collective_invoice_single_order: the order uses the collective invoice, but its billing address differs from the address stored for the customer. The order is created and invoiced on its own, not on the collective invoice. - status_not_changed (updateOrder): the status could not be changed because of an unexpected error. All other changes of the request were saved; the order shows its old status. Send order_status_id again, or pass reference to the shop operator. one of: no_shipping_method, customer_already_linked, collective_invoice_single_order, status_not_changed
message string required Human-readable English text. It may change; evaluate code instead.
reference string optional Only with status_not_changed. Identifies the case in our log.

201 Created The order was created.

{
  "data": {
    "id": 48211,
    "order_number": "48211",
    "external_order_id": "APP-100234",
    "duplicate": false,
    "customer_id": 9021,
    "customer_created": true,
    "status_id": 1,
    "status": "Incoming order",
    "payment_method_id": 3,
    "referrer_id": 17,
    "shipping_method_id": 4,
    "shipping_method": "Parcel",
    "shipping_cost_gross": 4.9,
    "shipping_cost_source": "app",
    "items": [
      {
        "sku": "SAMPLE-1KG",
        "quantity": 2,
        "unit_price_gross": 29.9,
        "price_source": "app"
      },
      {
        "sku": "SAMPLE-SHAKER",
        "quantity": 1,
        "unit_price_gross": 5,
        "price_source": "system"
      }
    ],
    "grand_total_gross": 69.7,
    "currency": "EUR"
  },
  "warnings": []
}
Response fields
Field Type Required Description
data object required
id integer required Our order number. Store it on your side.
order_number string required Our order number as text (same value as id).
external_order_id string required Your order number.
duplicate boolean required true if the order already existed and nothing new was created.
customer_id integer required Our customer number. Can be sent as customer.customer_id in later orders.
customer_created boolean required true if a new customer was created for this order.
status_id integer required ID of the order status.
status string required Name of the order status as named in the shop.
payment_method_id integer required
referrer_id integer | null required
shipping_method_id integer | null required Shipping method chosen by the shop's rules; null if none matched (then a no_shipping_method warning is given).
shipping_method string | null required Name of the shipping method; null if none matched.
shipping_cost_gross number required Shipping costs including tax.
shipping_cost_source string required app = your value, system = calculated by the shop. one of: app, system
items[] array of object required
sku string required Our article number.
quantity integer required
unit_price_gross number required Unit price including tax.
price_source string required app = your price, system = the shop's price. one of: app, system
grand_total_gross number required Total of the order including tax. This value is authoritative.
currency string required
warnings[] array of object required Always present. Empty means everything is fine. Always empty for a duplicate.
code string required - no_shipping_method: no shipping method matched; the order was created without one and the shop operator sets it by hand. - customer_already_linked: the customer was found by email, but is already linked to a different customer ID of your app. - collective_invoice_single_order: the order uses the collective invoice, but its billing address differs from the address stored for the customer. The order is created and invoiced on its own, not on the collective invoice. - status_not_changed (updateOrder): the status could not be changed because of an unexpected error. All other changes of the request were saved; the order shows its old status. Send order_status_id again, or pass reference to the shop operator. one of: no_shipping_method, customer_already_linked, collective_invoice_single_order, status_not_changed
message string required Human-readable English text. It may change; evaluate code instead.
reference string optional Only with status_not_changed. Identifies the case in our log.

Error responses

401 Unauthorized The API key is missing, malformed, wrong, paused, expired or revoked. The body is always the same and never names the reason.
{
  "error": {
    "code": "unauthorized",
    "message": "Invalid or missing API key.",
    "details": []
  }
}
403 Forbidden The API key is valid but lacks a scope this endpoint needs. details.required lists the scopes the endpoint requires, details.missing the ones your key lacks. Ask the shop operator to add the scope.
{
  "error": {
    "code": "insufficient_scope",
    "message": "The API key is missing a required scope.",
    "details": {
      "required": [
        "orders.write"
      ],
      "missing": [
        "orders.write"
      ]
    }
  }
}
404 Not Found The path does not exist, the API is not enabled on this system, the order does not belong to the shop of your API client, or the customer, address or label value is not known to your API client.
{
  "error": {
    "code": "not_found",
    "message": "The requested resource does not exist.",
    "details": []
  }
}
409 Conflict An order existed for this external_order_id, but it was deleted in the meantime. Do not retry.
{
  "error": {
    "code": "order_deleted",
    "message": "Order 48211 was created for this external order ID and has since been deleted.",
    "details": []
  }
}
422 Unprocessable Content The order was not accepted. Nothing was created. - validation_failed: the order data is invalid. details lists every problem at once: per field a list of {code, message}. Field names use dots, for example items.1.sku is the field sku of the second item (counting from 0). - client_not_configured: your API client is not fully set up (no shop, deleted shop, or its default referrer is inactive or not assigned to the shop). Contact the shop operator.
{
  "error": {
    "code": "validation_failed",
    "message": "The order was not created.",
    "details": {
      "items.1.sku": [
        {
          "code": "unknown_article",
          "message": "Article 'SAMPLE-XYZ' is not known."
        }
      ],
      "payment_method_id": [
        {
          "code": "unknown_payment_method",
          "message": "Payment method 99 does not exist or is inactive."
        }
      ]
    }
  }
}
429 Too Many Requests Too many requests. Either your API client used up its requests per minute (message Too many requests., with all rate limit headers), or too many failed authentications came in a short time (message Too many authentication attempts., only Retry-After). Both carry the code rate_limited.
{
  "error": {
    "code": "rate_limited",
    "message": "Too many requests.",
    "details": []
  }
}
500 Internal Server Error An unexpected error occurred; the order was not created. details.reference identifies the case. Resend the unchanged request later; if the error persists, give the reference to the shop operator.
{
  "error": {
    "code": "server_error",
    "message": "An unexpected error occurred. The order was not created.",
    "details": {
      "reference": "3f2a9c1e-7b4d-4e8a-9f61-2d5c8b0a7e13"
    }
  }
}

All error codes: error code reference.

Check an order without creating it

POST /orders/validate

Scope: orders.write

Takes the same body as POST /orders and applies the same rules and error codes, but creates nothing: no order, no customer, no stock reservation. Useful during development.

The response shows how the order would be resolved. Prices, shipping method and totals are only calculated when the order is really created. A customer that would be matched by email and a customer that would be created both appear as new_or_email without a customer ID; which of the two applies is only decided when the order is created.

Request body

Field Type Required Description
external_order_id string required Your order number. Unique per API client and case-sensitive. The same number never creates a second order. max length 191
ordered_at string | null optional Time of the order. Use ISO 8601 with a time zone (Z or +02:00). Must not be in the future and at most 30 days in the past. Without it, the time of receipt is used.
payment_method_id integer required ID of a payment method from listPaymentMethods. Any other ID is rejected with payment_method_not_available (or unknown_payment_method if it is not active). For the collective invoice, the customer must also be approved for it.
referrer_id integer | null optional ID of a referrer (order origin). Must be active and assigned to the shop of your API client (see listReferrers). Without it, the default referrer of your API client is used.
order_status_id integer | null optional ID of an order status from listOrderStatuses. The order is created directly in this status; every status of the shop is accepted, including cancelled and shipped statuses. Without it, the order starts in the shop's incoming order status. Any other ID is rejected with unknown_order_status.
currency string required Currency code. Only EUR is supported. one of: EUR · min length 3 · max length 3
comment string | null optional Message of the customer about the order. max length 2000
shipping_cost_gross number | null optional Shipping costs including tax, at most 2 decimal places. If sent, it applies (also 0). If missing, shipping costs are calculated by the shop's rules. min 0 · max 999999.99 · multiple of 0.01
customer object required The customer of the order. For an existing customer, the ID alone is enough ({"external_id": "u-55871"} or {"customer_id": 9021}). For a new customer, email and billing are required.
external_id string | null optional Your customer ID. Required unless customer_id is sent. Case-sensitive; the same ID always leads to the same customer. max length 191
customer_id integer | null optional Our customer number, for example from data.customer_id of an earlier response or given to you by the shop operator. Any active, registered customer of your shop can be referenced; guest, blocked or deleted customers and customers of other shops fail with unknown_customer. Referencing a customer by number does not link your external_id to it. min 1
id integer | null optional Same as customer_id. If both are sent, they must have the same value, otherwise the request fails with invalid_value on customer.id. Errors about the customer number are reported on customer.customer_id. min 1
email string (email) | null optional Email address. Required for a new customer. max length 191
email_verified boolean | null optional true if you confirmed the email (for example by a link). Only then can the order be matched to an existing customer by email, and only if the shop operator enabled this for your client. default false
telephone string | null optional Phone number. max length 191
billing object | null optional Billing address. Required for a new customer. For a known customer it applies to this order only; the stored customer is not changed.
shipping object | null optional Delivery address. If missing, null or {}, the order is delivered to the billing address. A sent delivery address is stored in the order and added to the customer's address book (the same address only once).
items[] array of object required Order items, 1 to 200. min 1 items · max 200 items
sku string | null optional Our article number. Not case-sensitive. max length 191
article_id integer | null optional Our number of the main article. All variants of an article (for example sizes) share this number; for articles with variants use sku. min 1
quantity integer required min 1 · max 9999
unit_price_gross number | null optional Unit price including tax, at most 2 decimal places. If sent, it is used as a fixed price; if missing, the shop's price applies. min 0 · max 999999.99 · multiple of 0.01

Example request

curl -X POST "https://shop.example.com/api/v1/orders/validate" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "external_order_id": "APP-100235",
  "payment_method_id": 3,
  "currency": "EUR",
  "customer": {
    "external_id": "u-55871"
  },
  "items": [
    {
      "sku": "SAMPLE-1KG",
      "quantity": 2
    }
  ]
}'

Responses

200 OK The order is valid and would be accepted.

{
  "data": {
    "valid": true,
    "duplicate": false,
    "order_id": null,
    "resolved": {
      "customer": {
        "match": "existing",
        "customer_id": 9021
      },
      "items": [
        {
          "variation_id": 3311,
          "sku": "SAMPLE-1KG",
          "article_id": 812,
          "quantity": 2,
          "price_source": "system"
        }
      ],
      "payment_method_id": 3,
      "referrer_id": 17,
      "order_status_id": 1,
      "shipping_cost_source": "system"
    },
    "warnings": []
  }
}
Response fields
Field Type Required Description
data object required
valid boolean required Always true in a 200 response; invalid orders answer 422. always true
duplicate boolean required true if an order already exists for this external_order_id.
order_id integer | null required Our order number of the existing order if duplicate is true, otherwise null.
resolved object required
customer object required
match string required existing: the customer is already known through your customer ID or our customer number; customer_id is set. new_or_email: the customer would be created or matched by email; customer_id is null. one of: existing, new_or_email
customer_id integer | null required
items[] array of object required
variation_id integer | null required Our ID of the matched article variant.
sku string | null required Our article number of the matched variant.
article_id integer | null required Our number of the main article.
quantity integer required
price_source string required app if you sent unit_price_gross, otherwise system. one of: app, system
payment_method_id integer required
referrer_id integer | null required The referrer that would be used (yours or the default of your API client).
order_status_id integer required The status the order would start in (yours or the shop's incoming order status).
shipping_cost_source string required app if you sent shipping_cost_gross, otherwise system. one of: app, system
warnings[] array of object required Reserved for notes about the order. Currently always empty on this endpoint.
code string required - no_shipping_method: no shipping method matched; the order was created without one and the shop operator sets it by hand. - customer_already_linked: the customer was found by email, but is already linked to a different customer ID of your app. - collective_invoice_single_order: the order uses the collective invoice, but its billing address differs from the address stored for the customer. The order is created and invoiced on its own, not on the collective invoice. - status_not_changed (updateOrder): the status could not be changed because of an unexpected error. All other changes of the request were saved; the order shows its old status. Send order_status_id again, or pass reference to the shop operator. one of: no_shipping_method, customer_already_linked, collective_invoice_single_order, status_not_changed
message string required Human-readable English text. It may change; evaluate code instead.
reference string optional Only with status_not_changed. Identifies the case in our log.

Error responses

401 Unauthorized The API key is missing, malformed, wrong, paused, expired or revoked. The body is always the same and never names the reason.
{
  "error": {
    "code": "unauthorized",
    "message": "Invalid or missing API key.",
    "details": []
  }
}
403 Forbidden The API key is valid but lacks a scope this endpoint needs. details.required lists the scopes the endpoint requires, details.missing the ones your key lacks. Ask the shop operator to add the scope.
{
  "error": {
    "code": "insufficient_scope",
    "message": "The API key is missing a required scope.",
    "details": {
      "required": [
        "orders.write"
      ],
      "missing": [
        "orders.write"
      ]
    }
  }
}
404 Not Found The path does not exist, the API is not enabled on this system, the order does not belong to the shop of your API client, or the customer, address or label value is not known to your API client.
{
  "error": {
    "code": "not_found",
    "message": "The requested resource does not exist.",
    "details": []
  }
}
422 Unprocessable Content The order was not accepted. Nothing was created. - validation_failed: the order data is invalid. details lists every problem at once: per field a list of {code, message}. Field names use dots, for example items.1.sku is the field sku of the second item (counting from 0). - client_not_configured: your API client is not fully set up (no shop, deleted shop, or its default referrer is inactive or not assigned to the shop). Contact the shop operator.
{
  "error": {
    "code": "validation_failed",
    "message": "The order was not created.",
    "details": {
      "items.1.sku": [
        {
          "code": "unknown_article",
          "message": "Article 'SAMPLE-XYZ' is not known."
        }
      ],
      "payment_method_id": [
        {
          "code": "unknown_payment_method",
          "message": "Payment method 99 does not exist or is inactive."
        }
      ]
    }
  }
}
429 Too Many Requests Too many requests. Either your API client used up its requests per minute (message Too many requests., with all rate limit headers), or too many failed authentications came in a short time (message Too many authentication attempts., only Retry-After). Both carry the code rate_limited.
{
  "error": {
    "code": "rate_limited",
    "message": "Too many requests.",
    "details": []
  }
}
500 Internal Server Error An unexpected error occurred on our side. Retry later.
{
  "error": {
    "code": "server_error",
    "message": "An unexpected error occurred.",
    "details": []
  }
}

All error codes: error code reference.

Get an order

GET /orders/{orderId}

Scope: orders.read

Returns an order by our order number (id from the response of createOrder). Every order of the shop assigned to your API client can be read, no matter how it was placed (shop, marketplace, other API clients, manual entry). type tells the kind of document, for example Auftrag (order), Gutschrift (credit note) or Retoure (return).

external_order_id is your order number only if the order was created through your API client; for any other order it is null.

An unknown order number, a deleted order and an order of another shop all answer 404. If no shop is assigned to your API client, the answer is 422 with client_not_configured.

Path parameters

Parameter Type Required Description
orderId integer required Our order number (id from the response of createOrder). min 1

Example request

curl "https://shop.example.com/api/v1/orders/104233" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Accept: application/json"

Responses

200 OK The order.

{
  "data": {
    "id": 104233,
    "order_number": "104233",
    "customer_id": 9021,
    "status_id": 4,
    "status": "Payment received",
    "payment_method_id": 3,
    "referrer_id": 12,
    "shipping_method_id": 2,
    "shipping_method": "DHL Parcel",
    "shipping_cost_gross": 4.99,
    "shipping_cost_source": "system",
    "items": [
      {
        "item_id": 88120,
        "sku": "TS-BLUE-M",
        "quantity": 2,
        "unit_price_gross": 19.9,
        "price_source": "app",
        "article_id": 5512,
        "variation_id": 7741,
        "name": "T-shirt blue M",
        "total_gross": 39.8
      }
    ],
    "grand_total_gross": 44.79,
    "currency": "EUR",
    "external_order_id": "APP-2026-000187",
    "type": "Auftrag",
    "created_at": "2026-10-15T09:12:44.000000Z",
    "updated_at": "2026-10-15T11:30:02.000000Z",
    "email": "alex.sample@example.com",
    "telephone": null,
    "paid_status": "paid",
    "payment_method": "PayPal",
    "shipping_cost_net": 4.19,
    "tax_total": 7.15,
    "grand_total_net": 37.64,
    "billing": {
      "salutation": "Mr",
      "title": null,
      "first_name": "Alex",
      "last_name": "Sample",
      "company": null,
      "street": "Sample Street",
      "house": "5",
      "additional": null,
      "postcode": "10115",
      "city": "Berlin",
      "country": "DE"
    },
    "shipping": null,
    "shipments": [
      {
        "shipment_number": "00340434161094042557",
        "tracking_url": "https://www.dhl.de/de/privatkunden/pakete-empfangen/verfolgen.html?piececode=00340434161094042557",
        "delivered_at": null
      }
    ]
  }
}
Response fields
Field Type Required Description
data object required An order of your shop. Addresses use the format of customer.billing and customer.shipping in createOrder; empty fields are null.
id integer required Our order number.
order_number string required Our order number as text (same value as id).
external_order_id string | null required Your order number if the order was created through your API client, otherwise null.
type string required Kind of document as named in the shop, for example Auftrag (order), Gutschrift (credit note), Retoure (return), Angebot (offer) or Sammelauftrag (collective invoice order).
created_at string (date-time) | null required Order date (UTC).
updated_at string (date-time) | null optional Last change (UTC).
customer_id integer required Our customer number.
email string required
telephone string | null optional
status_id integer required ID of the order status (see listOrderStatuses).
status string required Name of the order status as named in the shop.
paid_status string | null required Payment state: unpaid, in_payment (partly paid), paid or canceled.
payment_method_id integer required
payment_method string | null required Name of the payment method at the time of the order.
referrer_id integer | null required
currency string required
billing object required Billing address. Has no state.
salutation string | null optional
title string | null optional
first_name string | null optional
last_name string | null optional
company string | null optional
street string | null optional
house string | null optional
additional string | null optional
postcode string | null optional
city string | null optional
country string | null optional ISO 3166-1 alpha-2 country code.
shipping object | null required Delivery address; null if the order is delivered to the billing address.
items[] array of object required
item_id integer required Our number of the item. Use it in updateOrder (items.update, items.remove).
sku string required Our article number of the variant.
article_id integer | null required Our number of the main article.
variation_id integer | null required Our number of the variant; null for items without an article (for example a free text item).
name string required
quantity integer required
unit_price_gross number required Unit price including tax.
total_gross number required Item total including tax.
price_source string required app = fixed price, system = the shop's price. one of: app, system
shipping_method_id integer | null required
shipping_method string | null required
shipping_cost_gross number required
shipping_cost_net number required
shipping_cost_source string required one of: app, system
tax_total number required Total tax of the order.
grand_total_gross number required Total of the order including tax.
grand_total_net number required Total of the order without tax.
shipments[] array of object required Parcels of the order with a tracking number (cancelled labels excluded). Empty until the order is shipped.
shipment_number string required
tracking_url string | null required Tracking link of the shipping method; null if none is configured.
delivered_at string (date-time) | null required Delivery time reported by the carrier (UTC), if known.

Error responses

401 Unauthorized The API key is missing, malformed, wrong, paused, expired or revoked. The body is always the same and never names the reason.
{
  "error": {
    "code": "unauthorized",
    "message": "Invalid or missing API key.",
    "details": []
  }
}
403 Forbidden The API key is valid but lacks a scope this endpoint needs. details.required lists the scopes the endpoint requires, details.missing the ones your key lacks. Ask the shop operator to add the scope.
{
  "error": {
    "code": "insufficient_scope",
    "message": "The API key is missing a required scope.",
    "details": {
      "required": [
        "orders.write"
      ],
      "missing": [
        "orders.write"
      ]
    }
  }
}
404 Not Found The path does not exist, the API is not enabled on this system, the order does not belong to the shop of your API client, or the customer, address or label value is not known to your API client.
{
  "error": {
    "code": "not_found",
    "message": "The requested resource does not exist.",
    "details": []
  }
}
422 Unprocessable Content No shop is assigned to your API client (client_not_configured).
{
  "error": {
    "code": "client_not_configured",
    "message": "No shop is configured for this API client.",
    "details": []
  }
}
429 Too Many Requests Too many requests. Either your API client used up its requests per minute (message Too many requests., with all rate limit headers), or too many failed authentications came in a short time (message Too many authentication attempts., only Retry-After). Both carry the code rate_limited.
{
  "error": {
    "code": "rate_limited",
    "message": "Too many requests.",
    "details": []
  }
}
500 Internal Server Error An unexpected error occurred on our side. Retry later.
{
  "error": {
    "code": "server_error",
    "message": "An unexpected error occurred.",
    "details": []
  }
}

All error codes: error code reference.

Update an order

PATCH /orders/{orderId}

Scope: orders.update

Changes an order of the shop assigned to your API client: status, payment method, billing and delivery address, and items. Send only the blocks you want to change; at least one is required. Every order of the shop can be changed, no matter how it was placed.

All checks run before anything is written, and every problem is reported at once. If one entry is invalid, nothing is changed. Unknown fields are rejected (unknown_field), not ignored.

Items: items.add adds items like createOrder (with price the item gets a fixed price, without it the shop's price applies). items.update changes quantity and/or price of an item, addressed by its item_id from getOrder. A quantity change alone works like a change in the shop's back office: an item with a fixed price keeps it, all other items are priced again by the shop's price rules (including volume prices). items.remove removes items by item_id. At most 100 entries per request; the order must keep at least one item. To empty an order, change its status to a cancelled status.

If the order is finalised (invoiced), cancelled or shipped (also when all its goods are booked out, whatever its status), items, addresses and the payment method can no longer be changed (409 order_locked); the status can, sent as order_status_id alone.

The status is changed last, after the other changes are saved. If that fails, the other changes stay saved: on an unexpected error the answer is 200 with the old status and the warning status_not_changed; send order_status_id again to retry.

Sending the current state again changes nothing and answers 200. Sending items.add again adds the items again, unless you send the same Idempotency-Key with exactly the same body.

Path parameters

Parameter Type Required Description
orderId integer required Our order number (id from the response of createOrder). min 1

Headers

Header Type Required Description
Idempotency-Key string optional Your own unique key for this change, at most 191 characters, for example a UUID. If you send the same key with exactly the same body again within 24 hours, you get the stored answer and nothing is changed a second time; the answer then carries the header Idempotent-Replayed: true. The same key with a different body answers 422 idempotency_key_reused. Answers with status 5xx and 409 stock_locked are not stored, so a retry with the same key runs again. All other answers are stored, also errors such as 422 validation_failed or 409 order_locked: after you correct the request, send it with a new key. max length 191

Request body

Field Type Required Description
order_status_id integer optional New order status, an ID from listOrderStatuses. Allowed on every order, also a finalised, cancelled or shipped one.
payment_method_id integer optional New payment method, an ID from listPaymentMethods. Same rules as in createOrder; for the collective invoice the customer of the order must be approved.
billing object optional Address. last_name or company is required.
salutation string | null optional max length 191
title string | null optional max length 50
first_name string | null optional max length 191
last_name string | null optional Required unless company is set. max length 191
company string | null optional max length 191
street string required max length 191
house string | null optional House number. For a parcel locker, the number of the parcel locker. max length 191
additional string | null optional Additional address line. max length 191
postcode string required max length 191
city string required max length 191
state string | null optional State or region as text. max length 191
country string required Country code according to ISO 3166-1 alpha-2, for example DE or AT. min length 2 · max length 2
shipping object | null optional New delivery address; replaces the old one completely. null or {} removes it, the order then goes to the billing address.
items object optional At most 100 entries in add, update and remove together. An item_id may appear only once.
add[] array of object optional
sku string | null optional Our article number. Not case-sensitive. max length 191
article_id integer | null optional Our number of the main article; for articles with variants use sku. min 1
quantity integer required min 1 · max 9999
price number | null optional Unit price including tax, at most 2 decimal places. If sent, it is used as a fixed price, also 0 (the item is then free of charge); if missing or null, the shop's price applies. min 0 · max 999999.99 · multiple of 0.01
update[] array of object optional
item_id integer required item_id of the item, from getOrder. min 1
quantity integer | null optional New quantity. It cannot be lower than the quantity already delivered. min 1 · max 9999
price number | null optional New unit price including tax; the item gets a fixed price. 0 is allowed and makes the item free of charge. The tax rate is the rate of the delivery country after this request, also when the same request changes the country; without a rate there, article_tax_unresolved. min 0 · max 999999.99 · multiple of 0.01
remove array of integer optional item_ids of the items to remove. An item that is already partly delivered cannot be removed. items: min 1

Example request

curl -X PATCH "https://shop.example.com/api/v1/orders/104233" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "order_status_id": 4,
  "items": {
    "add": [
      {
        "sku": "TS-BLUE-L",
        "quantity": 1
      }
    ],
    "update": [
      {
        "item_id": 88120,
        "quantity": 3
      }
    ],
    "remove": [
      88121
    ]
  }
}'

Responses

200 OK The changed order, in the format of getOrder.

{
  "warnings": [],
  "data": {
    "id": 104233,
    "order_number": "104233",
    "customer_id": 9021,
    "status_id": 4,
    "status": "Payment received",
    "payment_method_id": 3,
    "referrer_id": 12,
    "shipping_method_id": 2,
    "shipping_method": "DHL Parcel",
    "shipping_cost_gross": 4.99,
    "shipping_cost_source": "system",
    "items": [
      {
        "item_id": 88120,
        "sku": "TS-BLUE-M",
        "quantity": 3,
        "unit_price_gross": 19.9,
        "price_source": "app",
        "article_id": 5512,
        "variation_id": 7741,
        "name": "T-shirt blue M",
        "total_gross": 59.7
      },
      {
        "item_id": 88122,
        "sku": "TS-BLUE-L",
        "quantity": 1,
        "unit_price_gross": 19.9,
        "price_source": "system",
        "article_id": 5512,
        "variation_id": 7742,
        "name": "T-shirt blue L",
        "total_gross": 19.9
      }
    ],
    "grand_total_gross": 84.59,
    "currency": "EUR",
    "external_order_id": "APP-2026-000187",
    "type": "Auftrag",
    "created_at": "2026-10-15T09:12:44.000000Z",
    "updated_at": "2026-10-15T12:01:10.000000Z",
    "email": "alex.sample@example.com",
    "telephone": null,
    "paid_status": "unpaid",
    "payment_method": "Invoice",
    "shipping_cost_net": 4.19,
    "tax_total": 13.51,
    "grand_total_net": 71.08,
    "billing": {
      "salutation": "Mr",
      "title": null,
      "first_name": "Alex",
      "last_name": "Sample",
      "company": null,
      "street": "Sample Street",
      "house": "5",
      "additional": null,
      "postcode": "10115",
      "city": "Berlin",
      "country": "DE"
    },
    "shipping": null,
    "shipments": []
  }
}
Response fields
Field Type Required Description
data object required An order of your shop. Addresses use the format of customer.billing and customer.shipping in createOrder; empty fields are null.
id integer required Our order number.
order_number string required Our order number as text (same value as id).
external_order_id string | null required Your order number if the order was created through your API client, otherwise null.
type string required Kind of document as named in the shop, for example Auftrag (order), Gutschrift (credit note), Retoure (return), Angebot (offer) or Sammelauftrag (collective invoice order).
created_at string (date-time) | null required Order date (UTC).
updated_at string (date-time) | null optional Last change (UTC).
customer_id integer required Our customer number.
email string required
telephone string | null optional
status_id integer required ID of the order status (see listOrderStatuses).
status string required Name of the order status as named in the shop.
paid_status string | null required Payment state: unpaid, in_payment (partly paid), paid or canceled.
payment_method_id integer required
payment_method string | null required Name of the payment method at the time of the order.
referrer_id integer | null required
currency string required
billing object required Billing address. Has no state.
salutation string | null optional
title string | null optional
first_name string | null optional
last_name string | null optional
company string | null optional
street string | null optional
house string | null optional
additional string | null optional
postcode string | null optional
city string | null optional
country string | null optional ISO 3166-1 alpha-2 country code.
shipping object | null required Delivery address; null if the order is delivered to the billing address.
items[] array of object required
item_id integer required Our number of the item. Use it in updateOrder (items.update, items.remove).
sku string required Our article number of the variant.
article_id integer | null required Our number of the main article.
variation_id integer | null required Our number of the variant; null for items without an article (for example a free text item).
name string required
quantity integer required
unit_price_gross number required Unit price including tax.
total_gross number required Item total including tax.
price_source string required app = fixed price, system = the shop's price. one of: app, system
shipping_method_id integer | null required
shipping_method string | null required
shipping_cost_gross number required
shipping_cost_net number required
shipping_cost_source string required one of: app, system
tax_total number required Total tax of the order.
grand_total_gross number required Total of the order including tax.
grand_total_net number required Total of the order without tax.
shipments[] array of object required Parcels of the order with a tracking number (cancelled labels excluded). Empty until the order is shipped.
shipment_number string required
tracking_url string | null required Tracking link of the shipping method; null if none is configured.
delivered_at string (date-time) | null required Delivery time reported by the carrier (UTC), if known.
warnings[] array of object required Notes about the change. Empty if everything was applied.
code string required - no_shipping_method: no shipping method matched; the order was created without one and the shop operator sets it by hand. - customer_already_linked: the customer was found by email, but is already linked to a different customer ID of your app. - collective_invoice_single_order: the order uses the collective invoice, but its billing address differs from the address stored for the customer. The order is created and invoiced on its own, not on the collective invoice. - status_not_changed (updateOrder): the status could not be changed because of an unexpected error. All other changes of the request were saved; the order shows its old status. Send order_status_id again, or pass reference to the shop operator. one of: no_shipping_method, customer_already_linked, collective_invoice_single_order, status_not_changed
message string required Human-readable English text. It may change; evaluate code instead.
reference string optional Only with status_not_changed. Identifies the case in our log.

Error responses

401 Unauthorized The API key is missing, malformed, wrong, paused, expired or revoked. The body is always the same and never names the reason.
{
  "error": {
    "code": "unauthorized",
    "message": "Invalid or missing API key.",
    "details": []
  }
}
403 Forbidden The API key is valid but lacks a scope this endpoint needs. details.required lists the scopes the endpoint requires, details.missing the ones your key lacks. Ask the shop operator to add the scope.
{
  "error": {
    "code": "insufficient_scope",
    "message": "The API key is missing a required scope.",
    "details": {
      "required": [
        "orders.write"
      ],
      "missing": [
        "orders.write"
      ]
    }
  }
}
404 Not Found The path does not exist, the API is not enabled on this system, the order does not belong to the shop of your API client, or the customer, address or label value is not known to your API client.
{
  "error": {
    "code": "not_found",
    "message": "The requested resource does not exist.",
    "details": []
  }
}
409 Conflict Nothing was changed, with one exception noted below. - order_locked: the order is finalised (invoiced), cancelled or shipped and the request changes items, addresses or the payment method; to change only the status, send order_status_id alone. Or the new status would cancel a credit note that is settled in a collective invoice. If the credit note was settled only while the other changes of the request were being saved, those changes stay saved and only the status is not changed; the message says so. - stock_locked: a running stocktake locks the stock. Retry later. - conflict: a request with the same Idempotency-Key is still running. Retry in a few seconds.
{
  "error": {
    "code": "order_locked",
    "message": "Order 104233 is finalised. Items, addresses and the payment method can no longer be changed. Send order_status_id alone to change the status.",
    "details": []
  }
}
422 Unprocessable Content Nothing was changed. - validation_failed: the request data is invalid. details lists every problem at once, per field a list of {code, message}. Detail codes of this endpoint: - required: in body, no block was sent; in items, no entry in add, update or remove; otherwise a required field is missing. - invalid_format, too_long: wrong type or format, or a text that is too long. An Idempotency-Key longer than 191 characters is reported as too_long in idempotency_key. - out_of_range: a number outside the allowed range, or more than 100 entries in items (add, update and remove together). - duplicate_value: an item_id appears twice, or in items.update and items.remove at the same time. - unknown_item: the item_id is not an item of this order. - unknown_field: a field of the body is not known on its level, usually a typo (for example items.update.0.qty instead of quantity, or billing.zip instead of postcode). Unknown fields are never ignored. - item_already_delivered: the item is partly delivered; it cannot be removed, and its quantity cannot be lower than the quantity already delivered. - order_empty: the order would have no items left. - unknown_order_status, unknown_payment_method, payment_method_not_available, unknown_country, required_for_packstation, unknown_article, ambiguous_article, article_inactive, article_tax_unresolved, article_reserved: as for createOrder. - client_not_configured: no shop is assigned to your API client. - idempotency_key_reused: the Idempotency-Key was already used with a different body. With an Idempotency-Key, this answer is stored for 24 hours like every 4xx answer except 409 stock_locked: sending the same key again returns it unchanged. Send the corrected request with a new key.
{
  "error": {
    "code": "validation_failed",
    "message": "The order was not changed.",
    "details": {
      "order_status_id": [
        {
          "code": "unknown_order_status",
          "message": "Order status 99 does not exist."
        }
      ]
    }
  }
}
429 Too Many Requests Too many requests. Either your API client used up its requests per minute (message Too many requests., with all rate limit headers), or too many failed authentications came in a short time (message Too many authentication attempts., only Retry-After). Both carry the code rate_limited.
{
  "error": {
    "code": "rate_limited",
    "message": "Too many requests.",
    "details": []
  }
}
500 Internal Server Error An unexpected error occurred; the order was not created. details.reference identifies the case. Resend the unchanged request later; if the error persists, give the reference to the shop operator.
{
  "error": {
    "code": "server_error",
    "message": "An unexpected error occurred. The order was not created.",
    "details": {
      "reference": "3f2a9c1e-7b4d-4e8a-9f61-2d5c8b0a7e13"
    }
  }
}

All error codes: error code reference.