For developersDevelopers ke liye

API & webhooksAPI aur webhooks

Built your own store? Send each cash-on-delivery order to Yaqeen and get the answer back in the same request — ship, confirm first, or ask for an advance. When the answer changes (the buyer confirms, cancels or pays the advance), we send a signed webhook.Apna store banaya hai? Har COD order Yaqeen ko bhejein aur usi request mein jawab lein — bhejein, pehle confirm, ya advance lein. Jab jawab badle (khareedar confirm, cancel ya advance de), hum signed webhook bhejte hain.

API keys are given by the Yaqeen team during the pilot. Pilot ke dauran API keys Yaqeen team deti hai. Ask for a key on WhatsAppWhatsApp par key maangein.

AuthenticationAuthentication

Base address: Base address: https://useyaqeen.com/api/v1. Send your key with every request:. Har request ke saath apni key bhejein:

Authorization: Bearer yq_live_…

Keep the key on your server — never in a website, app or public code. If it leaks, ask us to revoke it and we'll give you a new one.Key sirf apne server par rakhein — website, app ya public code mein kabhi nahi. Agar leak ho jaye to humein batayein, hum band kar ke nayi key denge.

1. Send an order1. Order bhejein

POST/api/v1/orders

curl https://useyaqeen.com/api/v1/orders \
  -H "Authorization: Bearer $YAQEEN_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "external_id": "1001",
    "phone": "0300 1234567",
    "name": "Ayesha Khan",
    "address": "House 12, Street 4, Gulberg III",
    "city": "Lahore",
    "items": [{ "name": "Lawn suit", "quantity": 1 }],
    "amount": 4200,
    "payment": "cod"
  }'
  • external_id, phone, address are required. external_id is your own order number.zaroori hain. external_id aap ka apna order number hai.
  • Sending the same external_id again returns the order we already have (duplicate: true) and uses no second credit — safe to retry.Wohi external_id dobara bhejne par wohi order wapas milta hai (duplicate: true) aur doosra credit nahi lagta — retry mehfooz hai.
  • "payment": "prepaid" orders aren't checked, stored or charged. orders check, save ya charge nahi hote.

Answer (201):Jawab (201):

{
  "order": {
    "id": "8f1c…",
    "external_id": "1001",
    "status": "awaiting_confirmation",
    "label": "Confirming",
    "decision": "yellow",
    "score": 50,
    "reasons": ["New buyer — no delivery history yet"],
    "advance": null,
    "created_at": "2026-10-27T10:15:02Z",
    "decided_at": "2026-10-27T10:15:02Z",
    "outcome_at": null
  }
}

What each status meansHar status ka matlab

statuslabelWhat to doKya karein
ready_to_shipShipShip it.Bhej dein.
awaiting_confirmationConfirmingWe're asking the buyer on WhatsApp (then a short Urdu call). Wait.Khareedar se WhatsApp (phir Urdu call) par poocha ja raha hai. Intezar karein.
awaiting_advanceHold – advanceThe buyer was asked for an advance, paid to you. Hold until it arrives.Khareedar se advance maanga gaya, aap ko. Aane tak rokein.
advance_expiredNo advance – don't shipNo advance within 24 hours. We recommend not shipping.24 ghante mein advance nahi aaya. Mashwara: na bhejein.
unreachableCouldn't reach buyerNo reply on WhatsApp or the call. Your call.WhatsApp ya call par jawab nahi. Faisla aap ka.
cancelled_by_buyerCancelled by buyerThe buyer doesn't want it. Don't ship.Khareedar ko nahi chahiye. Na bhejein.
receivedNot checked (no credits)Saved, but your credits ran out. Top up and it's checked.Save hua, lekin credits khatam. Top up par check hoga.

It's advice, not a block: you can always ship any order. The reasons are about your own order; you never see other shops or their orders.Yeh mashwara hai, rukawat nahi: aap hamesha koi bhi order bhej sakte hain. Wajahen aap ke apne order ki hain; aap kabhi doosri dukanen ya un ke orders nahi dekhte.

