REST API · JSON · Bearer Auth

Shiplee
API Reference

Full logistics integration — authenticate, create orders, fetch rates, book and track shipments.https://apiv1.shiplee.app

Overview

The Shiplee API is a RESTful JSON interface for programmatic logistics management. All requests and responses use application/json unless noted.

Capabilities

All protected endpoints require Authorization: Bearer <token>. Tokens expire after 1 hour — re-authenticate via /login to refresh.

Authentication

Shiplee uses signed JWT tokens bound to your seller account. Every token encodes your user ID, email, and Shiplee ID.

Setup steps
  1. Register at app.shiplee.ai and generate an API key in API Settings.
  2. Whitelist your server IP address and request domain in API Settings.
  3. POST credentials to /login — receive a JWT valid for 1 hour.
  4. Pass Authorization: Bearer <token> on every subsequent request.

Both IP and domain must be whitelisted. Requests from unknown origins return 403 Forbidden.

Login

POST/login

Authenticates your credentials and returns a JWT token.

Request body
json
{
    "username": "you@example.com",
    "apikey":   "your-api-key"
}
Code examples
bash
curl -X POST https://apiv1.shiplee.app/login \
  -H "Content-Type: application/json" \
  -H "Origin: http://localhost" \
  -d '{"username":"you@example.com","apikey":"your-api-key"}'
powershell
$body    = @{ username = "you@example.com"; apikey = "your-api-key" } | ConvertTo-Json
$headers = @{ "Content-Type" = "application/json"; "Origin" = "http://localhost" }
Invoke-RestMethod -Uri "https://apiv1.shiplee.app/login" -Method Post -Body $body -Headers $headers
php
<?php
$ch = curl_init('https://apiv1.shiplee.app/login');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => ['Content-Type: application/json','Origin: http://localhost'],
    CURLOPT_POSTFIELDS => json_encode(['username'=>'you@example.com','apikey'=>'your-api-key']),
]);
echo curl_exec($ch); curl_close($ch);
python
import requests
r = requests.post('https://apiv1.shiplee.app/login',
    json={'username': 'you@example.com', 'apikey': 'your-api-key'},
    headers={'Origin': 'http://localhost'})
token = r.json()['token']
javascript
const { token } = await fetch('https://apiv1.shiplee.app/login', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ username: 'you@example.com', apikey: 'your-api-key' })
}).then(r => r.json());
Response 200
json
{
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "user": { "id": 62, "email": "you@example.com", "shiplee_id": "d10701280b9798033c6917e9415b03c3" }
}

Add Order

POST/order

Creates a new forward order. Returns a numeric order_id used across all shipping endpoints.

Request body
json
{
    "pincode": "560098", "city": "Bangalore", "state": "Karnataka",
    "name": "John Doe", "email": "customer@example.com", "mobileNumber": "9000000001",
    "addressLine1": "123 Sample Street, Apt 4B", "sameAddressCheckbox": 1,
    "orderID": "ORD-123456", "paymentType": "prepaid",
    "products": [{ "productName": "Sample Product", "quantity": 2, "productPrice": 500.00, "sku": "SKU123" }],
    "parcels": [{ "length": 10, "breadth": 10, "height": 10, "physicalWeight": 1.5 }]
}

Set sameAddressCheckbox to 0 and add billingPincode, billingName, etc. for separate billing addresses.

Response 201
json
{ "success": true, "message": "Order added successfully", "order_id": 484900 }

Reverse Order

POST/reverse_order

Creates a reverse pickup order for a customer return or exchange.

Critical: orderId must be the numeric integer from /order (e.g. 484900). The warehouseId must belong to your account.

Request body
json
{
    "orderId": 484900, "awbNumber": "XB1234567890", "reason": "Customer return — wrong size",
    "warehouseId": 2147483833, "paymentType": "prepaid", "insurance": false,
    "customer": { "name": "John Doe", "mobile": "9000000001", "address1": "123 Sample Street, Apt 4B",
        "pincode": "560098", "city": "Bangalore", "state": "Karnataka" },
    "products": [{ "productName": "Sample Product", "quantity": 1, "productPrice": 500.00, "sku": "SKU123" }],
    "parcel": { "length": 10, "breadth": 10, "height": 10, "physicalWeight": 1.5 }
}
Response 201
json
{ "success": true, "message": "Reverse order created successfully", "reverse_order_id": "RO-7A685" }

Get Rates

POST/rates

Returns available courier options with freight and COD charges for an existing order.

