Official Communication: Lekya Logistics will never ask for your password or OTP. Stay safe from fraud!

For Developers & Partners

Carrier API Documentation

Integrate our lightning-fast logistics directly into your app. Powerful, secure, and developer-friendly.

Introduction

The Parcel Uncle Merchant API provides programmatic access to manage your logistics operations. Build directly into your storefront, ERP, or custom dashboard.

Base URL: https://parceluncle.com/carrier/v1/merchant/

All requests must be made over HTTPS. Responses are served in JSON format. We provide both Sandbox (TEST) and Production (LIVE) environments accessible through different API keys.

Authentication

Authenticate your API requests by including your API key in the X-API-Key header. You can manage your API keys in the Developer section of your Seller Dashboard.

Sandbox Mode

Keys prefixed with pu_test_. Actions are simulated and no real wallet deductions occur. COD is forced.

Live Mode

Keys prefixed with pu_live_. Actions are real and shipments will be dispatched. Wallet/Credit deductions apply.

Authentication Example
curl -X GET https://parceluncle.com/carrier/v1/merchant/shipments/ \
  -H "X-API-Key: pu_live_1234567890abcdef1234567890abcdef1234567890abcdef"

Rate Limits

To ensure service stability, API requests are rate-limited per API key on a 1-minute sliding window. If you exceed the limit, you will receive a 429 Too Many Requests response.

Key Type General Endpoints Tracking Endpoint
Live (Production) 500 req / min 120 req / min
Test (Sandbox) 60 req / min 120 req / min
GET

Serviceability Check

/carrier/v1/merchant/serviceability/?pincode={pincode}

Check if Parcel Uncle provides delivery services to a specific pincode. Unauthenticated requests are allowed for this endpoint if you provide a valid API key.

Query Parameters

  • pincode Required — The 6-digit postal code to check.
Request
curl -X GET "https://parceluncle.com/carrier/v1/merchant/serviceability/?pincode=110014" \
  -H "X-API-Key: pu_live_..."
Response (200 OK)
{
  "success": true,
  "data": {
    "pincode": "110014",
    "is_serviceable": true,
    "city": "South Delhi"
  }
}
POST

Rate Quote

/carrier/v1/merchant/rates/

Calculate estimated shipping costs before creating a shipment. Prices vary based on service type, weight, and distance.

Payload Details

  • service_type: "SAME_DAY" | "NEXT_DAY" | "EXPRESS_4H"
  • weight_kg: float
  • pickup_pincode: string
  • delivery_pincode: string
  • is_cod: boolean (optional)
  • distance_km: float (optional)
  • length_cm, width_cm, height_cm: float (optional)
Response (200 OK)
{
  "success": true,
  "data": {
    "service_type": "EXPRESS_4H",
    "currency": "INR",
    "total": "145.50",
    "breakdown": {
      "distance_charge": 100,
      "weight_charge": 25,
      "gst_amount": 20.50
    },
    "sandbox": false
  }
}
POST

Create Shipment

/carrier/v1/merchant/shipments/

Create a new shipment request. This will instantly deduct funds from your Wallet or Credit Line if in LIVE mode.

🆕 New Fields: You can now use payment_mode, order_number, and total_amount for a cleaner integration. These fields are optional and fully backward-compatible — existing integrations continue to work without changes.

New Optional Fields

Field Type Required Description
order_number string Optional Your own order reference number (e.g., Shopify order ID)
payment_mode "COD" | "Prepaid" Optional Controls whether the recipient pays on delivery (COD) or the order is already paid (Prepaid)
total_amount number Required if payment_mode Complete order value (must be > 0)
cod_amount number Required if COD Amount to collect from recipient. Must be > 0 for COD, must be 0 for Prepaid.
Payment Mode Rules:
  • If payment_mode is "COD": cod_amount is mandatory and must be > 0. The rider will collect this amount from the recipient.
  • If payment_mode is "Prepaid": cod_amount must be 0. The order is already paid by the customer.
  • total_amount should always contain the complete order value.
  • payment_method (WALLET/CREDIT/COD) controls how you pay Parcel Uncle for shipping.

