# 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