Request body
json
{ "orderId": 484900, "warehouseId": 2147483833, "shipmentType": "forward" }
Response 200
json
{
    "success": true, "message": "Rates fetched successfully",
    "data": { "carrier_info": [
        { "carrier_id": "delhivery_e_prepaid", "carrier_name": "Delhivery Express", "cost": 138, "freight_charges": 138, "cod_charges": 0, "tat": "2-3 days" },
        { "carrier_id": "delhivery_s_prepaid", "carrier_name": "Delhivery Surface", "cost": 104, "freight_charges": 104, "cod_charges": 0, "tat": "4-6 days" }
    ]}
}

Create Shipment

POST/create_shipment

Books a forward shipment for an existing order. Deducts charges from your wallet and returns the AWB number.

Minimum wallet balance of ₹500 required. Duplicate bookings for the same orderId are rejected automatically.

Request body
json
{
    "orderId": 484900, "warehouseId": 2147483833, "action": "book_shipment",
    "carrierId": "delhivery_e_prepaid", "carrierName": "Delhivery Express", "shipmentType": "forward"
}
Response 201
json
{ "success": true, "message": "Shipment booked", "awb_number": "XB1234567890", "shipment_id": "SHPL-54321" }

Reverse Shipment

POST/reverse_create_shipment

Books a Delhivery pickup for an existing reverse order. Request body is application/x-www-form-urlencoded.

Request body
form-urlencoded
order_id=1042&warehouse_id=2147483833&carrierId=delhivery_e_prepaid&carrierName=Delhivery+Express
Response 200
json
{ "success": true, "message": "Reverse shipment booked", "awb_number": "1234567890123", "shipment_id": "UPLOAD_WBN_ABC" }

Track Shipment

GET/track?awb={awb_number}

Returns the full tracking timeline for a shipment by AWB number. Sellers can only query AWBs belonging to their own account.

Response 200
json
{
    "data": {
        "orderNumber": "122", "orderStatus": "Manifested", "orderStatusCode": "manifested",
        "trackingNumber": "80905112190", "carrierName": "Blue Dart- Apex",
        "paymentType": "cod", "orderValue": 1450, "weightGrams": 500,
        "trackingDetails": [
            { "scanStatus": "SHIPMENT DELIVERED", "scanLocation": "KATARGAM OFFICE", "scanDateTime": "2025-09-27 16:31:00", "message": "delivered" }
        ]
    }, "errorMessage": null
}

Generate Label

POST/label

Generates a shipping label PDF for one or more AWBs. Returns a binary PDF stream (application/pdf) ready for download or direct printing. Labels respect your account's label settings — size (4×6 or A4), style, logo, hide flags, and premium branding.

Security: Every AWB is verified against your seller account. If any AWB in the request belongs to another seller the entire request is rejected with 403 — no partial output is returned.

The response Content-Type is application/pdf on success and application/json on error. Check the response header before parsing.

Request body
json — single AWB
{
    "awb": "80905112190"
}
json — bulk (up to 50)
{
    "awbs": ["80905112190", "XB1234567890", "1234567890123"]
}
Request fields
FieldTypeRequiredDescription
awbstringoptional*Single AWB number. Alphanumeric + _-, max 50 chars.
awbsarrayoptional*Array of AWB strings. Max 50 items per request.

* Provide either awb or awbs — at least one is required.

Code examples
bash
# Single AWB — save PDF to file
curl -X POST https://apiv1.shiplee.app/label \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -d '{"awb":"80905112190"}' \
  --output label.pdf

# Bulk — up to 50 AWBs in one call
curl -X POST https://apiv1.shiplee.app/label \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -d '{"awbs":["80905112190","XB1234567890"]}' \
  --output labels.pdf
php
<?php
// Single AWB
$ch = curl_init('https://apiv1.shiplee.app/label');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Content-Type: application/json',
        'Authorization: Bearer YOUR_JWT_TOKEN',
    ],
    CURLOPT_POSTFIELDS => json_encode(['awb' => '80905112190']),
]);
$response    = curl_exec($ch);
$contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
curl_close($ch);

if (str_contains($contentType, 'application/pdf')) {
    file_put_contents('label.pdf', $response);
    echo "Label saved.";
} else {
    $err = json_decode($response, true);
    echo "Error: " . $err['message'];
}

// Bulk
$ch2 = curl_init('https://apiv1.shiplee.app/label');
curl_setopt_array($ch2, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json', 'Authorization: Bearer YOUR_JWT_TOKEN'],
    CURLOPT_POSTFIELDS     => json_encode(['awbs' => ['80905112190', 'XB1234567890']]),
]);
file_put_contents('labels_bulk.pdf', curl_exec($ch2));
curl_close($ch2);
python
import requests

headers = {'Authorization': 'Bearer YOUR_JWT_TOKEN'}

# Single AWB
r = requests.post('https://apiv1.shiplee.app/label',
    json={'awb': '80905112190'},
    headers=headers)

