Receive orders from a shop
Turn the orders of a shop into orders in BIRP, once each, then confirm or cancel them.
Version v1.1, updated
On this page
You will create in BIRP the orders your shop receives, with their customer, lines, prices and addresses. Each order keeps the id the shop gave it, so importing it twice is refused.
Before you start
A key with
orders:writeandorders:read, andcustomers:writeif you create customers with the order.The products of the order in BIRP, as finished products, linked to your ids or with their SKU.
Note. Orders accept finished products. A line with resale goods answers 422 validation_failed, naming the line.
Steps
Name the customer
Name a customer BIRP already knows in customer, as a reference. Or create it with the order in customer_upsert, which works like the customer upsert of Match and update customers.
{
"source": "woocommerce",
"external_id": "cust-77",
"match_by": [
"email"
],
"data": {
"country_code": "FR",
"customer_type": "b2b",
"email": "achats@example.com",
"name": "Epicerie Exemple SARL"
}
}Send the order
POST /v1/orders creates the order as a draft. Send source and external_id, the id the shop gave the order. A second import of the same order then answers 409 external_id_conflict, so it is never created twice.
curl -X POST "https://api.birp.io/v1/orders" \
-H "Authorization: Bearer $BIRP_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"currency":"EUR","customer":{"external_id":"cust-77","source":"woocommerce"},"expected_at":"2026-09-29T06:00:00Z","external_id":"order-5512","lines":[{"product":{"sku":"FP-BREAD-500"},"quantity":"20","unit_price":"3.20"}],"notes":"Deliver before 7:00","ordered_at":"2026-09-27T08:00:00Z","shipping_address":{"city":"Paris","company":"Epicerie Exemple SARL","country_code":"FR","email":null,"line1":"12 rue des Exemples","line2":null,"name":"Claire Exemple","phone":"+33 0 00 00 00 00","postal_code":"00000","region":null},"source":"woocommerce"}'const response = await fetch("https://api.birp.io/v1/orders", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.BIRP_API_KEY}`,
"Idempotency-Key": crypto.randomUUID(),
"Content-Type": "application/json",
},
body: JSON.stringify({
"currency": "EUR",
"customer": {
"external_id": "cust-77",
"source": "woocommerce"
},
"expected_at": "2026-09-29T06:00:00Z",
"external_id": "order-5512",
"lines": [
{
"product": {
"sku": "FP-BREAD-500"
},
"quantity": "20",
"unit_price": "3.20"
}
],
"notes": "Deliver before 7:00",
"ordered_at": "2026-09-27T08:00:00Z",
"shipping_address": {
"city": "Paris",
"company": "Epicerie Exemple SARL",
"country_code": "FR",
"email": null,
"line1": "12 rue des Exemples",
"line2": null,
"name": "Claire Exemple",
"phone": "+33 0 00 00 00 00",
"postal_code": "00000",
"region": null
},
"source": "woocommerce"
}),
});
if (!response.ok) throw new Error(`BIRP API error ${response.status}`);
const result = await response.json();<?php
$ch = curl_init("https://api.birp.io/v1/orders");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("BIRP_API_KEY"),
"Idempotency-Key: " . bin2hex(random_bytes(16)),
"Content-Type: application/json",
],
CURLOPT_POSTFIELDS => <<<'JSON'
{
"currency": "EUR",
"customer": {
"external_id": "cust-77",
"source": "woocommerce"
},
"expected_at": "2026-09-29T06:00:00Z",
"external_id": "order-5512",
"lines": [
{
"product": {
"sku": "FP-BREAD-500"
},
"quantity": "20",
"unit_price": "3.20"
}
],
"notes": "Deliver before 7:00",
"ordered_at": "2026-09-27T08:00:00Z",
"shipping_address": {
"city": "Paris",
"company": "Epicerie Exemple SARL",
"country_code": "FR",
"email": null,
"line1": "12 rue des Exemples",
"line2": null,
"name": "Claire Exemple",
"phone": "+33 0 00 00 00 00",
"postal_code": "00000",
"region": null
},
"source": "woocommerce"
}
JSON,
CURLOPT_RETURNTRANSFER => true,
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);import os
import uuid
import requests
response = requests.request(
"POST",
"https://api.birp.io/v1/orders",
json={
"currency": "EUR",
"customer": {
"external_id": "cust-77",
"source": "woocommerce"
},
"expected_at": "2026-09-29T06:00:00Z",
"external_id": "order-5512",
"lines": [
{
"product": {
"sku": "FP-BREAD-500"
},
"quantity": "20",
"unit_price": "3.20"
}
],
"notes": "Deliver before 7:00",
"ordered_at": "2026-09-27T08:00:00Z",
"shipping_address": {
"city": "Paris",
"company": "Epicerie Exemple SARL",
"country_code": "FR",
"email": None,
"line1": "12 rue des Exemples",
"line2": None,
"name": "Claire Exemple",
"phone": "+33 0 00 00 00 00",
"postal_code": "00000",
"region": None
},
"source": "woocommerce"
},
headers={
"Authorization": f"Bearer {os.environ['BIRP_API_KEY']}",
"Idempotency-Key": str(uuid.uuid4()),
},
timeout=10,
)
response.raise_for_status()
result = response.json()Each line names a product, a
quantityand aunit_price, as decimal strings.Without
currency, the base currency of the company applies.shipping_addressandbilling_addressare kept with the order as you send them.Without
expected_at, the expected date is the order date.
Change it while it is a draft
PATCH /v1/orders/{id} changes the lines, the currency, the addresses, the expected date and the notes while the order is a draft. The customer and the order date stay as created.
Confirm or cancel
POST /v1/orders/{id}/confirm confirms a draft. POST /v1/orders/{id}/cancel cancels a draft or a confirmed order and needs a reason.
Once BIRP starts producing an order, the API refuses to cancel it: cancel it in BIRP, where the people who produce it decide.
Check the result
GET /v1/orders?source=woocommerce&external_id=order-5512 returns the order with its status and lines. Confirmed orders keep confirmed_at.
What can go wrong
Related
- orders
- customers
- references-and-external-ids
- idempotency