E-commerce API
Rate, book, track, and return shipments from your own platform. Base URL: https://sureasship.com/api/ecommerce/v1
Authentication
Every request carries your API key as a bearer token. Create keys under Settings → API Keys in your dashboard. Live keys start with sas_live_, test keys with sas_test_ — test keys behave identically but book against carrier sandboxes and are never charged.
Authorization: Bearer sas_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Endpoints
GET /profile— account, tier, andcan_create_shipmentscapability.POST /rates— live discounted rates across Canada Post, Purolator, UPS and FedEx for a shipment payload.POST /shipments— book a shipment (all four carriers); returns label URLs and tracking. Idempotent perreference.GET /shipments/{id}— status, tracking events, documents.POST /returns— create a return label / QR for an existing shipment.GET /tracking/{tracking_number}— tracking detail.POST /webhooks,GET /webhooks,DELETE /webhooks/{id}— manage event subscriptions (below).
The API root (GET /api/ecommerce/v1) returns a machine-readable index of all endpoints.
Webhooks
Subscribe an HTTPS endpoint and we push shipment lifecycle events as they happen. Available events:
shipment.booked— a label was purchased.shipment.tracking.updated— any tracking movement (includes the event detail).shipment.delivered— delivered (also fires tracking.updated).shipment.exception— a delivery exception (also fires tracking.updated).shipment.voided— the shipment was cancelled/voided.
Each delivery is a JSON POST with an envelope: {"id":"evt_…","event":"shipment.booked","created":"2026-08-20T14:00:00+00:00","data":{…}}. data carries shipment_id, client_ref, carrier, tracking_number, status, live_mode, and event specifics.
For the three tracking events, data also carries the scan itself: tracking_event (one of pickup, in_transit, out_for_delivery, delivered, delivery_attempted, exception), event_type (the carrier's own type), description, location, event_time, status_text, and — on an exception — exception_code and exception_description. Fields with no value are omitted rather than sent empty, so treat every one as optional.
Verifying signatures
Every delivery includes X-SAS-Signature: t=<unix>,v1=<hmac> where v1 is the HMAC-SHA256 of <t>.<raw body> keyed with the whsec_… secret returned when you created the subscription. Verify before trusting a payload, and reject stale timestamps (we recommend a 5-minute tolerance):
$parts = [];
parse_str(str_replace(',', '&', $_SERVER['HTTP_X_SAS_SIGNATURE']), $parts);
$expected = hash_hmac('sha256', $parts['t'] . '.' . file_get_contents('php://input'), $secret);
$valid = hash_equals($expected, $parts['v1']) && abs(time() - (int)$parts['t']) < 300;
Respond with any 2xx within 10 seconds. Failed deliveries retry with backoff (roughly 1 minute to 12 hours, 7 attempts); a subscription that keeps failing is automatically disabled — check is_active via GET /webhooks and re-create it after fixing your endpoint.
Errors & limits
Errors return a JSON body with error and a machine code (e.g. PAYMENT_FAILED, CARD_NOT_ENABLED_FOR_ECOMMERCE) and an appropriate HTTP status. Requests are rate-limited per key; the limit rides standard X-RateLimit-* response headers.
Questions or a use case we don't cover? Contact us — integrations are free on every plan.
