Getting Started

Hubbazzar Shipping API

The Hubbazzar Shipping API lets you create shipments, cancel orders, track packages, manage NDR actions, query your wallet, and receive real-time events via webhooks — all without logging into the panel.

Base URL
https://hubbazzar.com/api/v1/shipping
Authentication
Bearer Token
Rate Limit
600 req / min
Quick Start: Get your API token from Shipping Panel → API Settings. Include it as Authorization: Bearer <token> in every request.

Authentication

All protected endpoints require a Bearer token in the Authorization header. You can obtain a token two ways:

  1. Static token (recommended): Generated once in Panel → API Settings. Never expires unless you regenerate. Always visible in the panel.
  2. Login token: POST /auth/login with email + password. Revocable via /auth/logout.
# Include in every API request: Authorization: Bearer 1|AbCdEfGhIjKlMnOpQrStUvWxYz... Accept: application/json
POST /auth/login Obtain a Bearer token (no token required)

Returns a Bearer token for subsequent requests.

// Request { "email": "user@example.com", "password": "your-password", "device_name": "my-integration" // optional } // Response 200 { "success": true, "data": { "token": "1|AbCdEfGhIj...", "token_type": "Bearer", "user": { "id": 42, "name": "Acme Store", "wallet_balance": 1500.00 } } }

Rate Limits

Protected endpoints are limited to 600 requests per minute per token. When exceeded, the API returns 429 Too Many Requests with a Retry-After header.

Bulk endpoints (bulk create, bulk cancel, NDR bulk action) count as a single request regardless of order count.

Error Handling

All errors follow the same envelope structure:

{ "success": false, "message": "Human-readable error", "errors": { /* validation map */ } }
HTTP CodeMeaning
200Success
201Resource created
401Missing / invalid token
402Insufficient wallet balance
403Account inactive
404Resource not found
422Validation failed or business rule violation
429Rate limit exceeded
500Internal server error
502Upstream courier API failure

Pagination

List endpoints support per_page (max 100, default 20) and page query parameters.

{ "data": { "items": [ /* array of resources */ ], "total": 250, "per_page": 20, "current_page": 1, "last_page": 13 } }

Webhooks

Configure a webhook URL in API Settings (or via the API) and Hubbazzar will POST a JSON payload to your server on key events.

Payload shape

{ "event": "order.cancelled", "timestamp": "2026-05-28T10:30:00+05:30", "data": { /* event-specific payload */ } }

Signature verification

When a secret is configured every POST includes:

X-Hub-Signature-256: sha256=<HMAC-SHA256(secret, raw_body)> X-Hub-Event: order.cancelled X-Hub-Delivery: <uuid>

Verify in PHP:

$valid = hash_equals( 'sha256=' . hash_hmac('sha256', $rawBody, $secret), $_SERVER['HTTP_X_HUB_SIGNATURE_256'] );
EventTrigger
order.createdNew shipment created via API
order.status_updatedOrder status changed via Delhivery tracking webhook (fires on every status transition)
order.cancelledSingle order cancelled (API or panel)
orders.bulk_cancelledBulk cancel batch completed
ndr.action_submittedNDR reattempt / reschedule action submitted
webhook.testTest ping from API settings

order.status_updated — example payload

Fired automatically every time Delhivery pushes a status change to our panel. Use this to keep your system in sync without polling.

{ "event": "order.status_updated", "timestamp": "2026-05-28T14:30:00+05:30", "data": { "order_id": 1024, "client_order_id": "MY-ORD-2001", "waybill": "1234567891", "previous_status": "in_transit", "new_status": "delivered", "status_description": "Shipment delivered", "status_location": "Gurugram_Sector15_D (Haryana)", "event_date": "2026-05-28T14:28:00.000", "nsl_code": null, "is_ndr": false } }
Note: previous_status and new_status use the canonical status keys (e.g. in_transit, delivered, rto). When is_ndr is true, the nsl_code field will contain the Delhivery NDR reason code.
Endpoints

Shipments

GET /shipments List orders

Returns paginated list of shipments. Filter by status, waybill, date range, or payment mode.

Query Parameters