Example: COD Order

COD Payload
{
  "service_type": "SAME_DAY",
  "payment_method": "COD",
  "payment_mode": "COD",
  "order_number": "ORD-2024-001",
  "total_amount": 800,
  "cod_amount": 800,
  "pickup_address": "114/7, Second Floor, Hari Nagar Ashram",
  "pickup_city": "New Delhi",
  "pickup_state": "Delhi",
  "pickup_pincode": "110014",
  "delivery_address": "A-42, Sector 4",
  "delivery_city": "Noida",
  "delivery_state": "UP",
  "delivery_pincode": "201301",
  "sender_name": "Lekya Store",
  "sender_phone": "9876543210",
  "recipient_name": "John Doe",
  "recipient_phone": "9998887776",
  "weight_kg": 1.5,
  "parcel_type": "PACKAGE"
}

Example: Prepaid Order

Prepaid Payload
{
  "service_type": "SAME_DAY",
  "payment_method": "WALLET",
  "payment_mode": "Prepaid",
  "order_number": "ORD-2024-002",
  "total_amount": 800,
  "cod_amount": 0,
  "pickup_address": "114/7, Second Floor, Hari Nagar Ashram",
  "pickup_city": "New Delhi",
  "pickup_state": "Delhi",
  "pickup_pincode": "110014",
  "delivery_address": "A-42, Sector 4",
  "delivery_city": "Noida",
  "delivery_state": "UP",
  "delivery_pincode": "201301",
  "sender_name": "Lekya Store",
  "sender_phone": "9876543210",
  "recipient_name": "John Doe",
  "recipient_phone": "9998887776",
  "weight_kg": 1.5,
  "parcel_type": "PACKAGE"
}
Payment Methods: Use WALLET to debit from prepaid balance, CREDIT for post-paid credit line, or COD for Cash on Delivery. If COD is selected, you must also provide cod_amount.

Success Response (201 Created)

Response
{
  "success": true,
  "sandbox": false,
  "message": "Shipment created successfully",
  "data": {
    "tracking_number": "AWB987654321",
    "status": "PAID",
    "service_type": "SAME_DAY",
    "payment_method": "WALLET",
    "is_cod": false,
    "cod_amount": "0.00",
    "shipment_amount": "145.50",
    "order_number": "ORD-2024-002",
    "payment_mode": "Prepaid",
    "total_amount": "800.00",
    "pickup": {
      "address": "114/7, Second Floor, Hari Nagar Ashram",
      "city": "New Delhi",
      "state": "Delhi",
      "pincode": "110014",
      "landmark": ""
    },
    "delivery": {
      "address": "A-42, Sector 4",
      "city": "Noida",
      "state": "UP",
      "pincode": "201301",
      "landmark": ""
    },
    "sender": {
      "name": "Lekya Store",
      "phone": "9876543210",
      "email": ""
    },
    "recipient": {
      "name": "John Doe",
      "phone": "9998887776",
      "email": ""
    },
    "parcel": {
      "type": "PACKAGE",
      "weight_kg": "1.50",
      "length_cm": null,
      "width_cm": null,
      "height_cm": null
    },
    "cost_breakdown": {
      "distance_charge": 100,
      "weight_charge": 25,
      "gst_amount": 20.50
    },
    "assigned_rider": null,
    "special_instructions": "",
    "created_at": "2024-05-10T10:00:00Z",
    "updated_at": "2024-05-10T10:00:00Z",
    "delivered_at": null
  }
}
New Response Fields: The response now includes order_number, payment_mode ("COD" or "Prepaid"), and total_amount. These are returned for all shipments, even those created without these fields (they will default to empty/null/derived values).
GET

