O2M Logo
One to Many
Orders from a Custom Marketplace
Was this page helpful?

Orders from a Custom Marketplace

Send orders from your website or marketplace to the order address of its Custom Marketplace connection.

Overview

A Custom Marketplace connection has its own order address. Your website or marketplace sends each order there, signed with the connection's secret, and O2M saves it like any other order.

Address

Each Custom Marketplace connection has its own address, shown on its Orders tab in O2M. It needs no API key: the connection's signing secret (or its order key) proves the request is yours.

HTTP
POST https://api.o2m.in/api/custom-marketplace/inbound/<connection>/orders

Sign each request

HTTP
X-O2M-Timestamp: 1790000000
X-O2M-Signature: 5f2c9a…
  1. 1Take the time in Unix seconds as the timestamp.
  2. 2Join the timestamp, a full stop and the raw body you are about to send: timestamp.body.
  3. 3Compute the HMAC-SHA256 of that text with the connection's signing secret, in hexadecimal. That is the signature.
  4. 4Send both headers. O2M refuses a request whose timestamp is more than 5 minutes from its own clock.
Node.js
import crypto from "node:crypto";

const body = JSON.stringify(order);
const timestamp = Math.floor(Date.now() / 1000).toString();
const signature = crypto.createHmac("sha256", process.env.O2M_SIGNING_SECRET).update(`${timestamp}.${body}`).digest("hex");

await fetch(process.env.O2M_ORDER_URL, {
  method: "POST",
  headers: { "Content-Type": "application/json", "X-O2M-Timestamp": timestamp, "X-O2M-Signature": signature },
  body,
});

Good to know  If the connection is set to check orders by key instead, send the key in an X-O2M-Key header and no signature.

Body

In O2M's order format, the body is the same as Create an order, without channel: the connection is the channel. If the connection reads your own format, send your order as it is; the connection's mapping finds each value.

Order
{
  "order_id": "W-1001",
  "ordered_at": "2026-11-04T10:00:00+05:30",
  "payment_method": "prepaid",
  "customer": {
    "name": "Ravi",
    "email": "ravi@example.com"
  },
  "shipping_address": {
    "name": "Ravi",
    "phone": "9800000000",
    "address1": "1 MG Road",
    "city": "Pune",
    "state": "Maharashtra",
    "pincode": "411001"
  },
  "lines": [
    {
      "sku": "TEE-S",
      "quantity": 1,
      "unit_price": 499
    }
  ]
}

To cancel an order you sent before, send it again with "status": "cancelled" (in your own format, with a status value the connection lists as cancelled). It is cancelled only before it ships.

Answers

StatusBodyMeaning
201{ "created": true, "order": { … } }The order is saved and its stock reserved.
200{ "created": false, "order": { … } }An order with this order_id was already there; nothing changed.
200{ "duplicate": true }This exact body was handled before; nothing changed.
200{ "cancelled": true, "order": { … } }The order was cancelled.

Errors

StatusCodeMessageWhat to do
401UNAUTHORISEDNot authorisedCheck the signing secret, the timestamp and that you signed the raw body exactly as sent.
409NOT_ACTIVE<name> is not turned on in O2MTurn the connection on in O2M.
403LOCKEDCustom Marketplace is not enabled for this companyAsk your O2M account manager.
400BAD_JSONThe body is not JSONSend a JSON body.
422UNKNOWN_SKUNo item has SKU …Use SKUs that exist in O2M. A refused order can be sent again once fixed.
422order_id is required: your own number for this orderEvery order needs your own order number.
429Too many orders at once. Slow down and retry.At most 120 requests a minute per connection; wait and retry.