Connect your existing delivery, ERP or e-commerce system to Tariq's route optimization. Three API calls cover the whole loop.
هذه الصفحة موجّهة لمبرمج أو مسؤول الأنظمة في شركتك. لا تحتاج لتغيير برنامجك الحالي — يبقى كما هو، ونضيف له تحسين المسارات فقط.
البرنامج عندك يرسل الطلبات إلى طريق، وطريق يرتّبها على السائقين بأفضل مسار، ثم يُرجع لك حالة كل طلب لحظة تسليمه. العمل المطلوب من المبرمج عادةً يوم إلى يومين.
Tariq does not replace your system. It sits beside it: you keep your orders, customers and invoicing where they are, and Tariq handles the part none of those systems do — deciding which driver takes which stop, in which order.
Drivers use the Tariq Android app — nothing to build on your side. Your dispatcher can keep working in your existing software; Tariq's dashboard is optional.
https://tariq.codeator.ai (HTTPS only)X-API-Key header25000, not 25000.00lat/lng are optional but strongly recommended. Without them an order cannot be placed on a route accuratelyIn the Tariq dashboard, sign in as the account owner and go to Settings → API Keys → Create key. The key is shown once and starts with tk_. Store it as a server-side secret.
Send orders whenever your system creates them, or in one batch each morning. Both work.
/api/v1/orders — one ordercurl -X POST https://tariq.codeator.ai/api/v1/orders \
-H "X-API-Key: tk_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"customer": "Zainab Mohammed",
"phone": "07701234567",
"area": "Karrada",
"cod": 45000,
"lat": 33.3140,
"lng": 44.3930,
"priority": "normal",
"time_window": "morning",
"external_ref": "YOUR-ORDER-NO-8891",
"barcode": "PKG-2026-0142"
}'
# 200 OK
{"id": 4417, "status": "pending", "external_ref": "YOUR-ORDER-NO-8891", "duplicate": false, "message": "Created"}
external_ref, and send it every time. It is your own order number, and Tariq keeps it separate from barcode — which is the sticker on the parcel, scanned by the driver. A company that has both can send both.external_ref again and you get the order that already exists, with "duplicate": true, and nothing new is created. Every webhook carries external_ref back, so you never need a mapping table./api/v1/orders/bulk — up to 500 at oncecurl -X POST https://tariq.codeator.ai/api/v1/orders/bulk \
-H "X-API-Key: tk_your_key_here" \
-H "Content-Type: application/json" \
-d '[
{"customer":"Ali Hasan","phone":"07701111111","area":"Mansour","cod":120000,"lat":33.345,"lng":44.348},
{"customer":"Noor Sabri","phone":"07702222222","area":"Dora","cod":70000,"lat":33.254,"lng":44.391}
]'
# 200 OK — partial success is normal: check "errors"
{"created": 2, "errors": [], "orders": [{"id":4418,...},{"id":4419,...}]}
errors with their array index. Always read errors.| Field | Required | Notes |
|---|---|---|
customer | yes | Recipient name |
phone | yes | Iraqi mobile, e.g. 07701234567 |
area | yes | District name, e.g. Karrada |
cod | yes | Integer IQD. Use 0 for prepaid orders |
lat, lng | no | Strongly recommended — routing quality depends on it |
priority | no | normal (default) or urgent |
time_window | no | any (default), morning, afternoon, evening |
external_ref | no | Your own order number. Returned in every webhook, and a repeat with the same value returns the existing order instead of creating a duplicate |
barcode | no | The barcode printed on the parcel, scannable by the driver app. Not the same thing as external_ref |
store_id | no | Origin branch, if you run more than one |
secondary_phone | no | Alternate number |
address_description | no | Free text landmark — useful in Baghdad |
notes | no | Note shown to the driver |
Call this once when the day's orders are loaded. Tariq solves the routing problem and assigns every pending order to a driver with a stop number. That assignment is what the drivers' phones read.
/api/v1/routescurl "https://tariq.codeator.ai/api/v1/routes?depart_hour=8" \
-H "X-API-Key: tk_your_key_here"
# 200 OK
{
"routes": [
{
"driver": 1,
"driver_id": 12,
"driver_name": "Hussein Kareem",
"driver_phone": "07801234567",
"google_maps_url": "https://www.google.com/maps/dir/...",
"orders": [
{"stop":1, "order_id":4417, "customer":"Zainab Mohammed", "area":"Karrada", "cod":45000},
{"stop":2, "order_id":4419, "customer":"Noor Sabri", "area":"Dora", "cod":70000}
]
}
],
"depart_hour": 8,
"traffic_multiplier": 1.5,
"total_time_seconds": 7420
}
GET, it publishes a new plan and reassigns every pending order. Call it when you want to (re)plan — do not poll it on a timer, or drivers will see their stops change under them.| Parameter | Default | Meaning |
|---|---|---|
depart_hour | current hour | Hour of day (0–23) drivers leave. Baghdad traffic is modelled per hour, so this changes the result |
store_id | all | Plan one branch only. The branch's location becomes the start point |
depot_lat, depot_lng | Baghdad centre | Explicit start point, if you do not use branches |
order_ids you pushed against those returned, and anything missing stays pending for the next run.Two options. Webhooks are strongly preferred: your system learns about a delivery within seconds instead of minutes, and you make no wasted calls.
In the Tariq dashboard: Settings → Webhooks → Add webhook. Enter your HTTPS endpoint and a shared secret you generate. Tariq POSTs JSON to that URL whenever an order changes state.
// Tariq POSTs this to your endpoint
{
"event": "order.delivered",
"company_id": 7,
"timestamp": "2026-09-22T11:04:19.223401",
"data": {
"order_id": 4417,
"status": "delivered",
"customer": "Zainab Mohammed",
"phone": "07701234567",
"area": "Karrada",
"cod": 45000,
"cod_collected": 45000,
"barcode": "YOUR-SYSTEM-REF-8891",
"assigned_driver_id": 12,
"received_by": "Zainab",
"fail_reason": null,
"fail_reason_code": null,
"postpone_reason": null,
"postpone_reason_code": null,
"postponed_to": null,
"delivered_at": "2026-09-22T11:04:18",
"completed_at": "2026-09-22T11:04:18"
}
}
| Event | Fires when |
|---|---|
order.created | A single order is created via the API |
order.bulk_created | A bulk import finishes. Payload is {count, order_ids}, not a full order |
order.delivered | Driver marks the stop delivered |
order.failed | Delivery failed — see fail_reason_code |
order.postponed | Rescheduled — see postponed_to |
order.returned | Returned to warehouse |
order.exchanged | Exchanged at the door |
Leave the event list empty to receive all of them, or subscribe to only the ones you need.
Every request carries X-Tariq-Signature: sha256=<hex> — an HMAC-SHA256 of the raw request body, keyed with your shared secret. Verify it before trusting the payload.
# Python / Flask
import hmac, hashlib
@app.route("/tariq-webhook", methods=["POST"])
def tariq_webhook():
raw = request.get_data() # raw bytes, not request.json
expected = "sha256=" + hmac.new(SECRET.encode(), raw, hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, request.headers.get("X-Tariq-Signature", "")):
return "", 401
event = request.get_json()
# ... update your own order record here ...
return "", 200
// Node / Express — note express.raw, not express.json
app.post("/tariq-webhook", express.raw({type: "application/json"}), (req, res) => {
const expected = "sha256=" + require("crypto")
.createHmac("sha256", SECRET).update(req.body).digest("hex");
if (expected !== req.headers["x-tariq-signature"]) return res.sendStatus(401);
const event = JSON.parse(req.body.toString());
// ... update your own order record here ...
res.sendStatus(200);
});
// PHP
$raw = file_get_contents("php://input");
$expected = "sha256=" . hash_hmac("sha256", $raw, $SECRET);
if (!hash_equals($expected, $_SERVER["HTTP_X_TARIQ_SIGNATURE"] ?? "")) { http_response_code(401); exit; }
$event = json_decode($raw, true);
// ... update your own order record here ...
2xx quickly. Tariq waits 5 seconds, then counts a timeout as a failure200order_id + status as the same eventtest event while you buildIf you cannot expose a public endpoint, poll instead. Every 5–10 minutes is enough; the data does not change faster than drivers move.
# Everything closed out — poll each status you care about
curl "https://tariq.codeator.ai/api/v1/orders?status=delivered" -H "X-API-Key: tk_..."
curl "https://tariq.codeator.ai/api/v1/orders?status=failed" -H "X-API-Key: tk_..."
# Full detail for one order, including POD and signature flags
curl "https://tariq.codeator.ai/api/v1/orders/4417" -H "X-API-Key: tk_..."
Returns the 200 most recent orders, newest first.
| Endpoint | Purpose |
|---|---|
GET /api/v1/orders | List orders. Optional ?status= |
GET /api/v1/orders/{id} | One order, full detail including driver notes and POD flags |
PATCH /api/v1/orders/{id} | Update status from your side. Body: {"status":"delivered"} |
GET /api/v1/drivers | Drivers with their last known GPS position |
PATCH fires the same webhooks as the driver app, so if your system is the one closing orders, guard against reacting to your own update.| Status | Meaning |
|---|---|
pending | Waiting to be delivered. Only these are routed |
delivered | Delivered. cod_collected holds the cash the driver actually took — it is null when the order was closed through the API rather than the app |
failed | Attempted, not delivered |
postponed | Rescheduled to postponed_to |
returned / exchanged | Returned to warehouse / swapped at the door |
| Code | Meaning |
|---|---|
400 | Missing or invalid fields — the message says which |
401 | Missing, wrong or deactivated X-API-Key |
403 | Subscription expired or suspended |
404 | Order or branch not found, or belongs to another company |
/orders/bulk, then call /routesMost teams finish this in one to two days.
Email tariq@codeator.ai with your company name and what you are connecting, and we will help directly.