For developers: Sado AI API
Send leads to Sado — the agent calls them. The result (summary, lead temperature, next step) comes back to your system through a webhook or the event feed.
Full reference (OpenAPI 3.1): https://api.sadoai.uz/v1/openapi.json
Postman/Insomnia: Import → Link → paste this URL.
1. Get a key
Portal → Settings → API keys. A key is shown only once, and each key has its own scopes: leads:write, leads:read, calls:read, calls:content (summary and transcript), catalog:write.
2. Send a lead
event_id is your own ID: sending it again won’t create a second lead. A consent basis is required (the law requires it).
curl -X POST https://api.sadoai.uz/v1/leads \
-H "Authorization: Bearer $SADO_KEY" \
-H "Content-Type: application/json" \
-d '{
"event_id": "site-form-1042",
"phone": "+998901112233",
"name": "Aziz",
"purpose": "2 xonali kvartira",
"consent": { "basis": "inbound_enquiry", "evidence": "sayt formasi #1042", "captured_at": "2026-09-26T10:00:00+05:00" }
}'3. Get the result — webhook
Portal → Integrations → Add webhook. Every request is signed: X-Sado-Signature = HMAC-SHA256(secret, «timestamp.body»). Check the signature and reject requests older than 5 minutes. If the response isn’t 2xx, it is retried up to 8 times.
import { createHmac, timingSafeEqual } from "node:crypto";
function verify(rawBody: string, headers: Record<string, string>, secret: string) {
const ts = headers["x-sado-timestamp"];
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
const expected = "sha256=" + createHmac("sha256", secret).update(`${ts}.${rawBody}`).digest("hex");
const got = headers["x-sado-signature"] ?? "";
return got.length === expected.length && timingSafeEqual(Buffer.from(got), Buffer.from(expected));
}$ts = $_SERVER['HTTP_X_SADO_TIMESTAMP'];
$body = file_get_contents('php://input');
$expected = 'sha256=' . hash_hmac('sha256', $ts . '.' . $body, $secret);
$ok = abs(time() - (int)$ts) <= 300 && hash_equals($expected, $_SERVER['HTTP_X_SADO_SIGNATURE'] ?? '');…or the event feed (for 1C and systems behind NAT)
If you can’t receive webhooks, poll the feed: oldest to newest, kept for 30 days. After processing a page, save next_cursor and send it as after in the next request.
curl "https://api.sadoai.uz/v1/events?types=call.analyzed,lead.created&after=$CURSOR" \
-H "Authorization: Bearer $SADO_KEY"
# → { "data": [ { "id": "evt_…", "type": "call.analyzed", "data": { "call": {…}, "analysis": {…} } } ], "next_cursor": "…" }4. Catalog: prices and stock
On a call the agent quotes only prices from the catalog. Send up to 1000 items per request; for a full sync, note the start time first and call retire at the end — items you didn’t send are taken off sale. If the catalog isn’t updated for 24 hours, the agent says the price may have changed.
curl -X PUT https://api.sadoai.uz/v1/catalog/items \
-H "Authorization: Bearer $SADO_KEY" -H "Content-Type: application/json" \
-d '{ "source": "shop", "items": [ { "external_id": "NK-42", "name": "Krossovka Nike Air", "name_alt": "Кроссовки Найк", "price_uzs": 1250000, "stock": 3 } ] }'
curl -X POST https://api.sadoai.uz/v1/catalog/items/retire \
-H "Authorization: Bearer $SADO_KEY" -H "Content-Type: application/json" \
-d '{ "source": "shop", "before": "2026-09-26T10:00:00Z" }'Limits and errors
600 requests per minute per key (above that: 429 and Retry-After). Errors are JSON: {error, issues}. Lists go newest to oldest, with a cursor.
Your manager will give you the 1C extension source code and install guide · Questions: write to your manager or the Sado team on Telegram.
