Partner API Sapa Moto
Рассчитайте доставку, создайте заказ, следите за курьером и получайте подписанные вебхуки — прямо из своей системы заказов.
Partner API соединяет систему вашего магазина, ресторана или склада с курьерами Sapa Moto в Алматы. Всё, что менеджер делает в кабинете, может делать ваша система: рассчитать доставку, создать и изменить заказ, отменить его, следить за курьером, забрать доказательства вручения — и получать подписанный вебхук на каждую смену статуса.
Как это работает
- Расчёт —
POST /v1/quotesвозвращает цену, её разбивку и ETA. Цена держится 10 минут. - Заказ —
POST /v1/ordersсоздаёт заказ (по цене расчёта). В ответе —tracking_urlдля получателя иdelivery_code, который получатель называет курьеру. - Готов —
POST /v1/orders/{id}/ready, когда заказ собран (необязательно; иначе действует норматив сборки точки). - События — вебхуки
order.status_changed,order.courier_assigned,order.eta_changed,order.delivered… - Доказательства —
GET /v1/orders/{id}/proof: фото, проверка кода, геоточка и время.
Среды и ключи
https://partner-sandbox.sapamoto.kz/v1— Песочница — тестовые ключи sk_test_…, виртуальный курьер, без денегhttps://partner.sapamoto.kz/v1— Боевая среда — ключи sk_live_…
| Песочница | Боевая среда | |
|---|---|---|
| Ключ | sk_test_… | sk_live_… |
| Доступна | сразу после создания организации | после чек-листа интеграции и договора |
| Курьеры | виртуальный курьер, 2–3 минуты на заказ | настоящие курьеры |
| Деньги | нет — никогда не попадают в счета и отчёты | счета, депозит, наложенный платёж |
| Пути и форматы | одинаковые | одинаковые |
Ключи создаются в кабинете, раздел «Интеграция». Ключ показывается один раз — сохраните его в хранилище секретов. Подробнее — Аутентификация.
Первый заказ за 5 минут
Нужен тестовый ключ (sk_test_…). Песочница принимает адреса с координатами, так что точка забора пока не нужна.
1. Рассчитайте доставку
curl https://partner-sandbox.sapamoto.kz/v1/quotes \
-H "Authorization: Bearer $SAPA_KEY" \
-H "Content-Type: application/json" \
-d '{
"pickup": {"address": "Алматы, Абая 10", "latitude": 43.2389, "longitude": 76.9286},
"dropoff": {"address": "Алматы, Жандосова 58", "latitude": 43.214, "longitude": 76.88}
}'const res = await fetch("https://partner-sandbox.sapamoto.kz/v1/quotes", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.SAPA_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
pickup: { address: "Алматы, Абая 10", latitude: 43.2389, longitude: 76.9286 },
dropoff: { address: "Алматы, Жандосова 58", latitude: 43.214, longitude: 76.88 },
}),
});
const quote = await res.json();
console.log(quote.quote_id, quote.price.amount / 100, "₸", quote.eta_minutes, "мин");import os, requests
quote = requests.post(
"https://partner-sandbox.sapamoto.kz/v1/quotes",
headers={"Authorization": f"Bearer {os.environ['SAPA_KEY']}"},
json={
"pickup": {"address": "Алматы, Абая 10", "latitude": 43.2389, "longitude": 76.9286},
"dropoff": {"address": "Алматы, Жандосова 58", "latitude": 43.214, "longitude": 76.88},
},
timeout=10,
).json()
print(quote["quote_id"], quote["price"]["amount"] / 100, "₸")<?php
$ch = curl_init('https://partner-sandbox.sapamoto.kz/v1/quotes');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('SAPA_KEY'), 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode([
'pickup' => ['address' => 'Алматы, Абая 10', 'latitude' => 43.2389, 'longitude' => 76.9286],
'dropoff' => ['address' => 'Алматы, Жандосова 58', 'latitude' => 43.214, 'longitude' => 76.88],
]),
]);
$quote = json_decode(curl_exec($ch), true);
echo $quote['quote_id'], ' ', $quote['price']['amount'] / 100, " ₸\n";Ответ — 201 с quote_id, price ({"amount": 145000, "currency": "KZT"} — 1 450 ₸ в тиынах), breakdown,
eta_minutes и valid_until.
2. Создайте заказ
Передайте quote_id, свой номер заказа в external_id и новый Idempotency-Key — тогда повтор после таймаута
никогда не создаст второй заказ.
curl https://partner-sandbox.sapamoto.kz/v1/orders \
-H "Authorization: Bearer $SAPA_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"external_id": "SHOP-100245",
"quote_id": "'"$QUOTE_ID"'",
"pickup": {"address": "Алматы, Абая 10", "latitude": 43.2389, "longitude": 76.9286},
"dropoff": {"address": "Алматы, Жандосова 58", "latitude": 43.214, "longitude": 76.88, "apartment": "41"},
"recipient": {"name": "Мадина", "phone": "+77011234567"},
"comment": "Позвонить за 10 минут"
}'import { randomUUID } from "node:crypto";
const order = await fetch("https://partner-sandbox.sapamoto.kz/v1/orders", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.SAPA_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": randomUUID(), // сохраните вместе с заказом и используйте при повторах
},
body: JSON.stringify({
external_id: "SHOP-100245",
quote_id: quote.quote_id,
pickup: { address: "Алматы, Абая 10", latitude: 43.2389, longitude: 76.9286 },
dropoff: { address: "Алматы, Жандосова 58", latitude: 43.214, longitude: 76.88, apartment: "41" },
recipient: { name: "Мадина", phone: "+77011234567" },
}),
}).then((r) => r.json());
console.log(order.id, order.status, order.tracking_url, order.delivery_code);import uuid
order = requests.post(
"https://partner-sandbox.sapamoto.kz/v1/orders",
headers={
"Authorization": f"Bearer {os.environ['SAPA_KEY']}",
"Idempotency-Key": str(uuid.uuid4()), # сохраните вместе с заказом и используйте при повторах
},
json={
"external_id": "SHOP-100245",
"quote_id": quote["quote_id"],
"pickup": {"address": "Алматы, Абая 10", "latitude": 43.2389, "longitude": 76.9286},
"dropoff": {"address": "Алматы, Жандосова 58", "latitude": 43.214, "longitude": 76.88},
"recipient": {"name": "Мадина", "phone": "+77011234567"},
},
timeout=10,
).json()
print(order["id"], order["status"], order["tracking_url"])<?php
$ch = curl_init('https://partner-sandbox.sapamoto.kz/v1/orders');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('SAPA_KEY'),
'Content-Type: application/json',
'Idempotency-Key: ' . bin2hex(random_bytes(16)), // сохраните и используйте при повторах
],
CURLOPT_POSTFIELDS => json_encode([
'external_id' => 'SHOP-100245',
'quote_id' => $quote['quote_id'],
'pickup' => ['address' => 'Алматы, Абая 10', 'latitude' => 43.2389, 'longitude' => 76.9286],
'dropoff' => ['address' => 'Алматы, Жандосова 58', 'latitude' => 43.214, 'longitude' => 76.88],
'recipient' => ['name' => 'Мадина', 'phone' => '+77011234567'],
]),
]);
$order = json_decode(curl_exec($ch), true);
echo $order['id'], ' ', $order['status'], ' ', $order['tracking_url'], "\n";Заказ стартует в статусе created. В песочнице виртуальный курьер берёт его через несколько секунд и доводит до
delivered примерно за две минуты.
3. Следите за заказом
curl https://partner-sandbox.sapamoto.kz/v1/orders/SHOP-100245 -H "Authorization: Bearer $SAPA_KEY"{id} принимает наш id или ваш external_id. Лучше, чем опрашивать: добавьте адрес вебхука в кабинете (или через
POST /v1/webhooks) и получайте подписанные события на каждое изменение.
4. Переходите в боевую среду
Когда сценарий в песочнице работает, пройдите чек-лист интеграции в кабинете — заказ создан, вебхук принят с верной
подписью, повтор вебхука обработан, отмена, недоставка. Аккаунт-менеджер включит боевые ключи. Поменяйте хост на
partner.sapamoto.kz, а ключ — на sk_live_…; больше ничего не меняется.
Соглашения
- JSON, UTF-8,
snake_case. Игнорируйте незнакомые поля — внутриv1мы добавляем поля. - Деньги —
{"amount": <целые тиыны>, "currency": "KZT"}; 1 ₸ = 100 тиынов. Поля запроса с окончанием_tiyn— просто целые числа в тиынах. - Время — ISO 8601 со смещением (
2026-10-24T15:00:00+05:00); в ответах — UTC (Z). - Координаты — WGS-84, десятичные градусы.
- Ошибки —
application/problem+jsonсо стабильнымcode, см. Ошибки. - Id запроса — в каждом ответе есть
X-Request-Id; передавайте свой, чтобы связать логи.