Noon

noon Partner API on noon-api-gateway.noon.partners: RS256 JWT service accounts, reads orders, stock, pricing and offers, writes stock, price and shipments.

noon is the largest home grown ecommerce marketplace in the Gulf, operating in the UAE, Saudi Arabia and Egypt, with Namshi as its fashion arm. Unlike almost every Indian marketplace in this reference, noon runs a modern, fully public API platform: a documentation site at noon-docs.noonpartners.dev with every endpoint, a developer portal with logs and analytics, a static sandbox, published rate limits per endpoint, and an event notification system you configure yourself. Namshi runs on the same platform behind a different gateway host, so one integration serves both marketplaces. The main structural thing to understand before writing code is that noon's fulfilment models are not flags, they are different warehouses with different APIs, and only one of them, FBPI, gives you a full order and shipment API.

At a glance

What it is

noon is a marketplace and a retailer at once, operating across three countries with separate storefronts and currencies, plus Namshi for fashion. Most of the API's shape follows from the fulfilment model a seller is on, and the models are mutually exclusive per warehouse.

  • FBN, fulfilled by noon. Stock sits in noon's warehouses and noon fulfils. The seller's API surface is catalogue, pricing and stock into noon, not order fulfilment.
  • FBP, fulfilled by partner. The seller operates the warehouse, with noon's tooling and a partner integration platform at fbpi.noon.partners.
  • FBPI, fulfilled by partner integration. The API native version of FBP: the seller runs their own warehouse system and receives orders, creates shipments, uploads invoices and handles returns entirely through APIs. This is the model a connector wants.
  • Directship, a UAE flow for sellers onboarded after 1 October 2025, processed through Seller Lab.

Two rules from noon's own FAQ matter at design time. A warehouse is tied to one fulfilment type and cannot be converted: moving to FBPI means creating a new warehouse with a new code. And FBPI serves both marketplaces, so a single integration receives orders from noon and from Namshi, distinguished by an mp_code of noon or namshi_v2.

Terminology: a project is the unit of access control and of rate limiting, identified by a project code such as PRJ152772. A partner SKU is your own identifier. An nsku is noon's catalogue identifier, with parent and child levels. A merchant code is prefixed STR.

API access

Sellers and integrators take different routes.

A seller signs in to the noon Partner platform, opens the Access app, goes to API Users, and clicks Add Service Account. You set a display name and username, optionally whitelist IPs and set an expiry, then assign a role. The limits, as published:

  • one service account per partner from the seller portal
  • a maximum of five keys per service account, though noon recommends not running multiple active keys
  • a session lifetime of 30 days
  • deactivation of a key is immediate, and subsequent logins with it fail

Creating the account produces a JSON key file containing a key_id and an RSA private_key. That file is the credential.

An integrator gets their own service account the same way, but must not ask sellers for theirs. To act on a seller's behalf you run the OAuth flow, which creates service accounts inside your project with access to the seller's project. The API User service then lets you create and manage credentials for those accounts programmatically, through CreateCredential and RemoveCredentials, and the OAuth service exposes CreateToken to exchange an authorisation code for an access token and ExchangeToken to complete the flow.

Hosts:

Every path is versioned per domain, for example /stock/v1/stock-update and /fbpi/v1/shipment/create. There is no published deprecation calendar. There is no official SDK, but every endpoint page carries a runnable Python example.

Note

The static sandbox is a genuine drop in replacement: same paths, same bodies, same headers, same credentials, same schema validation and the same rate limits, with deterministic mock responses and no side effects. The one exception is login. The sandbox has no identity service, so send POST /identity/public/v1/api/login to the production host and point only the subsequent calls at the sandbox host. Because sandbox traffic counts against your project quota, it is the right place to test 429 handling rather than a place to hammer.

Authentication

