Get your credentials
Open Shop Settings → API. Copy the endpoint URL, API key and API secret. They can be rotated at any time.
API & integrations
If you sell somewhere else as well — a WooCommerce store, a custom site, an app — send those orders into GoTrack.bd so everything is managed in one place.
Three steps, and no keeping two systems in sync by hand.
Open Shop Settings → API. Copy the endpoint URL, API key and API secret. They can be rotated at any time.
Post each order to the orders endpoint as it is placed. Customer, line items and totals are all you need.
Orders appear alongside the ones you take by hand — same stock, same couriers, same profit reporting.
WooCommerce
Install the GoTrack.bd sync plugin, paste in three values, and press Save & Test Connection. New orders start arriving on their own.
Reference
For custom sites and apps. Authenticate with your API key and secret, then post the order.
/api/v1/orders
There is also GET /api/v1/ping,
a lightweight authenticated health check — it is what the plugin's test button calls.
{
"external_source": "woocommerce",
"external_order_id": "42",
"customer": {
"name": "Rahima Akter",
"phone": "01712345678",
"address": "House 12, Road 4, Mirpur, Dhaka"
},
"line_items": [
{
"name": "Cotton Kurti",
"quantity": 2,
"selling_price": 1150.0,
"cost_price": 720.0,
"sku": "KURTI-MRN-L",
"variation": { "Size": "L", "Color": "Maroon" }
}
],
"delivery_charge": 60.0,
"total_selling_price": 2360.0
}
| Field | Type | Required | Notes |
|---|---|---|---|
| customer.phone | string | Required | Used to find an existing customer or create a new one. |
| customer.name | string | Optional | Required only when the customer does not already exist. |
| customer.address | string | Optional | Stored on the customer and sent to the courier at booking time. |
| line_items[].name | string | Required | Product name, used for matching when no SKU is supplied. |
| line_items[].quantity | integer | Required | Must be greater than zero. |
| line_items[].selling_price | decimal | Required | Price per unit, greater than zero. |
| line_items[].cost_price | decimal | Optional | Falls back to the matched product's cost price, or zero. |
| line_items[].sku | string | Optional | Authoritative when present. Matched against variant SKUs, and against product codes written into product names. |
| line_items[].variation | object | Optional | Selected option values, used to resolve the specific variant. |
| external_order_id | string | Optional | Strongly recommended. Makes the request idempotent on replay. |
| external_source | string | Optional | Where the order came from. Defaults to "external". |
| delivery_charge | decimal | Optional | Added to the order total. |
| total_selling_price | decimal | Optional | Derived from line items plus delivery charge when omitted. |
{
"ok": true,
"warnings": [],
"order": {
"id": 4821,
"status": "pending",
"total_selling_price": 2360.0,
"line_items": [
{
"name": "Cotton Kurti - CK-200 — L / Maroon [KURTI-MRN-L]",
"source_name": "Cotton Kurti",
"matched": true,
"matched_product_id": 88,
"matched_variant": "L / Maroon",
"match_strategy": "sku",
"match_score": 1.0
}
]
}
}
Each line item reports how it matched, so catalogue mismatches surface immediately instead of turning up later in your stock figures.
Your website sells Cotton Kurti; your catalogue here calls the same thing Cotton Kurti - CK-200, because the code is how your team knows which one to pick off the shelf. An order that arrived under the website's title would leave that guesswork to whoever packs it, so the name recorded on the order is your catalogue's — product name, variant and code together — with the title your website sent kept alongside it as source_name.
When nothing in your catalogue matches, the item is still recorded, under the title your website sent plus whatever options and SKU came with it — and the order is flagged for you in Shop Settings → API so you can add the product and know exactly which sale it was.
Every request is written down the moment it arrives — before it is read, matched or turned into an order. If anything then goes wrong, the order is retried on its own, and anything still stuck is listed in Shop Settings → API with the reason and a button to try again. A 4xx or 5xx from this endpoint never means the order was thrown away; sending it again is always safe, because the same external_order_id can only ever become one order.
Created
The order was created. The response lists each line item and how it matched.
Idempotent replay
This external_order_id was already received, so the existing order is returned instead of a duplicate.
Unauthorized
The API key or secret is missing or wrong. Nothing is stored.
Malformed body
The body was not valid JSON. It is still saved verbatim, and shown in Shop Settings → API.
Unprocessable
A required field is missing or invalid — the message names it. The order is saved and shown in Shop Settings → API so it can be fixed rather than lost.
Saved, not yet imported
Something went wrong on our side after the order was safely stored. It is retried automatically; sending it again is safe either way.
The API secret is a password. Never put it in client-side code or a public repository. If it leaks, rotate it from Shop Settings — the old credentials stop working immediately.
Bring your website orders into the same place as everything else. Start with a free month.
First month free · Cancel anytime · Support in Bangla and English