Shippea
Shippea Partner API

Shippea Partner API Documentation

Full REST API for SaaS partners and custom integrations: bearer-token authentication, wallet-based shipment payments, service lookup, tracking, label retrieval, cancellation, and webhook configuration.

Overview

Shippea Partner API

Full REST API for SaaS partners and custom integrations. Bearer-token authentication via client credentials, wallet-based shipment payments, and complete shipment lifecycle management — from service lookup to tracking and cancellation.

If you are building a Shopify app, use the Shopify Integration API v1 instead — it uses app-key authentication and a Shopify-native data model.

Authentication

Bearer token via client credentials

Content Type

application/json

Production

https://app.shippea.io/api/v2/partner

Sandbox

https://sandbox.shippea.io/api/v2/partner

Authentication

POST

/api/v2/partner/auth/token

Obtain access token

Use your client_id and client_secret to obtain a Bearer token. Include this token in all subsequent requests via the Authorization header. Tokens do not expire automatically — re-authenticate if you receive a 401 response.

Requires Authorization: Bearer {token} header.

Request

{
  "client_id": "your_client_id",
  "client_secret": "your_client_secret"
}

Response (200)

{
  "success": true,
  "token_type": "Bearer",
  "access_token": "1|...",
  "message": "Access token generated successfully."
}

cURL Example

curl --request POST '{BASE_URL}/auth/token' \
    --header 'Content-Type: application/json' \
    --data '{
        "client_id": "your_client_id",
        "client_secret": "your_client_secret"
    }'

Master Data

GET

/api/v2/partner/regions

List regions

Returns all active regions available for service coverage. Use the region id when querying services.

Requires header: Authorization: Bearer <token>

Request

GET {BASE_URL}/regions

Response (200)

{
  "success": true,
  "data": [
    {"id": 1, "name": "Panamá", "iso_code": "PA-8"}
  ]
}

cURL Example

curl --request GET '{BASE_URL}/regions' \
  --header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
  --header 'Accept: application/json'

Services & Prices

GET

/api/v2/partner/services

Quote services

Returns available services and prices for a given region. Filter by weight to see only services that accept the parcel.

Required query: region_id, origin_region_id • Optional query: weight, coordinates for ASAP

Request Parameters

FieldTypeRequiredDescription
region_idintegerREQUIREDRegion ID from the List Regions endpoint.
origin_region_idintegerREQUIREDSender's origin region ID from the List Regions endpoint. Regional couriers that do not cover this origin are excluded.
weightfloatOPTIONALWeight in pounds. When provided, only services whose weight range covers this value are returned.
sender_latfloatOPTIONALLatitude of sender's pickup address. Required for ASAP/dynamic courier pricing.
sender_longfloatOPTIONALLongitude of sender's pickup address. Required for ASAP/dynamic courier pricing.
receiver_latfloatOPTIONALLatitude of receiver's delivery address. Required for ASAP/dynamic courier pricing.
receiver_longfloatOPTIONALLongitude of receiver's delivery address. Required for ASAP/dynamic courier pricing.

Request

GET {BASE_URL}/services?region_id=1&origin_region_id=2&weight=2.5

Response (200)

{
  "success": true,
  "data": [
    {
      "id": 12,
      "rate_name": "Door-to-Door",
      "rate_type": "Door-to-Door",
      "min_weight": 0.0,
      "max_weight": 5.0,
      "price": 4.99,
      "return_charge": 0.0,
      "weight_unit": "lb",
      "courier": {
        "id": 3,
        "name": "Shippea Express",
        "logo_url": "https://..."
      },
      "agency": {
        "id": 2,
        "name": "Agency Name",
        "region_id": 1
      }
    }
  ]
}

cURL Example

curl --request GET '{BASE_URL}/services?region_id=1&origin_region_id=2&weight=2.5' \
  --header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
  --header 'Accept: application/json'

Customers

POST

/api/v2/partner/customers

Create customer

Creates a customer account for shipment ownership. If the email already exists, returns the existing customer information — no duplicate is created.

