Send test webhook
Download OpenAPISends a tracking.test event to your callback_url.
Authorization
api_key In: query
Path Parameters
Webhook ID
uuidResponse Body
application/json
curl -X POST "https://example.com/v2/webhooks/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/test"{ "success": true, "data": { "success": true, "http_status": 200 }, "status": "OK", "status_description": "Request completed successfully"}{ "success": true, "data": { "success": false, "http_status": 500, "error_message": "fetch failed" }, "status": "OK", "status_description": "Request completed successfully"}Delete webhook DELETE
Previous Page
Receive tracking event Webhook
When an event you subscribed to occurs, TimeToCargo sends a `POST` request to your `callback_url`. Return `200 OK` as soon as you receive the event. If processing takes time, enqueue the event, send the response, and then process it asynchronously. TimeToCargo waits up to 10 seconds for a response. Delivery succeeds with any `2xx` status. TimeToCargo retries after `408`, `409`, `425`, `429`, and `5xx` statuses, as well as timeouts and DNS or network errors. It does not retry after `400`, `401`, `403`, `404`, or `422`. After a `429` response, TimeToCargo honors the `Retry-After` header when present. Each delivery can have up to five attempts. To verify the source of the request, use the webhook secret and the `x-timetocargo-timestamp` and `x-timetocargo-signature` headers. The signature is an HMAC SHA-256 digest of `timestamp + '.' + rawBody`, prefixed with `sha256=`. Use the unchanged request body as `rawBody`. Signature verification is optional, but recommended. ### Node.js / Express ```ts import crypto from 'node:crypto'; import express from 'express'; const app = express(); const secret = process.env.TIMETOCARGO_WEBHOOK_SECRET; if (!secret) { throw new Error('TIMETOCARGO_WEBHOOK_SECRET is not set'); } function queueWebhook(payload: unknown): void { // Enqueue the event, save it to your database, // or pass it to another service for processing. console.log('Webhook received from TimeToCargo:', payload); } app.post('/webhooks/timetocargo', express.raw({ type: 'application/json' }), (req, res) => { const timestamp = req.header('x-timetocargo-timestamp'); const signature = req.header('x-timetocargo-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('Webhook server is running on port 3000'); }); ``` ### Python / FastAPI ```python import hmac import hashlib import os from fastapi import FastAPI, Request, HTTPException app = FastAPI() secret = os.environ["TIMETOCARGO_WEBHOOK_SECRET"].encode() def enqueue_webhook(payload: dict) -> None: # Enqueue the event, save it to your database, # or pass it to another service for processing. print("Webhook received from TimeToCargo:", payload) @app.post("/webhooks/timetocargo") async def timetocargo_webhook(request: Request): body = await request.body() timestamp = request.headers.get("x-timetocargo-timestamp") signature = request.headers.get("x-timetocargo-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} ```