List Shipments

/carrier/v1/merchant/shipments/

Retrieve a paginated list of shipments associated with your account.

Query Parameters

  • page: Page number (default: 1)
  • limit: Items per page (default: 20, max: 100)
  • status: Filter by status (e.g. DELIVERED)
  • date_from / date_to: Filter by creation date (YYYY-MM-DD)
Response Format
{
  "success": true,
  "pagination": {
    "total": 142,
    "page": 1,
    "page_size": 20,
    "total_pages": 8,
    "has_next": true,
    "has_previous": false
  },
  "data": [
    {
      "tracking_number": "AWB123456789",
      "status": "DELIVERED",
      "service_type": "SAME_DAY",
      "payment_method": "WALLET",
      "is_cod": false,
      "cod_amount": "0.00",
      "shipment_amount": "145.50",
      "order_number": "ORD-2024-001",
      "payment_mode": "Prepaid",
      "total_amount": "800.00",
      "created_at": "2024-05-10T10:00:00Z"
    }
  ]
}
GET

Get Shipment

/carrier/v1/merchant/shipments/{tracking_number}/

Retrieve the full details of a specific shipment using its tracking number.

Path Parameters

  • tracking_number Required — The unique AWB/tracking number of the shipment.
Response Format
{
  "success": true,
  "data": {
    "tracking_number": "AWB123456789",
    "status": "DELIVERED",
    "service_type": "SAME_DAY",
    "payment_method": "COD",
    "is_cod": true,
    "cod_amount": "800.00",
    "shipment_amount": "145.50",
    "order_number": "ORD-2024-001",
    "payment_mode": "COD",
    "total_amount": "800.00",
    "pickup": {
      "address": "114/7, Second Floor, Hari Nagar Ashram",
      "city": "New Delhi",
      "state": "Delhi",
      "pincode": "110014",
      "landmark": ""
    },
    "delivery": {
      "address": "A-42, Sector 4",
      "city": "Noida",
      "state": "UP",
      "pincode": "201301",
      "landmark": ""
    },
    "sender": {
      "name": "Lekya Store",
      "phone": "9876543210",
      "email": ""
    },
    "recipient": {
      "name": "John Doe",
      "phone": "9998887776",
      "email": ""
    },
    "parcel": {
      "type": "PACKAGE",
      "weight_kg": "1.50",
      "length_cm": null,
      "width_cm": null,
      "height_cm": null
    },
    "cost_breakdown": {
      "distance_charge": 100,
      "weight_charge": 25,
      "gst_amount": 20.50
    },
    "assigned_rider": "Ramesh Kumar",
    "special_instructions": "",
    "delivery_proofs": [
      {
        "url": "https://parceluncle.com/media/shipments/proofs/proof_001.jpg",
        "uploaded_at": "2024-05-10T16:30:00Z"
      }
    ],
    "created_at": "2024-05-10T10:00:00Z",
    "updated_at": "2024-05-10T16:45:00Z",
    "delivered_at": "2024-05-10T16:30:00Z"
  }
}
GET

Track Shipment

/carrier/v1/merchant/shipments/{tracking_number}/track/

Retrieve the real-time tracking timeline and current status of a specific shipment. Perfect for embedding tracking directly into your frontend.

Response Format
{
  "success": true,
  "data": {
    "tracking_number": "AWB123456789",
    "current_status": "OUT_FOR_DELIVERY",
    "description": "Out for delivery",
    "is_delivered": false,
    "rider": {
      "name": "Ramesh Kumar"
    },
    "delivery_proofs": [
      {
        "url": "https://parceluncle.com/media/shipments/proofs/proof_001.jpg",
        "uploaded_at": "2024-05-10T16:30:00Z"
      }
    ],
    "timeline": [
      {
        "status": "CREATED",
        "description": "Order created and awaiting processing",
        "timestamp": "2024-05-10T10:00:00Z",
        "note": "Created via Merchant API v1 [LIVE]"
      },
      {
        "status": "PICKED_UP",
        "description": "Parcel picked up by rider",
        "timestamp": "2024-05-10T12:30:00Z",
        "note": ""
      }
    ]
  }
}
REF