ParameterTypeDescription
statusstringFilter by order_status (e.g. created, in_transit, delivered)
payment_modestringPrepaid or COD
waybillstringExact waybill/AWB match
client_order_idstringPartial match on your order reference
date_fromdateFilter by created_at ≥ date (YYYY-MM-DD)
date_todateFilter by created_at ≤ date
per_pageintItems per page (max 100, default 20)
// GET /api/v1/shipping/shipments?status=in_transit&per_page=50 { "success": true, "data": { "items": [ { "id": 1023, "client_order_id": "MY-ORD-001", "waybill": "1234567890", "order_status": "in_transit", "payment_mode": "COD", "order_amount": 499.00, "shipping_charge": 65.00, "courier_code": "Delhivery", "created_at": "2026-05-28 09:00:00" } ], "total": 142, "per_page": 50, "current_page": 1, "last_page": 3 } }
POST /shipments Create a single shipment

Creates a shipment, deducts shipping charge from your wallet, and pushes the order to Delhivery. Returns the assigned AWB (waybill).

Request Body

FieldTypeRequiredDescription
consignee_namestringRequiredRecipient full name
consignee_mobilestringRequiredRecipient phone (10 digits)
consignee_address1stringRequiredAddress line 1
consignee_address2stringOptionalAddress line 2
consignee_pincodestring (6 digits)RequiredDelivery pincode
consignee_citystringOptionalCity
consignee_statestringOptionalState
consignee_emailemailOptionalRecipient email
payment_modestringRequiredPrepaid or COD
order_amountnumericRequiredInvoice / declared value
cod_amountnumericOptionalCOD amount (defaults to order_amount for COD orders)
pick_address_idstringRequiredPickup address ID from your warehouses
return_address_idstringOptionalReturn address ID (defaults to pick_address_id)
express_typestringRequiredsurface or air
courier_codestringRequiredCourier code (e.g. Delhivery)
shipment_weightnumeric (kg)RequiredDead weight in kg (min 0.1)
shipment_lengthnumeric (cm)OptionalPackage length
shipment_widthnumeric (cm)OptionalPackage width
shipment_heightnumeric (cm)OptionalPackage height
client_order_idstringOptionalYour internal order reference (auto-generated if omitted)
invoice_numberstringOptionalInvoice number printed on label
address_typestringOptionalHome, Office, or Other
productsarrayOptionalProduct line items (see below)

Product object fields: product_name (required), product_quantity, product_price, sku

// POST /api/v1/shipping/shipments { "consignee_name": "Rahul Sharma", "consignee_mobile": "9876543210", "consignee_address1": "B-12, Sector 15", "consignee_pincode": "122001", "consignee_city": "Gurugram", "consignee_state": "Haryana", "payment_mode": "COD", "order_amount": 599, "pick_address_id": "my-warehouse-mumbai", "express_type": "surface", "courier_code": "Delhivery", "shipment_weight": 0.5, "client_order_id": "MY-ORD-2001", "products": [{ "product_name": "Blue T-Shirt", "product_quantity": 1, "product_price": 599 }] } // Response 201 { "success": true, "message": "Shipment created successfully.", "data": { "order_id": 1024, "client_order_id": "MY-ORD-2001", "waybill": "1234567891", "order_status": "created", "shipping_charge": { "base": 55.0, "cod": 10.0, "gst": 11.7, "total": 76.7 }, "wallet_balance": 1423.30 } }
A 402 response means your wallet balance + credit is insufficient. Recharge before retrying.
POST /shipments/bulk Create up to 50 orders in one call

Send an array of order objects (same fields as single create). Returns which succeeded and which failed.

// POST /api/v1/shipping/shipments/bulk { "orders": [ { /* same fields as single create */, "client_order_id": "ORD-001" }, { /* ... */, "client_order_id": "ORD-002" } ] } // Response 201 / 422 (422 if ALL failed) { "success": true, "message": "2 order(s) created, 0 failed.", "data": { "succeeded": [ { "order_id": 1024, "waybill": "123..." } ], "failed": [] } }
GET /shipments/{id} Get full order details

Returns all fields including consignee details, dimensions, products, and refund info.

// GET /api/v1/shipping/shipments/1024 { "success": true, "data": { "id": 1024, "client_order_id": "MY-ORD-2001", "waybill": "1234567891", "order_status": "in_transit", "payment_mode": "COD", "order_amount": 599.00, "consignee_name": "Rahul Sharma", "consignee_mobile": "9876543210", "shipment_weight": 0.5, "products": [ /* array */ ], "channel": "api", "label_printed": false } }
POST /shipments/{id}/cancel Cancel a shipment

Cancels the order on Delhivery first. Only if the courier confirms the cancel, the order is marked 227 (Cancelled) and the shipping charge is refunded to your wallet. Terminal orders (delivered, RTO, lost) cannot be cancelled.