Requires header: Authorization: Bearer <token>

Request Body Fields

FieldTypeRequiredDescription
first_namestringREQUIREDCustomer first name.
last_namestringREQUIREDCustomer last name.
emailstringREQUIREDEmail address. Used as unique identifier — returns existing record if already registered.
phonestringREQUIREDInternational format phone number.
passwordstringOPTIONALPassword for direct portal login. If omitted, the customer cannot log in directly.

Example request body

{
  "first_name": "John",
  "last_name": "Doe",
  "email": "john@example.com",
  "phone": "+50760000000",
  "password": "optionalStrongPassword"
}

Response (201)

{
  "success": true,
  "message": "Customer account created successfully.",
  "data": {
    "customer_uuid": "...",
    "email": "john@example.com"
  }
}

cURL Example

curl --request POST '{BASE_URL}/customers' \
    --header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
    --header 'Content-Type: application/json' \
    --data '{
        "first_name": "John",
        "last_name": "Doe",
        "email": "john@example.com",
        "phone": "+50760000000",
        "password": "optionalStrongPassword"
    }'

Shipments

Shipment Lifecycle

Shippea supports listing, creation, payment, tracking, label retrieval, and cancellation. In the standard flow, shipment creation debits the wallet immediately and queues label generation asynchronously.

Service lookupCreate shipmentWallet debitAsync label generationTrack shipment
GET

/api/v2/partner/shipments

List shipments

Returns a paginated list of all shipments for the authenticated partner account. Results are sorted newest first.

Requires header: Authorization: Bearer <token>

Query Parameters

FieldTypeRequiredDescription
statusstringOPTIONALFilter by shipment status, for example: label_created, in_transit, delivered, cancelled.
order_numberstringOPTIONALFilter by your internal order reference number.
from_datedateOPTIONALEarliest creation date to include. Format: Y-m-d.
to_datedateOPTIONALLatest creation date to include. Format: Y-m-d.
per_pageintegerOPTIONALResults per page. Default: 20. Maximum: 100.

Request

GET {BASE_URL}/shipments?status=label_created&per_page=20

Response (200)

{
  "success": true,
  "data": [
    {
      "shipment_id": 991,
      "tracking_number": "4001234",
      "order_number": "ORDER-1001",
      "status": "label_created",
      "is_paid": true,
      "total_price": 4.99,
      "currency": "USD",
      "label_url": "https://...",
      "created_at": "2026-06-12 10:00:00"
    }
  ],
  "meta": {
    "current_page": 1,
    "per_page": 20,
    "total": 145,
    "last_page": 8
  }
}

cURL Example

curl --request GET '{BASE_URL}/shipments?per_page=20' \
  --header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
  --header 'Accept: application/json'
POST

/api/v2/partner/shipments

Create shipment

Creates a shipment, debits the wallet automatically, and queues async label generation. Total weight and final price are calculated server-side. Accepts either service_id or service_name.

Instant payment: The wallet is debited immediately on creation. The shipment starts in label_created status with is_paid: true. The label is generated asynchronously — poll GET /shipments/{tracking}/label until it is ready.
Idempotency: If you send the same order_number twice, the original shipment is returned and no duplicate is created.

Request Body Fields

FieldTypeRequiredDescription
service_idintegerOPTIONALID of the service from List Services. Provide either this or service_name.
service_namestringOPTIONALExact service name. Alternative to service_id.
order_numberstringOPTIONALYour internal order reference, stored against the shipment.
customerobjectREQUIREDCustomer info: name, email, phone.
sender_detailsobjectREQUIREDPickup/sender info. See Sender Object below.
receiver_detailsobjectREQUIREDDelivery/receiver info.
items_informationarrayREQUIREDArray of item objects. See Item Object below.

Sender Object

FieldTypeRequiredDescription
namestringREQUIREDSender full name or business name.
addressstringREQUIREDFull street address.
citystringREQUIREDCity name.
countrystringREQUIREDCountry name.
province_codestringREQUIREDISO province code. Used to resolve region.
zipstringREQUIREDPostal code.
phonestringREQUIREDContact phone number.
latitudefloatOPTIONALGPS coordinates for pickup mapping. Lat.
longitudefloatOPTIONALGPS coordinates for pickup mapping. Long.