Tracking Status Codes

Every shipment moves through the following statuses. Use these codes to map your internal tracking system with Parcel Uncle's tracking updates.

Status Code Display Name Description Terminal?
First Mile
CREATED Created Order created and awaiting processing.
PENDING Pending Payment Awaiting payment confirmation.
PAID Payment Confirmed Payment received. Shipment queued for processing.
READY_TO_SHIP Ready to Ship Seller has packed the order, awaiting pickup.
ASSIGNED Assigned to Rider A rider has been assigned for pickup.
ACCEPTED Accepted by Rider Rider accepted and is heading to pickup location.
WAITING_PICKUP Waiting for Pickup Rider arrived at pickup location, waiting for parcel.
PICKUP_ATTEMPTED Pickup Attempted Rider tried to collect but couldn't (seller absent, not ready).
PICKED_UP Picked Up Parcel collected by rider from pickup location.
Mid Mile
ARRIVED_AT_HUB Arrived at Hub Parcel scanned at sorting hub. Hub name shown in timeline notes.
SORTING Sorting in Progress Parcel is being sorted at hub for next destination.
IN_TRANSIT In Transit Parcel moving between hubs. May repeat for multi-hub routes.
Last Mile
OUT_FOR_DELIVERY Out for Delivery Delivery rider heading to recipient address.
DELIVERY_ATTEMPTED Delivery Attempted Delivery tried but recipient unavailable. Creates NDR entry.
DELIVERED Delivered Successfully delivered to recipient. ✓ Final
Returns (RTO)
RTO_INITIATED RTO Initiated Return to origin process started.
RTO_IN_TRANSIT RTO In Transit Return shipment is moving back to seller.
RETURNED Returned Parcel returned to seller. ✓ Final
Exceptions
FAILED Delivery Failed All delivery attempts exhausted. Can be reattempted or RTO'd.
ON_HOLD On Hold Shipment paused by operations. Contact support.
DAMAGED Damaged Parcel reported as damaged during transit or handling.
LOST Lost Shipment lost — investigation in progress. ✓ Final
CANCELLED Cancelled Shipment cancelled before delivery. ✓ Final

Direct Delivery Flow

PAID ASSIGNED PICKED_UP OUT_FOR_DELIVERY DELIVERED

Hub-Based / Multi-Hub Flow

PICKED_UP ARRIVED_AT_HUB IN_TRANSIT ARRIVED_AT_HUB OUT_FOR_DELIVERY DELIVERED

ARRIVED_AT_HUB ↔ IN_TRANSIT can repeat for multi-hub routes. Hub name is in the timeline note.

RTO (Return) Flow

DELIVERY_ATTEMPTED RTO_INITIATED RTO_IN_TRANSIT RETURNED
💡 Tip: Not every shipment goes through all statuses. Use the timeline array from the Track endpoint for the actual sequence of events.
⚠️ Terminal Statuses: Once a shipment reaches DELIVERED, RETURNED, CANCELLED, or LOST, no further transitions occur.
GET

NDR List

NEW

/carrier/v1/merchant/ndr/

Retrieve all Non-Delivery Report (NDR) entries for your shipments. NDR entries are created when a delivery attempt fails.

Query Parameters

  • status: Filter by NDR status — OPEN, ACTION_TAKEN, RESOLVED, ESCALATED
  • action: Filter by action taken — PENDING, REATTEMPT, RTO, ADDRESS_UPDATE, HOLD
Request
curl -X GET "https://parceluncle.com/carrier/v1/merchant/ndr/?status=OPEN" \
  -H "X-API-Key: pu_live_..."