There is no static API key and no password. You sign a short lived JWT with the private key from your service account file, exchange it for a session, and then send the session cookies.

  1. Read the service account JSON, which holds key_id and private_key.
  2. Build a JWT with sub set to key_id, iat set to the current epoch seconds and jti set to a fresh UUID, signed RS256 with the private key.
  3. POST it to the login endpoint, optionally scoping the session to a project.
  4. Keep the session cookies from the response and send them on every subsequent request.
POST https://noon-api-gateway.noon.partners/identity/public/v1/api/login
Content-Type: application/json
User-Agent: YourAppName/1.0.0

{
  "token": "<RS256-signed-JWT>",
  "default_project_code": "PRJ152772"
}

The response sets session cookies. An authenticated call then looks like this:

curl -X POST 'https://noon-api-gateway.noon.partners/stock/v1/stock-update' \
  -H 'Content-Type: application/json' \
  -H 'User-Agent: YourAppName/1.0.0' \
  -b 'session=<cookie-from-login>' \
  -d '{"items":[{"warehouse_code":"WH-AE-01","partner_sku":"SKU-1001","qty":42}]}'

The User-Agent header is not optional. noon's documentation warns that requests without one may be rejected, which is an easy way to lose a day debugging.

Session lifetime is 30 days, so a refresh job that re-logs in daily is comfortably safe. There is no refresh token: you simply sign a new JWT and log in again. Treat a 401 as "log in again", and a key deactivation as permanent.

Multi account handling is by project code. One project per seller, rate limits counted per project, and the session scoped with default_project_code. An integrator holds one credential and many project scopes, which is a cleaner model than the per seller static passwords used by most Indian marketplaces.

Whoami returns the user code and username of the authenticated session, which is the cheapest health check for a credential.

Objects we can read

Orders

FBPI orders are both pushed and pollable. The push is a webhook carrying the order; the poll is a list call for reconciliation.

POST https://noon-api-gateway.noon.partners/fbpi/v1/fbpi-orders/list

The request body takes a mandatory warehouse_code and optional created_after and created_before, both UTC ISO 8601 of the form YYYY-MM-DDTHH:MM:SSZ and both inclusive. Pagination is a next_token query parameter, pages are up to 50 orders, and the filters must not change between pages: the token controls paging only and does not re-scope the result.

The documentation gives the schema without a populated example, so the field list is reproduced here and the sample response is not published.

GetFbpiOrder fetches a single order, and its description records the intended flow plainly: a webhook is sent to your system containing the order details whenever an order is created on noon or Namshi.

The two status fields are the most important design detail here. mp_status is what the marketplace thinks, integration_status is what your warehouse has told noon. They move independently, and a connector must reconcile both rather than collapsing them into one state.

Order items

Items live inside the order and are keyed by mp_item_nr. That is the identifier you put in a shipment and the one you mark unavailable. partner_sku is the join back to your own catalogue.

Products and listings

The catalogue is split across three domains.

Content handles product data: ListCategories, ListCategoryAttributes to discover what a category requires, UpsertProduct to create or update a product, and GetContent to read content back for specified products.

Catalog handles SKU identity and bulk import: SkuGenerate to mint partner SKUs, BatchSkuMap to map your partner_sku values onto nsku_children, BatchParentSkuRename and BatchChildSkuRename, ParentSkuDelete which cascades to all child SKUs, ChildSkuDelete, and BarcodeSkuMap which links a barcode to a partner SKU and creates the barcode if it does not exist. Bulk work goes through GenerateImportSignedUrl, which returns a signed URL for direct upload to a Google Cloud Storage bucket, accepting csv, tsv, json, xlsx, xlsm and parquet, then CreateBarcodeImport and GetImportStatus for progress and success and failure counts. CreateBarcodeImport takes exactly one source: a file_url, a BigQuery table, or inline items.

Offer exposes the selling side: GET /offer/v1/product/{partner_sku} returns the noon sku, title, brand and an offers array with an offer_code and country_code per country. That is how you see one partner SKU's presence across the UAE, Saudi and Egypt at once.