// POST /api/v1/shipping/shipments/1024/cancel { "reason": "Customer requested cancel" } // optional // Response 200 { "success": true, "message": "Shipment cancelled successfully.", "data": { "order_id": 1024, "waybill": "1234567891", "refunded_amount": 76.70, "wallet_balance": 1500.00, "courier_cancel": true } }
If Delhivery rejects the cancel (shipment already picked up), the API returns 422 and the order remains unchanged.
POST /shipments/bulk-cancel Cancel up to 50 orders

Same cancel logic as single cancel, applied per order. Returns succeeded + failed arrays.

// POST /api/v1/shipping/shipments/bulk-cancel { "order_ids": [1024, 1025, 1026], "reason": "Customer cancelled" } // Response 200 { "success": true, "message": "2 order(s) cancelled, 1 failed.", "data": { "succeeded": [ { "order_id": 1024, "waybill": "123...", "refunded_amount": 76.70 } ], "failed": [ { "order_id": 1026, "reason": "Delhivery cancel failed" } ], "wallet_balance": 1500.00 } }
GET /shipments/{id}/track Live tracking + scan events

Returns cached tracking data. Add ?sync=1 to force a live pull from Delhivery.

// GET /api/v1/shipping/shipments/1024/track?sync=1 { "data": { "order_id": 1024, "waybill": "1234567891", "order_status": "in_transit", "tracking": { "current_status": { "status_code": "Transit", "status_description": "In Transit", "status_location": "Delhi", "event_date": "2026-05-27 18:45:00" }, "tracking_events": [ { "event_date": "2026-05-27 18:45:00", "status_description": "In Transit", "status_location": "Delhi" } ], "estimated_delivery_date": "2026-05-29" } } }
GET /shipments/{id}/label Download shipping label PDF

Streams the PDF label. Add ?format=url to get a JSON response with the panel URL instead.

// GET /api/v1/shipping/shipments/1024/label // → streams PDF (Content-Type: application/pdf) // GET /api/v1/shipping/shipments/1024/label?format=url { "data": { "label_url": "https://hubbazzar.com/shipping-panel/label/1024", "format": "pdf" } }
Wallet

Wallet

GET /wallet Balance, credit & available total

available_total = wallet_balance + wallet_credit. Shipping charges are deducted from available_total, so you can use credit for shipments even if wallet_balance is 0.

{ "data": { "wallet_balance": 1500.00, "wallet_credit": 500.00, "available_total": 2000.00, "currency": "INR" } }
GET /wallet/transactions Paginated wallet ledger
Query ParamDescription
typecredit or debit
payment_methodwallet, refund, cashfree
date_from / date_toDate range filter (YYYY-MM-DD)
referencePartial match on waybill / reference
per_pageMax 100, default 20
{ "data": { "items": [ { "id": 5001, "transaction_id": "SHP-1024-1748400000-1234", "type": "debit", "payment_method": "wallet", "amount": 76.70, "balance_after": 1423.30, "reference": "Shipping charge for MY-ORD-2001", "created_at": "2026-05-28 09:00:00" } ], "total": 320, "per_page": 20, "current_page": 1 } }
payment_method values: wallet = shipping charge deduction or admin credit, refund = cancel refund, cashfree = Cashfree recharge
NDR

Non-Delivery Reports (NDR)

Manage failed delivery attempts. NDR orders require an action (reattempt or reschedule) within Delhivery's SLA window.

GET /ndr List active NDR orders
Query ParamDescription
action_statuspending (no action yet) or actioned
nsl_codeFilter by Delhivery NSL code (e.g. EOD-56)
date_from / date_toFilter by NDR date
per_pageMax 100, default 20
{ "data": { "items": [ { "id": 1023, "waybill": "1234567890", "ndr_reason": "Customer phone not reachable", "nsl_code": "EOD-56", "ndr_at": "2026-05-27 14:00:00", "ndr_action_type": null, "payment_mode": "COD", "order_amount": 499.00 } ] } }
POST /ndr/{id}/action Submit NDR action for one order
// POST /api/v1/shipping/ndr/1023/action { "action": "RE-ATTEMPT", // or "PICKUP_RESCHEDULE" "remark": "Please call before delivery" // optional } // Response 200 { "data": { "order_id": 1023, "waybill": "1234567890", "action": "RE-ATTEMPT", "upl_id": "UPL123456", "action_at": "2026-05-28 10:00:00" } }

RE-ATTEMPT — Request another delivery attempt on the next business day.
PICKUP_RESCHEDULE — Customer will collect from Delhivery branch or reschedule to a different date.

