Currently viewing services in North America. Change region?

API Reference

The public developer API is a shipment-focused, server-to-server surface. It deliberately excludes ShipPack's internal mobile, driver, wallet, admin, payment-provider, assignment, and pricing fields.

The OpenAPI 3.1 contract covers application-key credentials, shipment catalogs, shipments, sandbox simulation, and the signed outbound shipment webhook schema.

Base URL

Use the same base URL for sandbox and production. The application key prefix selects the environment.

https://dev.api.theshippack.com/api/v1/developer

How paths are shown

Endpoint lists below are gateway-relative and retain the /developer prefix to match the OpenAPI and Postman contracts. When a client is configured with the full developer base URL above, do not append /developer a second time.

EnvironmentKey prefixPurpose
Sandboxsk_test_Simulated shipments and sandbox lifecycle webhooks
Productionsk_live_Approved operational shipments and production webhooks

Authentication

Dashboard authentication

Account, application, key, and webhook management routes require a normal Sanctum user token and the developer app header.

http
Authorization: Bearer USER_ACCESS_TOKEN
X-App-Type: developer

Server-to-server authentication

Catalog and shipment routes require an application secret key.

http
Authorization: Bearer sk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Credential properties

Secrets are shown once and stored as SHA-256 hashes with their prefix, environment, expiry, and revocation state. The limit is 120 requests per minute per credential.

OpenAPI Contract

The machine-readable source of truth is maintained at:

openapi/shippack-developer-api.json

The server-to-server contract contains these operations:

http
GET  /developer/credentials
GET  /developer/package-sizes
GET  /developer/delivery-types
GET  /developer/delivery-options
GET  /developer/shipments
POST /developer/shipments
GET  /developer/shipments/{shipmentId}
POST /developer/shipments/{shipmentId}/cancel
POST /developer/shipments/{shipmentId}/simulate

Contract boundary

Registration, dashboard, application and key management, webhook configuration, and production review are intentionally documented outside the secret-key SDK contract.

Dashboard Endpoints

All routes in this section require the user token and X-App-Type: developer.

Developer account

http
GET  /developer/account
POST /developer/account

The developer_accounts row is normally provisioned during verification. POST remains idempotent for compatibility and recovery and does not create a second account.

Applications and production access

http
GET    /developer/applications
POST   /developer/applications
GET    /developer/applications/{applicationId}
PATCH  /developer/applications/{applicationId}
DELETE /developer/applications/{applicationId}
POST   /developer/applications/{applicationId}/production-access

Production-access request

JSON
{
  "reason": "We will create deliveries for paid ecommerce orders from our backend checkout workflow."
}

API keys

http
GET    /developer/applications/{applicationId}/api-keys
POST   /developer/applications/{applicationId}/api-keys
DELETE /developer/applications/{applicationId}/api-keys/{apiKeyId}

Create-key request

JSON
{
  "name": "Backend sandbox key",
  "environment": "sandbox",
  "expiresAt": null
}

Production Access Review

Developers submit the production-access request from their application. The following review endpoints are operator-only and cannot be called with developer credentials.

http
GET   /admin/developer-applications?productionStatus=pending&perPage=20
PATCH /admin/developer-applications/{applicationId}/production-access

Approval body

JSON
{
  "decision": "approved",
  "note": "Business and integration use case verified."
}
  • decision is approved or rejected.
  • Production keys require an approved application.
  • Rejecting production access revokes active live keys.

Credential and Catalog Endpoints

http
GET /developer/credentials
GET /developer/package-sizes
GET /developer/delivery-types
GET /developer/delivery-options?origins=LAT,LNG&destinations=LAT,LNG
  • credentials returns the authenticated application and environment context.
  • package-sizes provides valid packageSizeId values.
  • delivery-types provides valid deliveryTypeId values.
  • delivery-options evaluates options for the supplied origin and destination coordinates.

Shipment Endpoints

http
GET  /developer/shipments?perPage=20
POST /developer/shipments
GET  /developer/shipments/{shipmentId}
POST /developer/shipments/{shipmentId}/cancel
POST /developer/shipments/{shipmentId}/simulate

Application isolation

Every shipment is mapped to its creating application. One application cannot list or retrieve another application's shipments. Production callers also cannot choose an internal ShipPack user ID, and caller-supplied prices are discarded.

Create a Shipment

http
POST /developer/shipments

Request body