Item Object

FieldTypeRequiredDescription
titlestringREQUIREDItem name / product title.
skustringOPTIONALStock-keeping unit identifier.
quantityintegerREQUIREDNumber of units.
weightfloatREQUIREDWeight per unit in pounds.
lengthfloatOPTIONALPackage dimensions in inches. Length.
widthfloatOPTIONALPackage dimensions in inches. Width.
heightfloatOPTIONALPackage dimensions in inches. Height.
package_typestringOPTIONALPackaging type.
declared_valuefloatOPTIONALDeclared value for insurance purposes.

Example request body

{
  "order_number": "ORDER-1001",
  "service_name": "Door-to-Door",
  "customer": {
    "name": "John Doe",
    "email": "john@example.com",
    "phone": "+50760000000"
  },
  "sender_details": {
    "name": "My Store",
    "email": "store@example.com",
    "address": "Sender Street 45",
    "city": "Panamá",
    "country": "Panama",
    "province_code": "PA-8",
    "zip": "0801",
    "phone": "+50761110000",
    "latitude": 8.9824,
    "longitude": -79.5199
  },
  "receiver_details": {
    "name": "John Doe",
    "email": "john@example.com",
    "address": "Street 123",
    "city": "Panamá",
    "country": "Panama",
    "province_code": "PA-8",
    "zip": "0801",
    "phone": "+50760000000",
    "latitude": 8.9943,
    "longitude": -79.5188
  },
  "items_information": [
    {
      "title": "Shoes",
      "sku": "SHOE-001",
      "quantity": 1,
      "weight": 1.2,
      "length": 12,
      "width": 8,
      "height": 5,
      "package_type": "Box",
      "declared_value": 35
    }
  ]
}

Response (201)

{
  "success": true,
  "message": "Shipment created and payment processed. Label generation has been queued.",
  "data": {
    "shipment_id": 991,
    "tracking_number": "4001234",
    "status": "label_created",
    "is_paid": true,
    "payment_method": "shippea_wallet",
    "total_price": 4.99,
    "currency": "USD",
    "wallet_balance": 195.01,
    "service": {
      "id": 12,
      "name": "Door-to-Door",
      "type": "Door-to-Door"
    },
    "calculation": {
      "total_items": 1,
      "total_weight": 1.2,
      "total_declared_value": 35,
      "base_price": 4.99,
      "return_fee": 0,
      "final_price": 4.99
    },
    "items": [
      {
        "id": 1,
        "title": "Shoes",
        "sku": "SHOE-001",
        "quantity": 1,
        "weight": 1.2
      }
    ]
  }
}

cURL Example

curl --request POST '{BASE_URL}/shipments' \
    --header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
    --header 'Content-Type: application/json' \
    --data '{
        "order_number": "ORDER-1001",
        "service_name": "Door-to-Door",
        "sender_details": {
            "name": "My Store",
            "address": "Sender Street 45",
            "city": "Panamá",
            "country": "Panama",
            "province_code": "PA-8",
            "latitude": 8.9824,
            "longitude": -79.5199
        },
        "receiver_details": {
            "address": "Street 123",
            "city": "Panamá",
            "country": "Panama",
            "province_code": "PA-8",
            "latitude": 8.9943,
            "longitude": -79.5188
        },
        "items_information": [{"title":"Shoes","quantity":1,"weight":1.2}]
    }'
POST

/api/v2/partner/shipments/{trackingNumber}/pay

Pay shipment

Debits the wallet and queues async label generation for a shipment currently in PENDING_PAYMENT status. Only applicable to shipments that were not auto-paid at creation.

In the standard flow, payment is auto-debited at creation. This endpoint is only needed for shipments that are explicitly in PENDING_PAYMENT status.

Request

POST {BASE_URL}/shipments/4001234/pay

Response (200)

