Orders
Create an order for the seller, read it back, list what changed, and claim the seller’s manual orders.
An order is created in one call with all its lines — it lands whole or not at all. From then on ColiSwift owns its life (confirmation call, validation, picking, delivery) and tells you about every step through lead.* events, each carrying the Order object below.
Create an order
/ordersexternalIdstring, 1–64requiredYour order id. Unique per seller and per app: the idempotency key.
countryCodestring (2)requiredCountry of delivery; one of the seller’s countries.
customer.namestringrequiredCustomer full name.
customer.phonestringrequiredPhone number the call centre will ring.
customer.addressstringrequiredDelivery address, free text.
storeIdstring | nullOne of the seller’s stores; another id answers
422 STORE_NOT_FOUND.notesstring | nullFree text added to the order as a note for the agent who calls (options the customer chose, delivery preference…). Written only when the order is created, not on a retry.
lines[]object[], ≥ 1requiredThe basket.
lines[].referencestringrequiredProduct
reference, or a variantsku, or — for a COD Drop product the seller adopted — its seller SKU or the creator’s reference.lines[].variantLabelstring | nullFor a product with variants addressed by its product reference: the variant label (e.g.
Black / M). A variant product with no resolvable variant is refused withLEAD_VARIANT_REQUIRED.lines[].quantityinteger ≥ 1requiredUnits.
lines[].lineTotalmoney stringPrice of the whole line. Divided by
quantity, rounded half-up to 2 decimals ("599.00"for 3 →"199.67"per unit; the order total then reads599.01).lines[].unitPricemoney stringPrice of one unit. Send either
lineTotalorunitPrice, exactly one.
curl -X POST "https://coliswift.com/api/partner/v1/orders" \
-H "Authorization: Bearer $COLISWIFT_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"externalId": "shop_10482",
"countryCode": "MA",
"customer": {
"name": "Youssef El Amrani",
"phone": "+212600000000",
"address": "12 rue des Oliviers, Casablanca"
},
"storeId": "b2d4e6f8-1a3c-4e5f-8a9b-0c1d2e3f4a5b",
"notes": "Deliver after 6 pm",
"lines": [
{
"reference": "SERUM-ARGAN-30",
"quantity": 2,
"unitPrice": "199.00"
}
]
}'const res = await fetch('https://coliswift.com/api/partner/v1/orders', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.COLISWIFT_ACCESS_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"externalId": "shop_10482",
"countryCode": "MA",
"customer": {
"name": "Youssef El Amrani",
"phone": "+212600000000",
"address": "12 rue des Oliviers, Casablanca"
},
"storeId": "b2d4e6f8-1a3c-4e5f-8a9b-0c1d2e3f4a5b",
"notes": "Deliver after 6 pm",
"lines": [
{
"reference": "SERUM-ARGAN-30",
"quantity": 2,
"unitPrice": "199.00"
}
]
}),
});
const data = await res.json();$ch = curl_init('https://coliswift.com/api/partner/v1/orders');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('COLISWIFT_ACCESS_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => <<<'JSON'
{
"externalId": "shop_10482",
"countryCode": "MA",
"customer": {
"name": "Youssef El Amrani",
"phone": "+212600000000",
"address": "12 rue des Oliviers, Casablanca"
},
"storeId": "b2d4e6f8-1a3c-4e5f-8a9b-0c1d2e3f4a5b",
"notes": "Deliver after 6 pm",
"lines": [
{
"reference": "SERUM-ARGAN-30",
"quantity": 2,
"unitPrice": "199.00"
}
]
}
JSON,
]);
$data = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);import os, requests
res = requests.post(
"https://coliswift.com/api/partner/v1/orders",
headers={"Authorization": f"Bearer {os.environ['COLISWIFT_ACCESS_TOKEN']}"},
json={
"externalId": "shop_10482",
"countryCode": "MA",
"customer": {
"name": "Youssef El Amrani",
"phone": "+212600000000",
"address": "12 rue des Oliviers, Casablanca",
},
"storeId": "b2d4e6f8-1a3c-4e5f-8a9b-0c1d2e3f4a5b",
"notes": "Deliver after 6 pm",
"lines": [
{
"reference": "SERUM-ARGAN-30",
"quantity": 2,
"unitPrice": "199.00",
},
],
},
)
data = res.json(){
"lead_id": "6f1c2a9e-3b7d-4c11-9a52-0d8e4b7f2c10",
"external_id": "shop_10482",
"order_code": "MA03112026-0042",
"currency": "MAD",
"country": "MA",
"store_id": "b2d4e6f8-1a3c-4e5f-8a9b-0c1d2e3f4a5b",
"status": "new",
"confirmed_at": null,
"articles_amount": "398.00",
"lines": [
{
"line_id": "c0a8e1f2-5d6b-4a7c-9e8f-1a2b3c4d5e6f",
"product_id": "9e8d7c6b-5a4f-4e3d-2c1b-0a9f8e7d6c5b",
"product_reference": "SERUM-ARGAN-30",
"product_name": "Sérum à l'huile d'argan 30 ml",
"variant_id": null,
"variant_label": null,
"quantity": 2,
"unit_price": "199.00"
}
],
"created_at": "2026-11-03T09:58:41.000Z",
"updated_at": "2026-11-03T09:58:41.000Z"
}201— created.200with"duplicate": trueadded — an order with thisexternalIdalready exists for this seller and app; the body is that order (the same Order object, plusduplicate).- An order holds either the seller’s own products or one adopted COD Drop product, never both (
MIXED_SALE_TYPE), and at most one COD Drop line (COD_DROP_PACK_NOT_SUPPORTED).
Errors
| HTTP | Code | Meaning |
|---|---|---|
| 400 | VALIDATION_ERROR | Body shape: a missing field, a number where a money string is expected, both or neither of lineTotal / unitPrice. details[] names each field. |
| 403 | COUNTRY_NOT_ALLOWED | countryCode is not one of the seller’s countries. |
| 404 | PRODUCT_NOT_FOUND | No product, variant or active adoption has this reference. |
| 409 | AMBIGUOUS_PRODUCT_REFERENCE | Several adopted products carry this creator reference; use the seller SKU. |
| 422 | STORE_NOT_FOUND | storeId is not one of the seller’s stores. |
| 422 | LEAD_NO_LINES · LEAD_LINE_BAD_QUANTITY | Empty basket or a quantity that is not a whole number ≥ 1. |
| 422 | LEAD_VARIANT_REQUIRED · INVALID_VARIANT | The product has variants and none could be matched, or the variant is not this product’s. |
| 422 | PRODUCT_INACTIVE · PRODUCT_NOT_IN_LEAD_COUNTRY | The product is switched off, or not sold in countryCode. |
| 422 | MIXED_SALE_TYPE · COD_DROP_PACK_NOT_SUPPORTED | See above. |
| 403 / 422 | ADOPTION_PAUSED · ADOPTION_REMOVED · RESELLER_BLOCKED | The COD Drop adoption behind the reference cannot take orders. |
The Order object
One short shape, the same everywhere: the answers of GET /orders, GET /orders/{externalId}, POST /orders and POST /orders/claim-direct, the sandbox advance helper, and the data of every lead.* event — the read-back and the event stream can never disagree. It carries what an integration needs to follow an order and nothing more. A confirmed order:
{
"lead_id": "6f1c2a9e-3b7d-4c11-9a52-0d8e4b7f2c10",
"external_id": "shop_10482",
"order_code": "MA03112026-0042",
"currency": "MAD",
"country": "MA",
"store_id": "b2d4e6f8-1a3c-4e5f-8a9b-0c1d2e3f4a5b",
"status": "confirmed",
"confirmed_at": "2026-11-03T10:15:05.000Z",
"articles_amount": "398.00",
"lines": [
{
"line_id": "c0a8e1f2-5d6b-4a7c-9e8f-1a2b3c4d5e6f",
"product_id": "9e8d7c6b-5a4f-4e3d-2c1b-0a9f8e7d6c5b",
"product_reference": "SERUM-ARGAN-30",
"product_name": "Sérum à l'huile d'argan 30 ml",
"variant_id": null,
"variant_label": null,
"quantity": 2,
"unit_price": "199.00"
}
],
"created_at": "2026-11-03T09:58:41.000Z",
"updated_at": "2026-11-03T10:15:05.000Z"
}lead_idstringColiSwift order id.
external_idstring | nullYour
externalId(orcs_direct_<id>for a claimed order that had none).order_codestring | nullHuman order number shown in ColiSwift.
currencystring | nullCurrency frozen on the order.
countrystringCountry code.
store_idstring | nullStore.
statusstringWhere the order stands — see status values below.
newconfirmedshippeddeliveredreturnedcancelledout_of_stock
confirmed_attimestamp | nullWhen the order was confirmed with the customer and locked for shipping — the moment
statusturnedconfirmed;nullbefore.articles_amountmoneyFrozen articles total: Σ
unit_price×quantityof the lines. Copy it, never recompute it.lines[]object[]line_id,product_id,product_reference(the SKU),product_name(the product’s name in ColiSwift),variant_id,variant_label(the variant’s name,nullwithout a variant),quantity,unit_price.created_at · updated_attimestampCreation and last change.
Status values
status is the one progress field of the order: new → confirmed → shipped → delivered or returned, or cancelled / out_of_stock on the way.
| status | Meaning | Final? |
|---|---|---|
new | Received; the call centre is working on it (not called yet, no answer, call back later). | No |
confirmed | The order is confirmed with the customer and locked for shipping (confirmed_at is set). | No |
shipped | Handed to the delivery partner, out for delivery or rescheduled — no final delivery outcome yet. | No |
delivered | The parcel reached the customer, fully or partly. | Yes |
returned | The delivery failed for good (refused, cancelled at the door, unreachable…) and the parcel comes back. | Yes — unless ColiSwift relaunches the delivery |
cancelled | The customer cancelled or the order could not be confirmed (wrong number, duplicate, expired). | Yes — unless ColiSwift relaunches the order |
out_of_stock | Waiting for stock before it can go further; it moves on when the stock arrives. | No |
Ignore values you do not know — new ones may be added.
Retrieve an order
/orders/{externalId}By your externalId. Only orders your app created or claimed are visible; anything else is 404 NOT_FOUND.
curl "https://coliswift.com/api/partner/v1/orders/shop_10482" \
-H "Authorization: Bearer $COLISWIFT_ACCESS_TOKEN"const res = await fetch('https://coliswift.com/api/partner/v1/orders/shop_10482', {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.COLISWIFT_ACCESS_TOKEN}`,
},
});
const data = await res.json();$ch = curl_init('https://coliswift.com/api/partner/v1/orders/shop_10482');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('COLISWIFT_ACCESS_TOKEN'),
],
]);
$data = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);import os, requests
res = requests.get(
"https://coliswift.com/api/partner/v1/orders/shop_10482",
headers={"Authorization": f"Bearer {os.environ['COLISWIFT_ACCESS_TOKEN']}"},
)
data = res.json()List changed orders
/ordersupdatedSinceISO 8601requiredOrders whose
updated_atis after this instant.cursorstringFrom
nextCursor.limitintegerDefault 100, max 200.
curl "https://coliswift.com/api/partner/v1/orders?updatedSince=2026-11-01T00%3A00%3A00Z&limit=100" \
-H "Authorization: Bearer $COLISWIFT_ACCESS_TOKEN"const res = await fetch('https://coliswift.com/api/partner/v1/orders?updatedSince=2026-11-01T00%3A00%3A00Z&limit=100', {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.COLISWIFT_ACCESS_TOKEN}`,
},
});
const data = await res.json();$ch = curl_init('https://coliswift.com/api/partner/v1/orders?updatedSince=2026-11-01T00%3A00%3A00Z&limit=100');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('COLISWIFT_ACCESS_TOKEN'),
],
]);
$data = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);import os, requests
res = requests.get(
"https://coliswift.com/api/partner/v1/orders",
headers={"Authorization": f"Bearer {os.environ['COLISWIFT_ACCESS_TOKEN']}"},
params={
"updatedSince": "2026-11-01T00:00:00Z",
"limit": "100",
},
)
data = res.json()This is the reconciliation backstop for a gap in your event stream (an outage on your side), ordered by order id. It is not a feed of the seller’s whole history: only your app’s orders, and updatedSince is mandatory.
Claim the seller’s manual orders
Orders the seller typed in ColiSwift by hand (manual) or imported from a file (file_upload) belong to no app. Claiming attaches them to your app: from then on they behave exactly like orders you created — visible to GET /orders, and their lead.* events are delivered to you. Orders of other apps and of the seller’s store integrations (Shopify, YouCan, WooCommerce, Lightfunnels, Google Sheets) are never claimed. A claim cannot be undone — show the count to the user first. Both calls need orders:write: taking over the seller’s manual orders hands your app their customers’ details.
/orders/claim-direct/previewCounts what a claim would take, without taking anything. Optional since (ISO 8601, on creation date).
{
"count": 966,
"delivered": 410,
"bySource": {
"manual": 900,
"file_upload": 66
},
"oldestCreatedAt": "2026-03-01T09:00:00.000Z",
"newestCreatedAt": "2026-11-01T18:12:00.000Z"
}/orders/claim-directsinceISO 8601Only orders created at or after this instant.
limitinteger, 1–200Page size, default 100. Call again while
hasMoreis true.
curl -X POST "https://coliswift.com/api/partner/v1/orders/claim-direct" \
-H "Authorization: Bearer $COLISWIFT_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"since": "2026-10-01T00:00:00Z",
"limit": 100
}'const res = await fetch('https://coliswift.com/api/partner/v1/orders/claim-direct', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.COLISWIFT_ACCESS_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"since": "2026-10-01T00:00:00Z",
"limit": 100
}),
});
const data = await res.json();$ch = curl_init('https://coliswift.com/api/partner/v1/orders/claim-direct');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('COLISWIFT_ACCESS_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => <<<'JSON'
{
"since": "2026-10-01T00:00:00Z",
"limit": 100
}
JSON,
]);
$data = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);import os, requests
res = requests.post(
"https://coliswift.com/api/partner/v1/orders/claim-direct",
headers={"Authorization": f"Bearer {os.environ['COLISWIFT_ACCESS_TOKEN']}"},
json={
"since": "2026-10-01T00:00:00Z",
"limit": 100,
},
)
data = res.json()Answers { "claimed": [Order + customer], "hasMore": boolean }, oldest first. Each claimed order is the Order object plus a customer block (name, phone, phoneE164, address, city) — on this route only, because you have never seen these customers. An order without an external id gets cs_direct_<lead_id>. Repeating the call is safe: claimed orders are not found again.