2. Look up an order2. Order dekhein

GET/api/v1/orders/{id}

GET/api/v1/orders?external_id=1001

3. Report what happened at the door3. Darwaze par kya hua, batayein

POST/api/v1/orders/{id}/outcome

{ "outcome": "delivered" }      // or "refused", "delivery_problem"; optional "at": ISO time
  • refused — only when the buyer refused the parcel at the door. — sirf jab khareedar ne darwaze par parcel wapas kiya.
  • delivery_problem — courier failures: wrong address, rider didn't go, phone off. Never counted against the buyer. — courier ki nakaami: ghalat pata, rider nahi gaya, phone band. Kabhi khareedar ke khilaf nahi.
  • Cancelled before shipping? Report nothing — it's never recorded.Bhejne se pehle cancel? Kuch na batayein — yeh kabhi darj nahi hota.

These results keep the network honest for every shop. See the Yeh nateeje har dukan ke liye network ko durust rakhte hain. Dekhein Fair Use PolicyInsaaf ki Policy.

4. Webhooks4. Webhooks

PUT/api/v1/webhook

{ "url": "https://your-store.pk/yaqeen-webhook" }   →   { "webhook": { "url": "…", "secret": "whsec_…" } }

The secret is shown once; save it. Calling PUT again gives a new secret. GET shows the current address, DELETE turns webhooks off, and POST /api/v1/webhook/test sends a ping.Secret sirf ek dafa dikhta hai; save kar lein. PUT dobara karne par naya secret milta hai. GET maujooda address dikhata hai, DELETE webhooks band karta hai, aur POST /api/v1/webhook/test ek ping bhejta hai.

Every time an order's status changes we POST:Jab bhi order ka status badle, hum POST karte hain:

{ "event": "order.updated", "sent_at": "…", "order": { …same as above… } }

Check it really came from Yaqeen (Node.js):Tasdeeq karein ke yeh waqai Yaqeen se aaya (Node.js):

import { createHmac, timingSafeEqual } from "node:crypto";

// rawBody: the request body exactly as received (a string, before JSON.parse)
function fromYaqeen(rawBody, headers, secret) {
  const ts = headers["x-yaqeen-timestamp"];
  const given = Buffer.from(headers["x-yaqeen-signature"] ?? "");
  const expected = Buffer.from(createHmac("sha256", secret).update(`${ts}.${rawBody}`).digest("base64"));
  const fresh = Math.abs(Date.now() / 1000 - Number(ts)) < 300; // 5 minutes
  return fresh && given.length === expected.length && timingSafeEqual(given, expected);
}
  • Answer with any 2xx within 10 seconds.10 second ke andar koi bhi 2xx jawab dein.
  • If your server doesn't answer with a 2xx, we try again after 1 minute, 5 minutes, 30 minutes, 2 hours and 6 hours. A retry always carries the order's latest status, so you may get one event for several changes. Handle repeats safely (use order.id and order.status), and GET the order if you need to catch up.Agar aap ka server 2xx na de, to hum 1 minute, 5 minute, 30 minute, 2 ghante aur 6 ghante baad dobara bhejte hain. Har retry mein order ka taaza status hota hai, is liye kayi tabdeeliyon ka ek hi event aa sakta hai. Dohraye events ko mehfooz tareeqe se sambhalein (order.id aur order.status istemal karein), aur zaroorat ho to order GET kar lein.
  • Webhook addresses must be public https addresses.Webhook address public https hona chahiye.

Errors and limitsErrors aur hadein

Errors look like { "error": { "code", "message", "fields"? } }.Errors aise hote hain: { "error": { "code", "message", "fields"? } }.

401 unauthorizedMissing or wrong API key.
404 not_foundNo such order for your shop.
409 already_recorded / cancelled_before_shippingThat result can't be recorded.
422 invalid_order / invalid_outcome / invalid_webhookSee error.fields for what to fix.
429 rate_limitedMore than 120 requests a minute with one key.

Get an API keyAPI key lein