{
  "success": true,
  "message": "Payment successful. Label generation has been queued.",
  "data": {
    "tracking_number": "4001234",
    "status": "label_created",
    "transaction_id": "TXN-...",
    "amount_charged": 4.99,
    "currency": "USD"
  }
}

cURL Example

curl --request POST '{BASE_URL}/shipments/4001234/pay' \
  --header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
  --header 'Accept: application/json'
GET

/api/v2/partner/shipments/{trackingNumber}

Get shipment / tracking

Fetch shipment status and full details using the tracking number returned on creation.

Requires header: Authorization: Bearer <token>

Request

GET {BASE_URL}/shipments/4001234

Response (200)

{
  "success": true,
  "data": {
    "tracking_number": "4001234",
    "order_number": "ORDER-1001",
    "status": "in_transit",
    "is_paid": true
  }
}

cURL Example

curl --request GET '{BASE_URL}/shipments/4001234' \
  --header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
  --header 'Accept: application/json'
GET

/api/v2/partner/shipments/{trackingNumber}/label

Get label

Returns the label URL for a shipment. Label generation is asynchronous — poll this endpoint after creation until a URL is returned.

If the shipment is still in PENDING_PAYMENT status, a 402 response is returned indicating payment is required first.

Request

GET {BASE_URL}/shipments/4001234/label

Response (200)

{
  "success": true,
  "data": {
    "tracking_number": "4001234",
    "label_url": "https://.../label.pdf",
    "combined_url": "https://.../combined.pdf"
  }
}

cURL Example

curl --request GET '{BASE_URL}/shipments/4001234/label' \
  --header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
  --header 'Accept: application/json'
DELETE

/api/v2/partner/shipments/{trackingNumber}

Cancel shipment

Cancels a shipment when its current status allows cancellation. Returns an error if the shipment is already dispatched or delivered.

Requires header: Authorization: Bearer <token>

Request

DELETE {BASE_URL}/shipments/4001234

Response (200)

{
  "success": true,
  "message": "Shipment cancelled successfully."
}

cURL Example

curl --request DELETE '{BASE_URL}/shipments/4001234' \
  --header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
  --header 'Accept: application/json'

Account & Wallet

GET

/api/v2/partner/account

Account

Returns the authenticated partner account profile, wallet summary, and API client details.

Requires header: Authorization: Bearer <token>

Request

GET {BASE_URL}/account

Response (200)

{
  "success": true,
  "data": {
    "account": {
      "name": "My Company",
      "email": "partner@example.com",
      "phone": "+50760000000",
      "status": "active"
    },
    "wallet": {
      "balance": 195.01,
      "currency": "USD",
      "is_active": true
    },
    "api_client": {
      "name": "My Integration",
      "client_id": "clnt_abc123",
      "webhook_url": "https://myapp.com/webhooks",
      "last_used_at": "2026-06-12 10:00:00"
    }
  }
}

cURL Example

curl --request GET '{BASE_URL}/account' \
  --header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
  --header 'Accept: application/json'

Wallet

GET

/api/v2/partner/wallet

Wallet balance

Returns the current wallet balance, currency, and the last 20 transactions.

Requires header: Authorization: Bearer <token>

Request

GET {BASE_URL}/wallet

Response (200)

{
  "success": true,
  "data": {
    "balance": 195.01,
    "currency": "USD",
    "is_active": true,
    "transactions": [
      {
        "type": "debit",
        "amount": 4.99,
        "balance": 195.01,
        "reason": "Shipment payment - 4001234",
        "reference": "SHIPMENT-4001234",
        "date": "2026-06-12 10:00:00"
      }
    ]
  }
}

cURL Example

curl --request GET '{BASE_URL}/wallet' \
  --header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
  --header 'Accept: application/json'

Webhook

Webhook Configuration

Register a webhook URL for shipment event notifications. Verify inbound payloads by computing HMAC-SHA256(webhook_secret, raw_body) and comparing it with the X-Shippea-Signature header.

GET

/api/v2/partner/webhook

Get webhook

Returns the webhook URL and secret currently registered for this API client.