Response (200 OK)
{
  "success": true,
  "data": [
    {
      "ndr_id": "a1b2c3d4-...",
      "tracking_number": "PU1234567890",
      "attempt_number": 1,
      "reason": "RECIPIENT_UNAVAILABLE",
      "reason_detail": "Customer not at home",
      "rider_remarks": "Called twice, no answer",
      "status": "OPEN",
      "action": "PENDING",
      "action_taken_at": null,
      "reattempt_date": null,
      "reattempt_slot": "",
      "updated_address": "",
      "updated_phone": "",
      "created_at": "2024-05-10T16:45:00Z"
    }
  ]
}

NDR Reason Codes

Code Description
RECIPIENT_UNAVAILABLERecipient not available at delivery address
ADDRESS_INCORRECTIncorrect delivery address
ADDRESS_INCOMPLETEIncomplete address details
REFUSEDDelivery refused by recipient
DOOR_LOCKEDDoor locked / no response
COD_NOT_READYCOD amount not ready with recipient
RESCHEDULE_REQUESTEDCustomer requested reschedule
WEATHERWeather conditions prevented delivery
SECURITY_ISSUESecurity restriction at location
OTHEROther reason (see reason_detail)
POST

NDR Action

NEW

/carrier/v1/merchant/ndr/{tracking_number}/action/

Take action on an open NDR case. You can reattempt delivery, update the address, or initiate a Return to Origin (RTO).

Available Actions

Action Required Fields Description
REATTEMPT reattempt_date (YYYY-MM-DD), reattempt_slot (optional) Schedule a re-delivery attempt on the specified date
ADDRESS_UPDATE updated_address (required), updated_phone (optional) Update the delivery address and reattempt
RTO remarks (optional) Return the parcel to the sender (Return to Origin)

Example: Reattempt Delivery

Request
curl -X POST "https://parceluncle.com/carrier/v1/merchant/ndr/PU1234567890/action/" \
  -H "X-API-Key: pu_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "action": "REATTEMPT",
    "reattempt_date": "2024-05-12",
    "reattempt_slot": "10AM-1PM"
  }'
Response (200 OK)
{
  "success": true,
  "message": "NDR action REATTEMPT applied successfully",
  "data": {
    "ndr_id": "a1b2c3d4-...",
    "tracking_number": "PU1234567890",
    "attempt_number": 1,
    "reason": "RECIPIENT_UNAVAILABLE",
    "status": "ACTION_TAKEN",
    "action": "REATTEMPT",
    "action_taken_at": "2024-05-11T08:30:00Z",
    "reattempt_date": "2024-05-12",
    "reattempt_slot": "10AM-1PM"
  }
}

Example: Update Address

Request Payload
{
  "action": "ADDRESS_UPDATE",
  "updated_address": "B-15, Block C, Sector 62, Noida, UP 201309",
  "updated_phone": "9876543210"
}

Example: Return to Origin

Request Payload
{
  "action": "RTO",
  "remarks": "Customer refused delivery"
}
⚠️ Note: Only OPEN NDR cases can have actions taken on them. If no open NDR exists for the shipment, the API will return a 404 error.
POST

Cancel Shipment

/carrier/v1/merchant/shipments/{tracking_number}/cancel/

Cancel a shipment and receive a wallet refund. The behavior depends on whether a rider has been assigned:

No Rider Assigned
  • Instant cancellation
  • Full wallet refund (auto-approved)
  • Returns 200 OK
Rider Assigned
  • Cancellation request created
  • Admin reviews & decides refund (full/partial/none)
  • Returns 202 Accepted

Request Body

Field Type Required Description
reason string Yes Reason for cancelling the shipment

Cancellable Statuses

CREATED PENDING PAID ASSIGNED ACCEPTED

Example: Instant Cancel (No Rider)

