Cargotime

Получить событие отслеживания

Скачать OpenAPI

Когда происходит событие отслеживания, на которое вы подписаны, Cargotime отправляет POST-запрос на ваш callback_url.

После получения события как можно скорее верните 200 OK. Если обработка занимает время, сначала поставьте событие в очередь, отправьте ответ, а затем обработайте его асинхронно. Cargotime ждёт ответ 10 секунд.

Доставка считается успешной при любом статусе 2xx. Cargotime повторяет доставку после статусов 408, 409, 425, 429 и 5xx, а также при таймаутах и ошибках DNS или сети. После статусов 400, 401, 403, 404 и 422 повторной попытки не будет. При статусе 429 Cargotime учитывает заголовок Retry-After, если он передан. Всего может быть не более пяти попыток.

Чтобы проверить источник запроса, используйте секрет вебхука и заголовки x-cargotime-timestamp и x-cargotime-signature. Значение подписи — HMAC SHA-256 от строки timestamp + '.' + rawBody с префиксом sha256=. В rawBody должно попасть исходное тело запроса без изменений. Проверять подпись необязательно, но мы рекомендуем это делать.

Node.js / Express

import crypto from 'node:crypto';import express from 'express';const app = express();const secret = process.env.CARGOTIME_WEBHOOK_SECRET;if (!secret) {    throw new Error('CARGOTIME_WEBHOOK_SECRET is not set');}function queueWebhook(payload: unknown): void {    // Здесь можно поставить событие в очередь,    // сохранить его в базе данных или передать внутреннему сервису.    console.log('Cargotime прислал вебхук:', payload);}app.post('/webhooks/cargotime', express.raw({ type: 'application/json' }), (req, res) => {    const timestamp = req.header('x-cargotime-timestamp');    const signature = req.header('x-cargotime-signature');    if (!timestamp || !signature) {        return res.sendStatus(401);    }    const expected =        'sha256=' + crypto.createHmac('sha256', secret).update(timestamp).update('.').update(req.body).digest('hex');    const signatureBuffer = Buffer.from(signature);    const expectedBuffer = Buffer.from(expected);    if (signatureBuffer.length !== expectedBuffer.length || !crypto.timingSafeEqual(signatureBuffer, expectedBuffer)) {        return res.sendStatus(401);    }    const payload = JSON.parse(req.body.toString('utf8'));    queueWebhook(payload);    return res.sendStatus(200);});app.listen(3000, () => {    console.log('Сервер вебхуков запущен на порту 3000');});

Python / FastAPI

import hmacimport hashlibimport osfrom fastapi import FastAPI, Request, HTTPExceptionapp = FastAPI()secret = os.environ["CARGOTIME_WEBHOOK_SECRET"].encode()def enqueue_webhook(payload: dict) -> None:    # Здесь можно поставить событие в очередь,    # сохранить его в базе данных или передать внутреннему сервису.    print("Cargotime прислал вебхук:", payload)@app.post("/webhooks/cargotime")async def cargotime_webhook(request: Request):    body = await request.body()    timestamp = request.headers.get("x-cargotime-timestamp")    signature = request.headers.get("x-cargotime-signature")    if not timestamp or not signature:        raise HTTPException(status_code=401)    digest = hmac.new(        secret,        timestamp.encode() + b"." + body,        hashlib.sha256,    ).hexdigest()    expected = f"sha256={digest}"    if not hmac.compare_digest(signature, expected):        raise HTTPException(status_code=401)    payload = await request.json()    enqueue_webhook(payload)    return {"ok": True}

Параметры заголовков

x-cargotime-signature*string

HMAC SHA-256-подпись строки timestamp + '.' + rawBody с префиксом sha256=. Для rawBody используйте исходное тело запроса без изменений.

x-cargotime-timestamp*string

Метка времени Unix, использованная для подписи

x-cargotime-event-id*string

Уникальный идентификатор события, совпадающий с payload.id

Форматuuid
x-cargotime-delivery-id*string

Уникальный идентификатор попытки доставки

Форматuuid

Тело запроса

application/json

Типы TypeScript

Используйте тип request body в TypeScript.

Тело ответа

Примеры запросов

POST/trackingWebhookDelivery