Impex handles exports: CreateExport, GetExportCategoryList and GetExportStatus, the last returning status and a download link. Use this for bulk pulls rather than paging an API.

Inventory

POST https://noon-api-gateway.noon.partners/stock/v1/stock-list

The request is a list of warehouse_code and partner_sku pairs, and the response returns a quantity and a status per pair. Inventory is therefore explicitly per warehouse, unlike Snapdeal's single pool.

ListWarehouses at POST /warehouse-platform/v1/warehouses/list returns the partner's warehouses, filterable by fulfillment_system_code and paginated with next_token, which is how you discover the warehouse codes to use.

Shipments and tracking

POST https://noon-api-gateway.noon.partners/fbpi/v1/shipment/create
GET  https://noon-api-gateway.noon.partners/fbpi/v1/... (GetShipment, by order and shipment number)

CreateShipment takes the warehouse_code, a unique integration_shipment_nr you generate with no enforced format, the fbpi_order_nr, an awbs array of courier and awb_nr, and an items array of mp_item_nr. The courier is either the literal noon or your own logistics provider's name, so you can ship on noon's network or your own.

If you are using noon logistics, GetNoonLogisticsAWBs generates the AWB numbers to put in that call. AddShipmentCourierAwbs adds a courier and AWB after the fact, which the documentation says exists for when warehouse operations hit scanning problems with the current one. CancelShipment cancels.

Returns and cancellations

The published returns surface is thin relative to the rest. ListReturnReferences lists return items and their barcode references matching a barcode, for a given set of merchants, which is a warehouse receiving tool rather than a returns ledger. Cancellation shows up on the order as MP_ITEM_STATUS_CANCELLED with a cancellation_reason_code, and on your side as UpdateOrder, which marks one or more items unavailable before a shipment is created.

Return and RTO flows are described in noon's seller help centre as part of FBPI, so more likely exists than is published in the API reference. Confirm during onboarding.

Payments and settlements

No settlement, payout or fee API appears in the published domain list. This is the single largest gap in an otherwise complete platform. Settlement data has to come from Seller Lab reports or from the Impex export domain if a suitable export category exists. Check GetExportCategoryList first.

Customers

GET https://noon-api-gateway.noon.partners/fbpi/v1/fbpi-order/{fbpi_order_nr}/customer-details/get

Customer data is deliberately separated from the order and returns only first_name, last_name, city and administrative_division, all in latin characters. There is no street address, phone or email in this response. That is a privacy design, and it means the shipping label has to come from noon's logistics rather than being printed from data you hold.

Locations

Warehouses, through ListWarehouses. A warehouse code is bound to one fulfilment system and cannot change model.

Purchase orders

For the FBPO model there is GetPurchaseOrder, retrieving a purchase order by number. There is a matching event type, FBPO::PO_SYNC.

Writing back: listings, price and stock

Stock.

POST https://noon-api-gateway.noon.partners/stock/v1/stock-update

The body is an items array, each with a required warehouse_code and partner_sku, a nullable qty integer and a nullable processing_time. The response mirrors the request with a status per item, so partial success is the normal case: always read the per item status rather than trusting the HTTP code. Quantities are absolute per warehouse, not deltas.

Price.

POST https://noon-api-gateway.noon.partners/pricing/v1/pricing/upsert

Each item carries a required partner_sku and country_code, and nullable price, msrp and is_active. Three things follow. Price is per country, so the same SKU has an independent price in the UAE, Saudi and Egypt. msrp is the list price and price is what sells. And is_active is on the pricing call, which means activating and deactivating a listing is a pricing operation on noon, not a catalogue one. BatchGetPricing reads the same shape back.

For cross border there is a separate domain: BatchUpsertProduct, BatchUpsertTransferPrice and BatchGetTransferPrice set the transfer price used for cross border selling.

Listings. UpsertProduct creates and updates products, the catalogue domain manages SKU identity and mapping, and bulk loads go through a signed URL upload followed by an import job you poll with GetImportStatus.