Request
curl -X POST "https://parceluncle.com/carrier/v1/merchant/shipments/PU1234567890/cancel/" \
  -H "X-API-Key: pu_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "reason": "Customer changed delivery address"
  }'
Response (200 OK)
{
  "success": true,
  "data": {
    "tracking_number": "PU1234567890",
    "status": "CANCELLED",
    "cancellation_status": "AUTO_APPROVED",
    "refund_type": "FULL",
    "refund_amount": "149.00",
    "message": "Shipment cancelled successfully. Full refund processed.",
    "sandbox": false
  }
}

Example: Pending Review (Rider Assigned)

Request
curl -X POST "https://parceluncle.com/carrier/v1/merchant/shipments/PU9876543210/cancel/" \
  -H "X-API-Key: pu_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "reason": "Order cancelled by buyer"
  }'
Response (202 Accepted)
{
  "success": true,
  "data": {
    "tracking_number": "PU9876543210",
    "status": "ASSIGNED",
    "cancellation_status": "PENDING",
    "rider_assigned": "Rahul Sharma",
    "message": "Rider \"Rahul Sharma\" is assigned. Cancellation request submitted for admin review.",
    "sandbox": false
  }
}

Response Fields

Field Type Description
tracking_number string Tracking number of the shipment
status string CANCELLED (instant) or the current status (pending review)
cancellation_status string AUTO_APPROVED (no rider) or PENDING (rider assigned, awaiting admin)
refund_type string FULL, PARTIAL, or NONE. Only present for auto-approved.
refund_amount string Refund amount credited to wallet. Only present for auto-approved.
rider_assigned string Name of assigned rider. Only present when status is PENDING.
💡 Refund Flow: When no rider is assigned, the full shipment amount is automatically refunded to your wallet. When a rider is assigned, an admin will review your request and can approve a full refund, partial refund, or no refund depending on the circumstances.
⚠️ Non-cancellable: Shipments that are already PICKED_UP, IN_TRANSIT, OUT_FOR_DELIVERY, DELIVERED, FAILED, RETURNED, or CANCELLED cannot be cancelled via this endpoint. The API will return 400 Bad Request.
GET

Get Shipping Label

/carrier/v1/merchant/shipments/{tracking_number}/label/

Download a print-ready 4×6 inch PDF shipping label for any shipment. The label includes sender/recipient addresses, QR code for tracking, barcode, weight, dimensions, COD badge, and SKU details if available.

Path Parameters

  • tracking_number Required — The AWB/tracking number of the shipment.
📄 Response: This endpoint returns a binary PDF file (not JSON). Set your HTTP client to handle binary responses. The Content-Type header will be application/pdf.
Request
curl -X GET "https://parceluncle.com/carrier/v1/merchant/shipments/PU1234567890/label/" \
  -H "X-API-Key: pu_live_..." \
  --output Label-PU1234567890.pdf

Label Contents

  • Header: Parcel Uncle logo + QR code for live tracking
  • Tracking ID: Bold tracking number
  • From / To: Full sender and recipient addresses with phone numbers
  • Parcel Info: Weight, dimensions, service type
  • SKU Items: Item table with SKU, quantity, price (if available)
  • Payment: Payment method + COD amount badge
  • Barcode: Scannable barcode of the tracking number
Status Code Meaning
200 OK PDF label returned as binary download
404 Not Found Shipment not found or doesn't belong to your account
500 Error PDF generation failed (rare)
WEBHOOK

Webhooks

Receive real-time notifications when shipment events occur. Register a webhook URL and we'll POST event payloads to it automatically.

Configure Webhook URL

PUT /carrier/v1/merchant/webhook/

Register Webhook
curl -X PUT "https://parceluncle.com/carrier/v1/merchant/webhook/" \
  -H "X-API-Key: pu_live_..." \
  -H "Content-Type: application/json" \
  -d '{"webhook_url": "https://yoursite.com/parceluncle-webhook"}'