JSON
{
  "pickup": "Lekki Phase 1, Lagos, Nigeria",
  "pickupLat": 6.4488,
  "pickupLng": 3.472,
  "pickupCountry": "NG",
  "dropoffCountry": "NG",
  "destinationDetails": {
    "dropoff": "Wuse 2, Abuja, Nigeria",
    "dropoffLat": 9.0765,
    "dropoffLng": 7.4983,
    "recipient": {
      "name": "Adebayo Test",
      "phoneNumber": "+2348012345678"
    }
  },
  "shipmentMode": "LAND",
  "shipperMode": "AUTO",
  "packageSizeId": "PACKAGE_SIZE_ID",
  "deliveryTypeId": "DELIVERY_TYPE_ID",
  "packageDescription": "Documents and clothes",
  "attachments": [],
  "submit": false
}
  • Set submit to false to save without payment submission.
  • The production MVP accepts paymentMethod: wallet when submit is true.
  • Sandbox references begin with SPTEST and tracking IDs begin with TRKTEST.

Sandbox Simulation

The simulate operation is sandbox-only and must follow the public lifecycle order.

http
POST /developer/shipments/{shipmentId}/simulate

Request body

JSON
{
  "status": "ASSIGNED"
}

Valid sequence

PENDING → ASSIGNED → PICKED_UP → IN_TRANSIT → OUT_FOR_DELIVERY → DELIVERED

Any non-terminal status may transition to FAILED.

Webhook Management

Webhook configuration belongs to an application and uses dashboard authentication.

http
GET    /developer/applications/{applicationId}/webhooks
POST   /developer/applications/{applicationId}/webhooks
PATCH  /developer/applications/{applicationId}/webhooks/{webhookId}
DELETE /developer/applications/{applicationId}/webhooks/{webhookId}
POST   /developer/applications/{applicationId}/webhooks/{webhookId}/rotate-secret
POST   /developer/applications/{applicationId}/webhooks/{webhookId}/test
GET    /developer/applications/{applicationId}/webhooks/{webhookId}/deliveries
POST   /developer/applications/{applicationId}/webhooks/{webhookId}/deliveries/{deliveryId}/retry

Create-webhook request

JSON
{
  "environment": "sandbox",
  "url": "https://example.com/webhooks/shippack",
  "description": "Shipment lifecycle handler",
  "events": [
    "shipment.created",
    "shipment.assigned",
    "shipment.picked_up",
    "shipment.in_transit",
    "shipment.out_for_delivery",
    "shipment.delivered",
    "shipment.cancelled",
    "shipment.failed"
  ]
}

HTTPS and DNS validation

Webhook URLs cannot target localhost, private, reserved, or locally resolving addresses. DNS is checked again immediately before every delivery.

Webhook Payload and Signature

Example payload

JSON
{
  "id": "45be8cee-4382-4bad-9336-bca329ed0c77",
  "type": "shipment.delivered",
  "createdAt": "2026-08-17T11:30:00Z",
  "data": {
    "id": "developer-shipment-id",
    "reference": "SP123456789",
    "trackingId": "TRACK123",
    "status": "DELIVERED"
  }
}

Delivery headers

http
X-ShipPack-Event: shipment.delivered
X-ShipPack-Delivery: DELIVERY_UUID
X-ShipPack-Timestamp: 1786966200
X-ShipPack-Signature: sha256=HEX_HMAC

The signed value is TIMESTAMP.RAW_REQUEST_BODY.

Node.js verification

JavaScript
import crypto from "node:crypto";

const signed = timestamp + "." + rawBody;
const expected = "sha256=" + crypto
  .createHmac("sha256", webhookSecret)
  .update(signed)
  .digest("hex");

const valid = crypto.timingSafeEqual(
  Buffer.from(expected),
  Buffer.from(receivedSignature)
);
  • Reject timestamps outside a five-minute tolerance.
  • Return an HTTP 2xx response quickly, then process asynchronously.
  • Deduplicate with payload id or X-ShipPack-Delivery.
  • High-frequency location events are not forwarded in the MVP.

Webhook Delivery Retries

A delivery is marked failed after five unsuccessful attempts.

AttemptDelay
Initial attemptImmediately
Retry 130 seconds
Retry 22 minutes
Retry 310 minutes
Retry 430 minutes

Delivery logs expose status, the HTTP response, a truncated response body, and the last error. A non-delivered attempt can be retried manually.

Production Webhook Flow

  1. shipment-service publishes a shipment lifecycle event.
  2. notification-service performs normal notification work and forwards the protected shipment envelope.
  3. user-service resolves the operational shipment mapping to its developer application.
  4. The internal status is normalized into the public developer event name.
  5. One idempotent delivery record is created per matching endpoint and event ID.
  6. The user-service queue signs and delivers each callback.

Location-event boundary

High-frequency location events are deliberately not forwarded to developer webhooks in the MVP.

Pagination and Rate Limits

  • Use perPage on shipment collection requests; the documented example is perPage=20.
  • Each application credential is limited to 120 requests per minute.
  • The TypeScript SDK performs bounded retries only for eligible GET requests.