Orders API

Read orders, change their status and receive every new order as it happens. Built for call centers, carriers, ERPs and COD platforms.

Authentication

Create a credential in the store dashboard, under Settings, Integrations and API. Each credential has a token and a secret and only sees the store that created it. Send both on every request, in one of these ways:

X-Api-Token: 50c6...-2175
X-Api-Secret: secret_ae4e...
Authorization: Basic base64(token:secret)

Older keys starting with pd_live_ still work with Authorization: Bearer pd_live_....

Base URL: https://www.shopqila.com/api/v1. JSON responses, amounts as decimal strings ("129.90") next to the currency. Limit of 600 requests per minute per credential. Errors come as {"error": "...", "field": "..."}.

Endpoints

GET/storeStore name, country, currency and language. Handy to test the credential.
GET/ordersList sorted by order number. Filters: status, created_from and created_to (order date, like 2026-10-18, in the store time zone), updated_since (ISO 8601, by last change), after (order number), limit (up to 250). The response has next for pagination.
GET/orders/{number}One order.
PATCH/orders/{number}Changes status, tracking, note and tags. Cancelling or returning puts the stock back.

Status: pending, confirmed, shipped, delivered, cancelled, returned.

curl -X PATCH https://www.shopqila.com/api/v1/orders/1042 \
  -H "X-Api-Token: YOUR_TOKEN" -H "X-Api-Secret: YOUR_SECRET" -H "Content-Type: application/json" \
  -d '{"status": "shipped", "tracking": {"code": "PL123456", "carrier": "InPost", "url": "https://inpost.pl/sledzenie?n=PL123456"}}'

Order

{
  "id": "6f1c...", "number": 1042, "name": "#1042", "status": "pending",
  "payment_method": "cod", "payment_status": "pending", "currency": "PLN",
  "subtotal": "218.00", "discount": "21.80", "shipping": "0.00", "total": "196.20", "shipping_method": "",
  "customer": {"name": "Anna Kowalska", "phone": "+48600123456", "email": ""},
  "address": {"country": "PL", "state": "MZ", "state_name": "Mazowieckie", "city": "Warszawa",
              "zip": "00-001", "street": "ul. Marszałkowska", "number": "10", "complement": "m. 4",
              "neighborhood": "", "reference": ""},
  "extra_fields": {}, "items": [{"sku": "SER-30", "title": "Serum", "variant": "30 ml",
              "quantity": 2, "price": "109.00", "discount": "21.80", "product_id": "...", "variant_id": "..."}],
  "tracking": {"code": "", "carrier": "", "url": ""}, "language": "pl", "channel": "meta", "campaign": "...",
  "note": "", "tags": [], "created_at": "2026-10-18T14:02:11Z", "updated_at": "2026-10-18T14:02:11Z",
  "shipped_at": null, "delivered_at": null
}

Example with made-up data.

Webhooks and postback

Add the URL (https) in the same place as the credential. Webhook events: order.created and order.updated. Each delivery is a POST with {"event", "source", "sent_at", "order"}; source tells whether the change came from the store, the dashboard or the api. Reply 2xx within 10 seconds; otherwise we retry after 5 and after 30 seconds.

The postback is one per store, fires on order.created, and uses the method you choose: POST and PUT send the same JSON body; GET sends only event, order_id, number, status, payment_method, payment_status, total and currency as query parameters, with no customer data.

Check the signature with the secret (whsec_...). For GET, the signed content is the query string.

X-Shopqila-Event: order.created
X-Shopqila-Timestamp: 1760796131
X-Shopqila-Signature: sha256=HMAC_SHA256(secret, timestamp + "." + body)
X-Shopqila-Delivery: 9f2c41d0a7b3e8c15d6f0a2b
X-Shopqila-Store: store id (the same as GET /store)

The same headers also go out with the X-Paydrop- prefix, for integrations built before the name change.

# Python
import hashlib, hmac
expected = hmac.new(secret.encode(), f"{timestamp}.".encode() + body, hashlib.sha256).hexdigest()
ok = hmac.compare_digest("sha256=" + expected, signature)

// Node
const expected = crypto.createHmac("sha256", secret).update(timestamp + "." + body).digest("hex");
const ok = crypto.timingSafeEqual(Buffer.from("sha256=" + expected), Buffer.from(signature));

Reject deliveries whose timestamp is more than 5 minutes off. A retry repeats the same X-Shopqila-Delivery: store it and ignore what you already got. Each credential and webhook belongs to one store; if you serve several stores, use X-Shopqila-Store and each store's secret.