if r.headers.get('Content-Type', '').startswith('application/pdf'):
    with open('label.pdf', 'wb') as f:
        f.write(r.content)
    print("Label saved.")
else:
    print("Error:", r.json()['message'])

# Bulk
r2 = requests.post('https://apiv1.shiplee.app/label',
    json={'awbs': ['80905112190', 'XB1234567890']},
    headers=headers)
with open('labels_bulk.pdf', 'wb') as f:
    f.write(r2.content)
javascript
// Single AWB — trigger browser download
async function downloadLabel(awb) {
    const res = await fetch('https://apiv1.shiplee.app/label', {
        method: 'POST',
        headers: {
            'Content-Type':  'application/json',
            'Authorization': 'Bearer YOUR_JWT_TOKEN',
        },
        body: JSON.stringify({ awb }),
    });

    if (res.headers.get('Content-Type')?.includes('application/pdf')) {
        const blob = await res.blob();
        const url  = URL.createObjectURL(blob);
        const a    = document.createElement('a');
        a.href = url; a.download = `label_${awb}.pdf`;
        a.click(); URL.revokeObjectURL(url);
    } else {
        const err = await res.json();
        console.error('Label error:', err.message);
    }
}

// Bulk
async function downloadBulkLabels(awbs) {
    const res = await fetch('https://apiv1.shiplee.app/label', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_JWT_TOKEN' },
        body: JSON.stringify({ awbs }),
    });
    const blob = await res.blob();
    const a = Object.assign(document.createElement('a'),
        { href: URL.createObjectURL(blob), download: 'labels_bulk.pdf' });
    a.click();
}
Success response 200 application/pdf

A binary PDF file is streamed with the following headers:

response headers
Content-Type: application/pdf
Content-Disposition: attachment; filename="shiplee_labels_20250924_153012.pdf"

Each AWB occupies one page. The label format (4×6 or A4), style, logo, and branding are pulled from your account's label settings configured at app.shiplee.ai.

Label content per page
ElementNotes
Deliver To addressConsignee name, full address, pincode, mobile
Return To addressWarehouse name, address, mobile
AWB barcodeCode-128 barcode + human-readable AWB number
Order barcodeCode-128 barcode for internal order ID
Payment bandCOD (Rs. X) or PREPAID
Product listUp to 3 items shown; overflow shown as count
Courier nameAs recorded at booking time
Branding footerPowered by Shiplee or your custom brand name
Hide flags (configured in Label Settings)

Individual label fields can be suppressed via your label settings dashboard. The API honours all of these automatically:

SettingEffect when enabled
hide_cust_nameRemoves consignee name from label
hide_cust_mobileRemoves consignee phone number
hide_wh_nameRemoves warehouse/return name
hide_wh_addressRemoves warehouse/return address
hide_wh_mobileRemoves warehouse phone number
hide_productRemoves entire product list section
hide_skuRemoves SKU from product lines
hide_quantityRemoves quantity from product lines
hide_order_amountHides ₹ amount (COD/PREPAID label still shown)
Error responses 4xx / 5xx — application/json
json
{ "success": false, "message": "Missing Authorization header" }
{ "success": false, "message": "Invalid JWT token" }
{ "success": false, "message": "User account not active" }
{ "success": false, "message": "The IP '1.2.3.4' is not whitelisted" }
{ "success": false, "message": "Provide \"awb\" (string) or \"awbs\" (array)" }
{ "success": false, "message": "No valid AWBs provided" }
{ "success": false, "message": "Maximum 50 AWBs per request" }
{ "success": false, "message": "Forbidden: one or more AWBs do not belong to your account" }
{ "success": false, "message": "No valid orders found for the provided AWB(s)" }
{ "success": false, "message": "Internal server error" }

Warehouse Management

Warehouses are your pickup and return destinations. Register new locations or list existing ones.

POST/add_warehouse
json
{
    "nickname": "Main Warehouse", "mobileNumber": "9000000001",
    "address1": "123 Logistics Road", "pincode": "110076",
    "city": "New Delhi", "state": "Delhi", "addressType": "primary"
}
GET/get_warehouses

Returns all active warehouses for the authenticated seller.

json — 200
{
    "success": true, "message": "Warehouses retrieved successfully",
    "data": [{ "id": 2147483833, "nickname": "Main Warehouse", "address1": "123 Logistics Road", "pincode": "110076", "city": "New Delhi", "state": "Delhi", "addressType": "primary" }]
}

Support

Reach the Shiplee technical team through any of these channels:

ChannelContact
Emailsupport@shiplee.app
WhatsApp+91 86453 22815
Dashboardapp.shiplee.ai