Order and fulfilment writes. UpdateOrder marks items unavailable before shipment. CreateShipment, AddShipmentCourierAwbs and CancelShipment manage shipments. UploadFbpiOrderInvoice attaches a PDF invoice covering a whole order and UploadShipmentInvoice attaches one covering a single shipment. CreateSandboxOrder creates a test order in the sandbox so the whole FBPI path can be exercised end to end.

Batch responses are uniformly per item with a status object. Build every writer to read those.

Webhooks and notifications

Event Notifications is self serve, which is rare in this set of platforms.

  • You create up to five destinations per project. The only destination type currently supported is an HTTPS webhook: a valid HTTPS URL plus optional credentials as key value pairs.
  • You subscribe destinations to event types. Event types are named NAMESPACE::TYPE, for example FBPO::PO_SYNC, and are listed by ListEventTypes.
  • Destinations are managed by API as well as by UI: CreateHttpsDestination, GetDestination, ListDestinations and UpdateDestination.
  • Delivery failures are retried and logged automatically, and the developer portal exposes delivery logs and analytics.

Every event arrives in the same envelope:

{
  "event_schema_version": 1,
  "event_type": "FBPO::PO_SYNC",
  "metadata": {
    "message_id": "uuid",
    "destination_id": "string",
    "published_at": "timestamp",
    "project_code": "string"
  },
  "payload": { }
}

Two cautions. First, noon states that Event Notifications does not validate the business body's schema: the producing team owns it, so it can change under you. Validate defensively and persist the raw body. Second, if your server enforces IP firewall rules, allowlist noon's delivery addresses, published on 2026-09-21 as 34.76.219.109, 35.233.95.217 and 104.155.39.2.

Deduplicate on message_id. No signature header is documented, so the optional destination credentials and the IP allowlist are the authentication story.

Rate limits and pagination

Rate limits are per project code, so one project's usage never eats another's quota, and they are published per endpoint on that endpoint's page.

The algorithm is a fixed window counter with a second, stricter burst window. Both are tracked independently and a request must pass both, which means you cannot spend a minute's quota in the first second. Exceeding either returns 429.

On the endpoints checked on 2026-09-21, the published plan was 1500 requests per 60 seconds for both the rate and the burst window, on APILogin, UpdateStock, GetStock, BatchUpsertPricing, ListFbpiOrders and CreateShipment. Read the number off the endpoint page rather than assuming it, since noon documents it per endpoint precisely because it varies.

Pagination is cursor based: a next_token on list calls, with a page size of up to 50 on FBPI orders. Filters must be identical across pages of the same scan.

A workable cadence: rely on Event Notifications for order arrival, run ListFbpiOrders hourly over an overlapping window as reconciliation, push stock changes as they happen with absolute quantities, upsert prices in batches, and use Impex exports rather than paged reads for anything catalogue sized.

Mapping to the unified model

Gaps and open questions

  • No settlement or payout API. Every other domain is covered. Ask whether settlement data is available through an Impex export category before designing around Seller Lab reports.
  • The returns surface in the API reference is limited to barcode reference lookup, while the seller help centre describes returns and RTO flows as part of FBPI. Something is either unpublished or handled through events. Resolve during onboarding.
  • Endpoint pages give schemas rather than populated sample responses, so field semantics such as the exact format of order_created_at and processing_time need confirming against the sandbox.
  • No webhook signature scheme is documented. Destination credentials and the published IP allowlist are the only authentication for inbound events, and noon explicitly does not validate the business body's schema.
  • The 1500 per 60 seconds limit was uniform across the endpoints sampled, which suggests a platform default rather than a tuned per endpoint number. Re-read each endpoint page before relying on it.
  • FBN and FBP sellers get a much smaller surface than FBPI. If the target sellers are not on FBPI, most of the order and shipment section does not apply, and a new warehouse code would be needed to move.
  • Whether Namshi and the Dubai Mall variant differ in event types or domains beyond the gateway host is not covered here.

Sources