POST /ndr/bulk-action Same action for up to 100 NDR orders
{ "order_ids": [1023, 1024], "action": "RE-ATTEMPT" }
POST /ndr/sync Pull latest NDR state from Delhivery

Fetches bulk tracking for your active shipments (in 50-AWB chunks) and updates NDR flags and NSL codes in your panel. Optional limit query param (max 500, default 200).

// POST /api/v1/shipping/ndr/sync { "limit": 300 } // Response 200 { "message": "Synced 287 orders.", "data": { "synced": 287 } }
GET /ndr/nsl-codes All 102 Delhivery NSL codes + remarks
{ "data": [ { "nsl_code": "EOD-56", "remark": "Customer phone not reachable" }, { "nsl_code": "EOD-26", "remark": "Consignee unavailable" }, { /* ... 102 total */ } ], "total": 102 }
Webhook

Webhook Configuration

GET /webhook View current webhook settings
{ "data": { "webhook_url": "https://mystore.com/hooks", "webhook_secret": "***xYz9", "has_secret": true } }
POST /webhook Save / update webhook URL + secret
{ "webhook_url": "https://mystore.com/hooks/shipping", "webhook_secret": "my-super-secret-key-32chars", // optional, min 16 "auto_secret": true // if true and no webhook_secret, auto-generate a 48-char secret }
POST /webhook/test Send test ping to your URL

Sends a webhook.test event to your configured URL. Useful for verifying your endpoint and signature.

// No request body required { "success": true, "message": "Test webhook dispatched to https://mystore.com/hooks" }
Utilities

Utilities

GET /warehouses List pickup addresses

Returns all warehouses for your account. Use the pick_address_id field in shipment creation.

Also: POST /warehouses (add), PUT /warehouses/{id} (update), DELETE /warehouses/{id} (remove), POST /warehouses/{id}/sync (sync with Delhivery).

GET /rate-card Your rate card

Returns your negotiated rate card including weight slabs and COD charges.

Also: POST /calculate-rate — pass courier_code, weight, mode (surface/air), payment_mode, order_amount to get a cost estimate.

GET /cod-remittances COD remittance history

List COD remittance batches from Delhivery. Also: GET /cod-remittances/summary and GET /cod-remittances/{id}.

GET /pincode/{pincode} Check pincode serviceability

Check if a single pincode is serviceable. Use POST /pincode/bulk with { "pincodes": ["110001","400001"] } for batch checks (max 200).

GET /auth/profile Auth endpoints
MethodEndpointDescription
POST/auth/loginObtain token (public)
POST/auth/logoutRevoke current token
GET/auth/profileAccount details + wallet balance
POST/auth/token/rotateRevoke + issue a new token
Reference

Order Status Codes

Both canonical string statuses and legacy numeric Delhivery codes are used in order_status.

Panel Status Groups

Panel GroupStatus Values IncludedDescription
Not Pickedcreated, 220, 221, 222, 223, 224Order created, awaiting pickup by courier
In Transitin_transit, 228, 230, 231, 233, 232, 234, 238, 531In courier network
Dispatcheddispatched, 225Out for delivery
Delivereddelivered, 226Delivered to consignee
RTOrto, 235, 236, rto_returnedReturn to origin in progress or completed
Cancelled227, cancelledCancelled by seller or customer
Lost237, lostLost in transit (Delhivery claim)
NDR233, ndrNon-delivery report — requires action

All Numeric Status Codes (Delhivery)

CodeMeaningTerminal?
220Pickup ScheduledNo
221Pickup AttemptedNo
222Pickup CancelledNo
223Pickup ExceptionNo
224Manifest CreatedNo
225Out for DeliveryNo
226DeliveredYes
227CancelledYes
228In TransitNo
229Failed DeliveryYes
230Reached at HubNo
231MisroutedNo
232At Origin HubNo
233Undelivered / NDRNo
234Picked UpNo
235RTO InitiatedNo
236RTO In TransitNo
237LostYes
238Held at HubNo
531Shipment BookedNo
Cancellable orders — any order NOT in status: delivered, 226, rto, 227, 237, 229. Once picked up by the courier, Delhivery may reject the cancel.

NSL Codes — Delhivery NDR Reasons (102)

These codes appear in the nsl_code field of NDR orders. Use them to filter and take appropriate actions.

NSL CodeRemark
EOD-53 Amount disputed by customer
EOD-26 Consignee unavailable
SD-107 Order will be rescheduled due to low capacity - Drop
EOD-89 Customer wants to reschedule beyond 3 working days
CL-102 Canceled as per client's instructions
CL-101 Re-Scheduled as per client's instruction
ST-6W Consignee verified cancellation
ST-120 Maximum attempts reached for self collect
EOD-118 Temporary stair/lift issue
ST-NI IVR call not received by customer
EOD-40 Payment Mode / Amt Dispute
X-IIN3R No Service Zone. To be RTO'd
EOD-14 Office closed
DTUP-229 Content Short Reported By client
EOD-147 Consignee refused to Accept
EOD-56 Customer phone not reachable
EOD-35 Other
EOD-11 Consignee Unavailable
EOD-158 Failed KYC -Code not available
EOD-106 Reached Maximum attempt count
X-IIN1R No Service Zone. To be RTO'd
EOD-6 Consignee refused to accept/order cancelled
DLYB2B-107 Payment mode/ Amount dispute
X-IIN4R No Service Zone. To be RTO'd
EOD-103 Reached maximum attempt count
EOD-50 Returned as per client instructions
EOD-114 Buyer refused order
EOD-102 Customer not ready for e-KYC
EOD-43 Consignee will collect from branch
EOD-85 Customer phone not reachable
SC-107 Customer requested for self collect
COVID19-007 Corona Client Closed
EOD-15 Recipient wants delivery at a different address
COVID19-003 Corona Police/Administration Shut Down
ST-205 Consignee unavailable - Consignee location permanently closed
EOD-70 Unable to reach Customer
DLYRPC-417 Address on package is different from HQ address
EOD-149 On Hold. Recipient unable to Accept Delivery
RT-105 Wrong pin code & address is not serviceable
COVID19-004 Corona Limited Dispatch Timings
CL-108 Canceled as per customer instruction
EOD-65 Not attempted
DLYDC-107 Office/Institute closed
COVID19-010 Corona Red Zone Area
EOD-42 Product Dispute
EOD-107 No Service Zone
EOD-18 Consignee has refused delivery of product
RT-114 Address details invalid
EOD-17 Non serviceable location
DLYB2B-105 No Entry/ Entry restricted
EOD-51 Deferred by customer
SC-104 Bad Address
EOD-121 Entry restricted area
EOD-74 Incomplete address & contact details
EOD-8 Wanted to open the package before payment
EOD-69 Recipient wants open delivery
EOD-55 Customer not available at home
EOD-104 Entry restricted area
ST-NT NDR call not received by customer
EOD-32 Consignee unavailable for extended duration
EOD-12 Door locked, retrial tomorrow (Customer to be called)
EOD-148 Recipient unavailable. Establishment closed
ST-109 Out of service area
EOD-41 Payment Mode-Amount dispute
EOD-78 Cash not ready with the customer. To be attempted again
FMEOD-143 Seller/Buyer cancelled order - Geofenced
X-IIN2R No Service Zone. To be RTO'd
EOD-13 No such person at the given address
DLYB2B-108 Consignee not reachable/Contact details unavailable
EOD-151 Consignee unavailable - Permanently closed
ST-NI6 No customer response from IVR call
RT-107 Unsuccessful NDR Reattempt
X-NSZ Non-serviceable location
ST-102 Bad/Incomplete Address
EOD-83 Damaged/Used Product
EOD-67 Customer phone not Reachable
SC-102 ODA Shipment
FMEOD-115 Temporary stairs/lift problem
EOD-72 Consignee did not have cash
EOD-16 Payment not ready with customer
EOD-110 Customer did not show ID card
DLYLH-146 Appointment awaited from consignee
EOD-45 Duplicate consignment for RTO
FMEOD-118 Seller/Buyer cancelled order
EOD-59 Not interested
SC-103 Self Collect requested by customer
EOD-3 Delivery Rescheduled by Customer
EOD-138 Consignee did not receive the Code
EOD-97 Customer does not want to handover documents
FMEOD-150 Seller/Buyer cancelled order - OTP Verified
FMEOD-138 Seller/Buyer cancelled order - qr verified
DTUP-226 Address changed by Customer
EOD-76 Consignee not available for extended duration
DLYB2B-106 Payment Issue ( Amount Dispute/ Cash/ Cheque not ready
EOD-34 Other
DLYDC-132 Out of Delivery Area (ODA)
EOD-73 Bad/Incomplete address
EOD-6O Code verified cancellation
EOD-105 Shipment seized by consignee
EOD-46 Duplicate Consignment from Shipper
EOD-112 Dispatch but not attempted due to rain
EOD-98 No KYC request from Customer Side