Response
{
  "success": true,
  "message": "Webhook URL configured successfully",
  "data": {
    "webhook_url": "https://yoursite.com/parceluncle-webhook",
    "events": [
      "shipment.status_updated",
      "shipment.ndr_created",
      "shipment.ndr_updated",
      "shipment.pod_uploaded"
    ]
  }
}

Supported Events

Event Triggered When
shipment.status_updated Any status change — CREATED, ASSIGNED, PICKED_UP, OUT_FOR_DELIVERY, DELIVERED, CANCELLED, RETURNED, etc.
shipment.ndr_created A Non-Delivery Report is filed (delivery attempt failed)
shipment.ndr_updated NDR action taken — reattempt, RTO, address update, etc.
shipment.pod_uploaded Proof of delivery image uploaded by the rider

Example Webhook Payloads

Status Update
{
  "event": "shipment.status_updated",
  "timestamp": "2024-06-01T16:30:00Z",
  "data": {
    "tracking_number": "PU1234567890",
    "status": "DELIVERED",
    "previous_status": "OUT_FOR_DELIVERY",
    "delivered_at": "2024-06-01T16:30:00Z",
    "updated_at": "2024-06-01T16:30:00Z"
  }
}
NDR Created
{
  "event": "shipment.ndr_created",
  "timestamp": "2024-06-01T14:00:00Z",
  "data": {
    "tracking_number": "PU1234567890",
    "shipment_status": "FAILED",
    "ndr": {
      "attempt_number": 1,
      "reason": "RECIPIENT_UNAVAILABLE",
      "reason_detail": "Customer not at home",
      "action": "PENDING",
      "status": "OPEN",
      "reattempt_date": null
    }
  }
}
POD Uploaded
{
  "event": "shipment.pod_uploaded",
  "timestamp": "2024-06-01T16:35:00Z",
  "data": {
    "tracking_number": "PU1234567890",
    "shipment_status": "DELIVERED",
    "pod": {
      "image_url": "/media/shipments/proofs/proof_001.jpg",
      "uploaded_at": "2024-06-01T16:35:00Z"
    }
  }
}

Other Endpoints

  • GET /carrier/v1/merchant/webhook/ — View current webhook config
  • PUT /carrier/v1/merchant/webhook/ — Set/update webhook URL
  • DELETE /carrier/v1/merchant/webhook/ — Remove webhook URL
Retry Policy: Failed deliveries are retried up to 3 times with exponential backoff (5s, 10s, 20s). Your endpoint should return a 2xx status code to acknowledge receipt.
REF

Error Codes

All error responses follow a standard format. Use the error field for programmatic handling and the message field for user-friendly display.

Standard Error Format
{
  "success": false,
  "error": "ERROR_CODE",
  "message": "Human-readable description of what went wrong",
  "details": {}
}

HTTP Status Codes

Code Status Meaning How to Fix
200 OK Request succeeded
201 Created Resource created successfully (shipment, etc.)
202 Accepted Request accepted for processing (e.g., cancellation pending admin review)
400 Bad Request Invalid or missing request parameters. The request body failed validation. Check the message field for which parameter is invalid. Verify all required fields are present and correctly formatted.
401 Unauthorized Missing, invalid, expired, or revoked API key. Verify your X-API-Key header is present and the key is active in your dashboard.
403 Forbidden API key is paused, or your IP is not in the whitelist, or you lack permission for this action. Check key status in dashboard. If using IP whitelisting, add your IP. Ensure the key type matches (TEST vs LIVE).
404 Not Found The requested resource (shipment, NDR, etc.) was not found or does not belong to your account. Verify the tracking number or resource ID. Ensure the shipment was created with the same API key / seller account.
409 Conflict Duplicate request or conflicting state. E.g., creating a shipment with an already-used order number, or cancelling an already-cancelled shipment. Check if the resource already exists. Use idempotency keys for retries.
422 Unprocessable Entity Request is well-formed but logically invalid. E.g., insufficient wallet balance, pincode not serviceable, COD amount mismatch. Check the message for the specific business logic failure. Top up wallet, verify serviceability, or fix COD/Prepaid amounts.
429 Too Many Requests You have exceeded the rate limit for your API key. Current limits: 500 req/min (Live), 60 req/min (Test). Implement exponential backoff. Batch your requests. Use webhooks instead of polling for tracking updates.
500 Internal Server Error An unexpected error occurred on our server. These are rare and logged automatically. Retry with exponential backoff. If persistent, contact support with the request_id from the response.
503 Service Unavailable Server is temporarily overloaded or under maintenance. Wait and retry after a few seconds. Check our status page for scheduled maintenance.

