# Get Order Data from FBPI Webhooks
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
This guide walks you through handling an FBPI order webhook event and retrieving full order and customer data from the FBPI APIs. By the end, your integration will parse the `order_nr` from the webhook payload, fetch the complete order details, and store the data your system needs to process the order.
## How It Works
```mermaid
sequenceDiagram
participant noon as noon
participant W as Your Webhook
participant S as Your System
noon->>W: POST FBPI::ORDER_SYNC (order_nr in payload)
W-->>noon: HTTP 200 (acknowledge immediately)
S->>noon: GET /fbpi/v1/fbpi-order/{order_nr}/get
noon-->>S: Full order details (items, statuses, pricing)
S->>noon: GET /fbpi/v1/fbpi-order/{order_nr}/customer-details/get
noon-->>S: Customer name, city, administrative division
S->>S: Merge order + customer data, store for processing
```
Key points about this flow:
- **Return HTTP 200 immediately.** noon's Event Notifications system is push-based and at-least-once. Return 2xx before any processing — delaying the response risks retries and duplicate events.
- **The webhook payload contains only `order_nr`.** All order details, item statuses, and customer data come from subsequent API calls, not the webhook body.
- **`order_nr` is your primary key.** Use it for all downstream processing and API retrieval.
- **Use exponential backoff on API calls.** If `GetFbpiOrder` returns a transient error, the order may not yet be available. Retry with backoff.
## Prerequisites
- An active FBPI integration warehouse with a configured webhook URL — see [Warehouse Setup][fbpi/warehouse-setup]
- Your webhook destination registered in Event Notifications — see [Event Notifications][event-notifications-intro]
- An authenticated API session — see [Authenticating Your Requests][authenticating-requests]
---
## Step 1 — Receive the Webhook Event
noon sends an `FBPI::ORDER_SYNC` event to your webhook endpoint when an order is placed. Parse the `order_nr` from the payload, return HTTP 200 immediately, and enqueue the `order_nr` for background processing.
Webhook payload:
```json
{
"event_schema_version": 1,
"event_type": "FBPI::ORDER_SYNC",
"metadata": {
"message_id": "msg-abc123",
"destination_id": "dest-xyz456",
"published_at": "2026-04-09T08:42:15Z",
"project_code": "your-project-code"
},
"payload": {
"order_nr": "NFBO123456789"
}
}
```
Validation checklist before processing:
- `event_type` equals `FBPI::ORDER_SYNC`
- `payload.order_nr` is present and non-empty
- `event_schema_version` equals `1`
If any of these checks fail, return HTTP 200 anyway (to prevent retries) and log the raw payload for investigation. Do not return non-2xx on validation failure.
**You'll know this worked when** your endpoint returns HTTP 200 and you can see the event in the Event Notifications log.
---
## Step 2 — Retrieve Full Order Details
Call `GetFbpiOrder` (`GET /fbpi/v1/fbpi-order/{fbpi_order_nr}/get`) with the `order_nr` from the webhook to fetch the complete order.
```python
import requests
session = get_authenticated_session()
order_nr = "NFBO123456789" # from webhook payload
response = session.get(
f"https://noon-api-gateway.noon.partners/fbpi/v1/fbpi-order/{order_nr}/get",
headers={"User-Agent": "MyApp/1.0.0"},
timeout=30,
)
response.raise_for_status()
order = response.json()
```
```javascript
const client = await getAuthenticatedClient();
const orderNr = "NFBO123456789"; // from webhook payload
const response = await client.get(
`https://noon-api-gateway.noon.partners/fbpi/v1/fbpi-order/${orderNr}/get`,
{ headers: { "User-Agent": "MyApp/1.0.0" } }
);
const order = response.data;
```
```go
orderNr := "NFBO123456789" // from webhook payload
client := getAuthenticatedClient()
url := fmt.Sprintf("https://noon-api-gateway.noon.partners/fbpi/v1/fbpi-order/%s/get", orderNr)
req, _ := http.NewRequest(http.MethodGet, url, nil)
req.Header.Set("User-Agent", "MyApp/1.0.0")
client.Timeout = 30 * time.Second
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
var order map[string]any
json.NewDecoder(resp.Body).Decode(&order)
```
**Response:**
```json
{
"fbpi_order_nr": "NFBO123456789",
"mp_code": "noon",
"mp_order_nr": "NF123456789",
"mp_country_code": "ae",
"customer_country_code": "ae",
"merchant_code": "STR-12345",
"currency_code": "AED",
"warehouse_code": "WH-NOON-001",
"order_created_at": "2026-04-09T08:42:15Z",
"items": [
{
"mp_item_nr": "NFBO123456789-1",
"partner_sku": "MY-SKU-001",
"mp_status": "MP_ITEM_STATUS_CONFIRMED",
"integration_status": "INTEGRATION_ITEM_STATUS_ACKNOWLEDGED",
"delivered_invoice_price": 149.99,
"cancellation_reason_code": null
}
]
}
```
Key response fields:
| Field | Description |
|---|---|
| `fbpi_order_nr` | Primary key for all downstream API calls |
| `mp_code` | Marketplace source: `"noon"` or `"namshi"` |
| `customer_country_code` | Country from which the customer placed the order |
| `merchant_code` | Your merchant identifier, prefixed with `STR` |
| `warehouse_code` | Integration warehouse assigned to fulfil this order |
**`mp_status` values** — the marketplace's view of each item:
| Value | Meaning |
|---|---|
| `MP_ITEM_STATUS_CONFIRMED` | Item is active and confirmed by the marketplace |
| `MP_ITEM_STATUS_CANCELLED` | Item has been cancelled by the marketplace |
| `MP_ITEM_STATUS_UNSPECIFIED` | Default — treat as unresolved |
**`integration_status` values** — your integration's view of each item:
| Value | Meaning |
|---|---|
| `INTEGRATION_ITEM_STATUS_ACKNOWLEDGED` | Order received and acknowledged by your webhook |
| `INTEGRATION_ITEM_STATUS_OUT_OF_STOCK` | Item marked out of stock by your integration |
| `INTEGRATION_ITEM_STATUS_SHIPPED` | Shipment created for this item |
| `INTEGRATION_ITEM_STATUS_UNSPECIFIED` | Default — treat as unresolved |
**You'll know this worked when** you receive a response with `items` populated and `integration_status` set to `INTEGRATION_ITEM_STATUS_ACKNOWLEDGED`.
| Error | What it means | What to do |
|---|---|---|
| HTTP 404 | Order not yet available | Retry with exponential backoff — the order may not be queryable immediately |
| HTTP 401 | Session expired | Re-authenticate and retry |
For the full schema, see [GetFbpiOrder API Reference][get-fbpi-order].
---
## Step 3 — Retrieve Customer Details
Call `GetFbpiOrderCustomerData` (`GET /fbpi/v1/fbpi-order/{fbpi_order_nr}/customer-details/get`) to fetch the customer's name and delivery location. Use the same `order_nr`.
```python
import requests
session = get_authenticated_session()
order_nr = "NFBO123456789"
response = session.get(
f"https://noon-api-gateway.noon.partners/fbpi/v1/fbpi-order/{order_nr}/customer-details/get",
headers={"User-Agent": "MyApp/1.0.0"},
timeout=30,
)
response.raise_for_status()
customer = response.json()
```
```javascript
const client = await getAuthenticatedClient();
const orderNr = "NFBO123456789";
const response = await client.get(
`https://noon-api-gateway.noon.partners/fbpi/v1/fbpi-order/${orderNr}/customer-details/get`,
{ headers: { "User-Agent": "MyApp/1.0.0" } }
);
const customer = response.data;
```
```go
orderNr := "NFBO123456789"
client := getAuthenticatedClient()
url := fmt.Sprintf("https://noon-api-gateway.noon.partners/fbpi/v1/fbpi-order/%s/customer-details/get", orderNr)
req, _ := http.NewRequest(http.MethodGet, url, nil)
req.Header.Set("User-Agent", "MyApp/1.0.0")
client.Timeout = 30 * time.Second
resp, _ := client.Do(req)
defer resp.Body.Close()
var customer map[string]any
json.NewDecoder(resp.Body).Decode(&customer)
```
**Response:**
```json
{
"first_name": "Ahmed",
"last_name": "Al Rashid",
"city": "Dubai",
"administrative_division": "Dubai"
}
```
All fields are returned in Latin characters.
**You'll know this worked when** you receive a response with `first_name` and `city` populated for the order.
For the full schema, see [GetFbpiOrderCustomerData API Reference][fbpi-customer-data].
---
## Recommended Processing Flow
Use this sequence in your webhook worker:
1. Receive the webhook event → return HTTP 200 immediately.
2. Extract `order_nr` from `payload.order_nr`.
3. Call `GetFbpiOrder` with `order_nr`.
4. Call `GetFbpiOrderCustomerData` with `order_nr`.
5. Merge the order and customer data and persist them in your system.
6. Record processing status and outcome for monitoring and replay.
---
## Testing
Use `CreateSandboxOrder` (`POST /fbpi/v1/sandbox-order/create`) to trigger a test webhook event against your warehouse.
```python
session = get_authenticated_session()
response = session.post(
"https://noon-api-gateway.noon.partners/fbpi/v1/sandbox-order/create",
json={
"warehouse_code": "WH-NOON-001",
"idempotency_key": "wh-test-1",
"items": [
{
"status": "MP_ITEM_STATUS_CONFIRMED"
}
],
"country_code": "ae"
},
headers={"User-Agent": "MyApp/1.0.0"},
timeout=30,
)
response.raise_for_status()
result = response.json()
# result["fbpi_order_nr"] — verify this arrives at your webhook
```
```javascript
const client = await getAuthenticatedClient();
const response = await client.post(
"https://noon-api-gateway.noon.partners/fbpi/v1/sandbox-order/create",
{
warehouse_code: "WH-NOON-001",
idempotency_key: "wh-test-1",
items: [{ status: "MP_ITEM_STATUS_CONFIRMED" }],
country_code: "ae"
},
{ headers: { "Content-Type": "application/json", "User-Agent": "MyApp/1.0.0" } }
);
// response.data.fbpi_order_nr — verify this arrives at your webhook
```
**What to observe:**
1. Your webhook endpoint receives an `FBPI::ORDER_SYNC` event within a few seconds.
2. The event's `payload.order_nr` matches the `fbpi_order_nr` returned by `CreateSandboxOrder`.
3. `GetFbpiOrder` returns a populated response for that `order_nr`.
4. `GetFbpiOrderCustomerData` returns a response with `first_name` and `city`.
5. The [FBPI Orders Dashboard][fbpi/dashboard] shows a successful webhook delivery and acknowledgment for the sandbox order.
**Common failures:**
| Symptom | Likely cause | What to do |
|---|---|---|
| Webhook never fires | Warehouse not active or webhook URL misconfigured | Check warehouse status in Seller Lab — see [Warehouse Setup][fbpi/warehouse-setup] |
| `GetFbpiOrder` returns 404 | Order not yet queryable | Retry with exponential backoff |
| Dashboard shows failed delivery | Webhook returned non-2xx or timed out | Check your endpoint logs; ensure it responds within the timeout window |
---
## Next Steps
- [Managing Your Orders][fbpi/order-flow] — process the order after you've retrieved its data
- [FBPI Orders Dashboard][fbpi/dashboard] — monitor webhook delivery attempts and acknowledgment status
- [GetFbpiOrder API Reference][get-fbpi-order] — full response schema
- [GetFbpiOrderCustomerData API Reference][fbpi-customer-data] — full customer data schema
- [CreateSandboxOrder API Reference][fbpi-sandbox-order] — full sandbox order schema