API Reference

The ShipTriage REST API lets you create shipments, check status, manage notifications, and handle exceptions programmatically.

Base URL: https://www.shiptriage.eu/api/v1

Authentication

All API requests require an API key passed as a Bearer token in the Authorization Dashboard.

bash
curl -H "Authorization: Bearer st_your_api_key_here" \
  https://www.shiptriage.eu/api/v1/shipments
Security: API keys are hashed (SHA-256) before storage. We never store your key in plaintext. Treat your API key like a password — don't commit it to version control.

Rate Limits

API requests are rate-limited per API key. Current limits:

PlanRequests/minShipmentsChecks/month
Free6010100
Starter1201001,000
Pro3001,00010,000

Rate limit headers (X-RateLimit-Limit, X-RateLimit-Remaining) are included in every response.

Endpoints

Shipments

POST
/api/v1/shipments

Create one or more shipments for monitoring

GET
/api/v1/shipments

List shipments with pagination and status filter

POST
/api/v1/shipments/:id/resolve

Mark a shipment as resolved

Notifications

GET
/api/v1/notifications/channels

List notification channels

POST
/api/v1/notifications/channels

Create a notification channel

PUT
/api/v1/notifications/channels/:id

Update a notification channel

DELETE
/api/v1/notifications/channels/:id

Delete a notification channel

POST
/api/v1/notifications/channels/:id/test

Send a test notification

Webhooks & Stats

GET
/api/v1/webhooks

List webhook delivery attempts

GET
/api/v1/stats

Get shipment and usage statistics

GET
/api/v1/activity

Get activity log

System

GET
/api/health

Health check (no auth required)

Code Examples

Create shipments

curl
curl -X POST https://www.shiptriage.eu/api/v1/shipments \
  -H "Authorization: Bearer st_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "shipments": [
      { "trackingNumber": "00340434161094042684", "customerRef": "ORDER-001" },
      { "trackingNumber": "00340434161094042691", "customerRef": "ORDER-002" }
    ]
  }'
python
import requests

API_KEY = "st_your_api_key"
BASE_URL = "https://www.shiptriage.eu/api/v1"

response = requests.post(
    f"{BASE_URL}/shipments",
    headers={"Authorization": f"Bearer {API_KEY}"},
    json={
        "shipments": [
            {"trackingNumber": "00340434161094042684", "customerRef": "ORDER-001"},
            {"trackingNumber": "00340434161094042691", "customerRef": "ORDER-002"},
        ]
    },
)

print(response.json())
# {"success": true, "results": {"created": 2, "skipped": 0, "errors": []}}
javascript
const API_KEY = "st_your_api_key";

const response = await fetch("https://www.shiptriage.eu/api/v1/shipments", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    shipments: [
      { trackingNumber: "00340434161094042684", customerRef: "ORDER-001" },
      { trackingNumber: "00340434161094042691", customerRef: "ORDER-002" },
    ],
  }),
});

const data = await response.json();
console.log(data);
php
<?php
$apiKey = "st_your_api_key";

$ch = curl_init("https://www.shiptriage.eu/api/v1/shipments");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer $apiKey",
        "Content-Type: application/json",
    ],
    CURLOPT_POSTFIELDS => json_encode([
        "shipments" => [
            ["trackingNumber" => "00340434161094042684", "customerRef" => "ORDER-001"],
            ["trackingNumber" => "00340434161094042691", "customerRef" => "ORDER-002"],
        ],
    ]),
]);

$response = curl_exec($ch);
curl_close($ch);
echo $response;

List critical shipments

curl
curl "https://www.shiptriage.eu/api/v1/shipments?status=CRITICAL&limit=50" \
  -H "Authorization: Bearer st_your_api_key"

Webhook Signature Verification

When you configure a webhook URL, ShipTriage signs every request with an HMAC-SHA256 signature using your webhook secret. The signature is sent in the X-ShipTriage-Signature header.

javascript
const crypto = require("crypto");

function verifyWebhook(payload, signature, secret) {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(payload)
    .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(signature, "hex"),
    Buffer.from(expected, "hex")
  );
}

// In your Express handler:
app.post("/webhooks/shiptriage", (req, res) => {
  const signature = req.headers["x-shiptriage-signature"];
  const isValid = verifyWebhook(JSON.stringify(req.body), signature, WEBHOOK_SECRET);

  if (!isValid) {
    return res.status(401).send("Invalid signature");
  }

  // Process the webhook event
  console.log("Event:", req.body.event);
  console.log("Tracking:", req.body.trackingNumber);
  res.status(200).send("OK");
});
python
import hmac
import hashlib

def verify_webhook(payload: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode(),
        payload,
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature)

# In your Flask handler:
@app.route("/webhooks/shiptriage", methods=["POST"])
def handle_webhook():
    signature = request.headers.get("X-ShipTriage-Signature")
    if not verify_webhook(request.data, signature, WEBHOOK_SECRET):
        return "Invalid signature", 401

    data = request.json
    print(f"Event: {data['event']}, Tracking: {data['trackingNumber']}")
    return "OK", 200