Example Error Responses

400 — Validation Error
{
  "success": false,
  "error": "VALIDATION_ERROR",
  "message": "recipient_phone is required",
  "details": {
    "field": "recipient_phone",
    "reason": "missing"
  }
}
401 — Authentication Error
{
  "success": false,
  "error": "INVALID_API_KEY",
  "message": "API key is invalid or has been revoked"
}
422 — Insufficient Balance
{
  "success": false,
  "error": "INSUFFICIENT_BALANCE",
  "message": "Wallet balance ₹45.00 is insufficient. Required: ₹149.00",
  "details": {
    "wallet_balance": "45.00",
    "required": "149.00"
  }
}
429 — Rate Limited
{
  "detail": "Request was throttled. Expected available in 23 seconds."
}
404 — Not Found
{
  "success": false,
  "error": "NOT_FOUND",
  "message": "Shipment PU0000000000 not found"
}
422 — Not Serviceable
{
  "success": false,
  "error": "NOT_SERVICEABLE",
  "message": "Pincode 999999 is not serviceable"
}
💡 Best Practice: Always check the success field first. If false, read the error code for programmatic handling and message for human-readable context. Implement retry logic with exponential backoff for 429, 500, and 503 errors.
🚀 Reduce 429 Errors: Instead of polling the tracking endpoint for status updates, set up Webhooks to receive real-time push notifications. This eliminates rate limit issues entirely and gives you instant status updates.
REF

Response Fields Reference

Complete reference of all fields returned in shipment responses across Create, List, and Get endpoints.

Field Type Description
tracking_number string Unique AWB number for the shipment
status string Current status: CREATED, PAID, ASSIGNED, PICKED_UP, IN_TRANSIT, OUT_FOR_DELIVERY, DELIVERED, FAILED, CANCELLED
service_type string SAME_DAY, NEXT_DAY, or EXPRESS_4H
payment_method string How the merchant pays: WALLET, CREDIT, or COD
payment_mode 🆕 string Recipient-side payment: "COD" or "Prepaid". Derived from is_cod.
order_number 🆕 string Merchant's own order reference. Empty string if not provided.
total_amount 🆕 string | null Complete order value. Null for shipments created before this feature.
is_cod boolean Whether this is a Cash on Delivery order
cod_amount string Amount to collect from recipient ("0.00" if not COD)
shipment_amount string Shipping cost charged to the merchant
pickup object Pickup address details (address, city, state, pincode, landmark)
delivery object Delivery address details (address, city, state, pincode, landmark)
sender object Sender contact info (name, phone, email)
recipient object Recipient contact info (name, phone, email)
parcel object Parcel details (type, weight_kg, length_cm, width_cm, height_cm)
cost_breakdown object Itemized pricing (distance_charge, weight_charge, gst_amount, etc.)
assigned_rider string | null Name of the assigned rider, or null if not yet assigned
created_at string (ISO 8601) Timestamp when the shipment was created
delivered_at string | null Timestamp when delivered, null if not yet delivered
delivery_proofs array Proof of delivery images. Each entry has url (absolute image URL) and uploaded_at (ISO 8601 timestamp). Empty array if no proofs uploaded.