Request

GET {BASE_URL}/webhook

Response (200)

{
  "success": true,
  "data": {
    "webhook_url": "https://myapp.com/webhooks",
    "webhook_secret": "shp_secret_abc..."
  }
}
PUT

/api/v2/partner/webhook

Update webhook

Registers or updates the webhook URL. A webhook_secret is auto-generated on first registration — store it securely to verify incoming payloads.

Request Body

FieldTypeRequiredDescription
webhook_urlstringREQUIREDFull HTTPS URL of your endpoint to receive webhook event notifications.

Example request body

{
  "webhook_url": "https://myapp.com/webhooks/shippea"
}

Response (200)

{
  "success": true,
  "message": "Webhook URL registered successfully.",
  "data": {
    "webhook_url": "https://myapp.com/webhooks/shippea",
    "webhook_secret": "shp_secret_abc..."
  }
}
Verify inbound payloads by computing HMAC-SHA256(webhook_secret, raw_body) and comparing to the X-Shippea-Signature header.
DELETE

/api/v2/partner/webhook

Delete webhook

Removes the registered webhook URL. No further events will be dispatched to the old URL.

Request

DELETE {BASE_URL}/webhook

Response (200)

{
  "success": true,
  "message": "Webhook URL removed successfully."
}

Authentication

POST

/api/v2/partner/auth/logout

Logout

Revokes the current access token. Subsequent requests with this token return 401.

Only the token used for this request is revoked. Other active tokens for the same client are unaffected.

Request

POST {BASE_URL}/auth/logout

Response (200)

{
  "success": true,
  "message": "Token revoked successfully."
}

cURL Example

curl --request POST '{BASE_URL}/auth/logout' \
  --header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
  --header 'Accept: application/json'

Reference

Regions Reference

Panama region IDs and ISO codes to use with the region_id and origin_region_id query parameters on the /services endpoint, and the province_code fields in shipment creation. Use the /regions endpoint to retrieve live IDs.

The region_id integers and province_code ISO values below are defaults for Panama. Always verify IDs against your environment using the GET /regions endpoint — IDs may differ between production and sandbox.
Region IDProvince NameISO Province CodeUsage
1Bocas del ToroPA-1region_id=1, province_code="PA-1"
2CocléPA-2region_id=2, province_code="PA-2"
3ColónPA-3region_id=3, province_code="PA-3"
4ChiriquíPA-4region_id=4, province_code="PA-4"
5DariénPA-5region_id=5, province_code="PA-5"
6HerreraPA-6region_id=6, province_code="PA-6"
7Los SantosPA-7region_id=7, province_code="PA-7"
8PanamáPA-8region_id=8, province_code="PA-8"
9VeraguasPA-9region_id=9, province_code="PA-9"
10Kuna Yala (Guna Yala)PA-KYregion_id=10, province_code="PA-KY"
11Panamá OestePA-10region_id=11, province_code="PA-10"

Reference

Error Codes

All errors return success: false and a human-readable message. The HTTP status code indicates the error category.

HTTPError CodeDescription
422VALIDATION_ERRORMissing or invalid fields.
401UNAUTHORIZEDInvalid or expired Bearer token.
403AUTH_INACTIVE_ACCOUNTAccount or wallet is inactive.
422SERVICE_NOT_FOUNDThe specified service name or ID does not match any active service.
400INSUFFICIENT_WALLET_BALANCEWallet balance is below the service cost.
404SHIPMENT_NOT_FOUNDNo shipment matches the tracking number.
400CANNOT_CANCELShipment is past the cancellable state — already dispatched or delivered.
404LABEL_NOT_READYLabel has not been generated yet. Retry after a few seconds.
402PAYMENT_REQUIREDShipment is awaiting payment before the label can be issued.

Resources

Postman Collection

Download the Postman collection to get all v2 endpoints pre-configured with automated token-save test scripts.

📮Partner API – Postman CollectionAfter importing, set the base_url variable and fill in client_id and client_secret. The Auth token request auto-saves the token to a collection variable.