Ship from your own system.
Create orders, fetch the AWB WePicks assigns to them, track every scan, check serviceability and price a lane — all over a token-authenticated JSON API on the same platform your dashboard runs on.
Base URL
https://api.wepicks.in/api
Authentication
Authorization: Token <your-api-token>
Your token
How an integration fits together
The recommended flow books the order into your WePicks dashboard, lets WePicks assign the AWB, and then reads that AWB back into your system. Everything else — tracking, labels, pickups — keys off the AWB.
Generate an API token
In the merchant portal, open Settings → API Setup and request a live token. It is shown once — copy it into your secrets store.
Register your pickup location
Every order is booked from a warehouse. Create it in the portal or with Client Warehouse Creation; the name you give it is what you will pass as
pickup_location/warehousename.Create the order
Call Order to Dashboard with your own order id. WePicks processes it and assigns the AWB.
Read the AWB back
Call Fetch AWB by Order ID with the order id and pickup location until
awb_assignedistrue. Store the waybill against the order in your system.
Authentication
Token in headerEvery call is authenticated with your account's API token. Send it in the Authorization header using the Token scheme. The token identifies your merchant account; every record the API reads or writes is scoped to it.
Authorization: Token XXXXXXXXXXXXXXXXXXXXXXXX
Content-Type: application/json
Accept: application/json
Getting a token
- Sign in to one.wepicks.in and open Settings → API Setup.
- Click Request Live API Token. The token is shown once; copy it immediately.
- Store it in your server's secrets manager or environment, never in client-side code, mobile apps or version control.
If you suspect the token has leaked, write to support@wepicks.in from your registered email to have it rotated.
Accepted forms
| Where | Form | Notes |
|---|---|---|
Authorization header | Token <key> | Documented form. Use this. |
Authorization header | Bearer <key> | Accepted for HTTP clients that only know the Bearer scheme. |
X-Api-Key header | <key> | Accepted for platforms that cannot set Authorization. |
| Query string | ?token=<key> | Deprecated Still honoured on the older GET endpoints only (Pin-code, Fetch WayBill, Tracking, Label, Weight Mismatch). Responses carry a Deprecation: true header. Not accepted on any new endpoint. |
Move tokens out of URLs. A token in a query string is written to web-server logs, proxies and browser history. Switch existing integrations to the Authorization header; the query form will be removed in a later version.
Account state
Calls from a deactivated account are refused with 403 ACCOUNT_INACTIVE. Invalid or missing tokens are refused with 401 and are counted against the authentication-failure limit.
Security
What the API does on its side, and what we ask of your integration.
On the WePicks side
HTTPS only
All endpoints are served over TLS. Plain HTTP is redirected; never send a token over HTTP.
Account-scoped data
Orders, warehouses and waybills are always looked up together with the account behind the token. One merchant cannot read or act on another's shipments.
Parameterised queries
Token lookups and record lookups use prepared statements. Parameters are length-checked and control characters are rejected.
Rate limiting
Per-token request limits and a per-IP limit on failed authentication, both answered with 429 and Retry-After.
Request ids & audit log
Every call gets an X-Request-Id, echoed as request_id in JSON responses and kept in our request log. Quote it to support.
Hardened responses
Cache-Control: no-store, X-Content-Type-Options: nosniff and Referrer-Policy: no-referrer on every response. Server errors never include stack traces or paths.
On your side
- Call from your server, not the browser. The token must never ship inside a web page, mobile app or storefront theme.
- Keep the token in a secrets store (environment variable, vault, platform secret). Rotate it through support if it is ever committed or shared.
- Verify TLS. Do not disable certificate verification in your HTTP client, even in staging.
- Handle
429with backoff. ReadRetry-Afterand wait; do not retry in a tight loop. - Use your own order id as the idempotency key. If an Order to Dashboard call times out, call Fetch AWB by Order ID before creating the order again.
- Log
request_idalongside your own order id so support can trace a call end to end. - Egress allow-list:
api.wepicks.inon port 443.
Found a security issue? Email support@wepicks.in with "Security" in the subject. Please do not test against other merchants' data.
Errors & status codes
Authentication, validation and rate-limit failures use one JSON envelope on every endpoint. Endpoints that proxy the carrier (manifest, tracking, serviceability, edit, cancel, pickup, warehouses, bulk waybill) return the carrier's own JSON on success.
{
"success": false,
"statusCode": 401,
"error": "Invalid API token",
"code": "INVALID_TOKEN",
"request_id": "5186201d75b22cdb"
}
| HTTP | code | Meaning |
|---|---|---|
| 200 | — | Success. For Fetch AWB, check awb_assigned: the order can exist before its AWB does. |
| 400 | MISSING_PARAMETER INVALID_PARAMETER | A required field is absent (missing lists them) or contains control characters. |
| 401 | MISSING_TOKEN INVALID_TOKEN | No token was sent, or it does not belong to any account. |
| 403 | ACCOUNT_INACTIVE | The token is valid but the account is deactivated. |
| 404 | PICKUP_LOCATION_NOT_FOUND ORDER_NOT_FOUND ORDER_NOT_AT_PICKUP_LOCATION | Nothing on your account matches. The response says which part did not match. |
| 405 | METHOD_NOT_ALLOWED | Wrong HTTP method. The Allow header lists the accepted ones. |
| 429 | RATE_LIMITED TOO_MANY_AUTH_FAILURES | Slow down. Retry-After says for how long. |
| 502 | — | The carrier did not accept or did not answer a proxied request. Safe to retry after a short wait. |
Rate limits
- 120 / minute
- Authenticated requests per API token, across all endpoints. Returned as
X-RateLimit-LimitandX-RateLimit-Remainingon every response. - 20 / minute
- Failed authentication attempts per client IP. Past that, the address receives
429 TOO_MANY_AUTH_FAILURESfor a minute, whatever token it sends.
Carrier-side limits on proxied endpoints still apply on top: tracking is capped at 750 requests per 5 minutes per IP, shipping cost at 40 requests per minute, and bulk waybill fetches at 10,000 waybills per call and 50,000 per 5 minutes.
When you receive a 429, wait for the number of seconds in Retry-After (currently always 60) before retrying. Polling Fetch AWB by Order ID every few minutes per order is well within the limit; polling every second is not.
Order to Dashboard
RecommendedBooks an order into your WePicks dashboard under one of your registered pickup locations — exactly what uploading a row in the bulk sheet does. WePicks then processes the order and assigns the AWB; read it back with Fetch AWB by Order ID. This is the right entry point for store and ERP integrations.
https://api.wepicks.in/api/order_to_dashboardFields may be sent as a JSON body (preferred) or as query-string parameters. Requires an active account.
Request
| Field | Required | Type | Description |
|---|---|---|---|
orderid | Yes | string ≤100 | Your order reference. Unique per order; you will use it again in Fetch AWB. |
warehousename | Yes | string | Name of a pickup location registered on your account, exactly as shown in the portal. |
order_date | Optional | string | Order date as shown on your invoice. |
shipment_description | Optional | string | What is in the box. |
item_count | Optional | integer | Number of items. |
total_value | Optional | number | Declared value in INR. |
fragile_items | Optional | string | Send "0" to mark the shipment fragile; any other value means not fragile. |
delivery_first_name / delivery_last_name | Yes | string | Consignee name. |
delivery_phone_number | Yes | string | Consignee mobile. The last 10 digits are used. |
delivery_address1 | Yes | string | Street address. |
delivery_pincode | Yes | string | 6-digit destination pincode. |
delivery_city / delivery_state / delivery_country | Yes | string | Destination. |
shipment_length / shipment_width / shipment_height | Optional | number | Centimetres. |
shipment_weight | Yes | integer | Grams. |
mode_of_shipment | Optional | string | Surface or Express, as agreed on your account. |
mode_of_payment | Yes | string | COD or Pre-paid. For Pre-paid, cod_amount is forced to 0. |
cod_amount | Optional | number | Amount to collect, for COD. |
The characters & # % ; ' " and newlines are stripped from text fields before saving, so a name or address containing them is saved without them.
curl --request POST \
--url "https://api.wepicks.in/api/order_to_dashboard" \
--header "Content-Type: application/json" \
--header "Authorization: Token XXXXXXXXXXXXXXXXXX" \
--data '{
"orderid": "ORD-1001",
"warehousename": "Main Warehouse",
"order_date": "2026-10-07",
"shipment_description": "Cotton kurta x2",
"item_count": "2",
"total_value": "1499",
"fragile_items": "1",
"delivery_first_name": "Asha",
"delivery_last_name": "Nair",
"delivery_phone_number": "9876543210",
"delivery_address1": "12, 3rd Cross, Indiranagar",
"delivery_country": "India",
"delivery_pincode": "560038",
"delivery_state": "Karnataka",
"delivery_city": "Bengaluru",
"shipment_length": "30",
"shipment_height": "5",
"shipment_width": "25",
"shipment_weight": "500",
"mode_of_shipment": "Surface",
"mode_of_payment": "COD",
"cod_amount": "1499"
}'
Response
{
"statusCode": 200,
"message": "Order created successfully",
"orderid": "ORD-1001",
"warehouseid": 10,
"mobile": "9876543210",
"fragile_item": "false"
}
The AWB is not in this response: it is assigned when WePicks processes the order. Poll Fetch AWB by Order ID with the same orderid and warehousename.
Fetch AWB by Order ID
NewHeader token onlyReturns the AWB (waybill) number WePicks assigned to one of your orders. Pass the order id you used when creating the order and the pickup location it was booked from; the response carries the waybill, the current status and a public tracking link. Both fields are matched against your account only.
https://api.wepicks.in/api/fetch-awb?orderid={orderid}&pickup_location={pickup_location}Also accepts POST with the same two fields as a JSON body. Requires an active account. The ?token= query form is not accepted here — send the Authorization header.
Request
| Parameter | Required | Type | Description |
|---|---|---|---|
orderid | Yes | string ≤100 | The order id you sent as orderid (Order to Dashboard) or order (Package Shipment Creation). Exact match. |
pickup_location | Yes | string ≤100 | Name of the registered pickup location the order was booked from, exactly as in the portal. warehousename is accepted as an alias. |
curl --request GET \ --url "https://api.wepicks.in/api/fetch-awb?orderid=ORD-1001&pickup_location=Main%20Warehouse" \ --header "Authorization: Token XXXXXXXXXXXXXXXXXX" \ --header "Accept: application/json"
curl --request POST \
--url "https://api.wepicks.in/api/fetch-awb" \
--header "Authorization: Token XXXXXXXXXXXXXXXXXX" \
--header "Content-Type: application/json" \
--data '{"orderid": "ORD-1001", "pickup_location": "Main Warehouse"}'
<?php $ch = curl_init('https://api.wepicks.in/api/fetch-awb?' . http_build_query([ 'orderid' => 'ORD-1001', 'pickup_location' => 'Main Warehouse', ])); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'Authorization: Token ' . getenv('WEPICKS_API_TOKEN'), 'Accept: application/json', ], ]); $body = json_decode(curl_exec($ch), true); $http = curl_getinfo($ch, CURLINFO_HTTP_CODE); if ($http === 200 && $body['awb_assigned']) { echo $body['waybill']; // 1383541222369 } elseif ($http === 200) { // order exists, AWB not assigned yet — poll again later } else { error_log($body['code'] . ' ' . $body['request_id']); }
// Node 18+ (global fetch) const url = new URL('https://api.wepicks.in/api/fetch-awb'); url.searchParams.set('orderid', 'ORD-1001'); url.searchParams.set('pickup_location', 'Main Warehouse'); const res = await fetch(url, { headers: { Authorization: `Token ${process.env.WEPICKS_API_TOKEN}`, Accept: 'application/json' }, }); const data = await res.json(); if (res.ok && data.awb_assigned) { console.log(data.waybill, data.tracking_url); } else if (res.status === 429) { // back off for Retry-After seconds } else { console.error(data.code, data.request_id); }
import os, requests
r = requests.get(
"https://api.wepicks.in/api/fetch-awb",
params={"orderid": "ORD-1001", "pickup_location": "Main Warehouse"},
headers={"Authorization": f"Token {os.environ['WEPICKS_API_TOKEN']}",
"Accept": "application/json"},
timeout=20,
)
data = r.json()
if r.ok and data["awb_assigned"]:
print(data["waybill"], data["status"]["label"])
elif r.ok:
pass # order exists, AWB not assigned yet
else:
print(r.status_code, data["code"], data["request_id"])
Response
{
"success": true,
"orderid": "ORD-1001",
"pickup_location": "Main Warehouse",
"awb_assigned": true,
"waybill": "1383541222369",
"status": { "code": 7, "label": "In Transit" },
"payment_mode": "COD",
"order_created_at": "2026-10-06T21:28:24+05:30",
"tracking_url": "https://wepicks.in/track?track=1383541222369",
"message": "AWB assigned",
"request_id": "5186201d75b22cdb"
}
{
"success": true,
"orderid": "ORD-2002",
"pickup_location": "Main Warehouse",
"awb_assigned": false,
"waybill": null,
"status": { "code": 0, "label": "Processing" },
"payment_mode": "Pre-paid",
"order_created_at": "2026-10-07T09:12:40+05:30",
"tracking_url": null,
"message": "AWB not assigned yet — the order is still being processed. Retry in a few minutes.",
"request_id": "2d091ff3e7a40d71"
}
{
"success": false,
"statusCode": 404,
"error": "Order \"ORD-3003\" exists on your account but was booked from a different pickup location.",
"code": "ORDER_NOT_AT_PICKUP_LOCATION",
"orderid": "ORD-3003",
"pickup_location": "Main Warehouse",
"pickup_location_on_record": "Chennai Hub",
"request_id": "c364591bd61ce30d"
}
| Field | Type | Description |
|---|---|---|
awb_assigned | boolean | true once WePicks has assigned a waybill. Poll until it flips. |
waybill | string | null | The AWB number. Use it for tracking, labels and NDR actions. |
status.code / status.label | integer / string | Dashboard status of the order, e.g. 0 Processing, 3 Order Created, 5 Ready to Pickup, 7 In Transit, 8 Delivered, 9 NDR, 20 Cancelled, 26 RTO. |
payment_mode | string | COD or Pre-paid as booked. |
order_created_at | string | null | When the order was booked, ISO 8601 in IST (+05:30). |
tracking_url | string | null | Public tracking page for the waybill. Safe to show to your customer. |
Errors
| HTTP | code | When |
|---|---|---|
| 400 | MISSING_PARAMETER | orderid or pickup_location is absent (missing lists which). |
| 401 | MISSING_TOKEN / INVALID_TOKEN | No Authorization header, or the token is unknown. |
| 403 | ACCOUNT_INACTIVE | Your account is deactivated. |
| 404 | PICKUP_LOCATION_NOT_FOUND | No warehouse with that name on your account. Names must match exactly. |
| 404 | ORDER_NOT_AT_PICKUP_LOCATION | The order exists on your account but under another warehouse; pickup_location_on_record names it. |
| 404 | ORDER_NOT_FOUND | No order with that id for that pickup location. |
| 405 | METHOD_NOT_ALLOWED | Only GET and POST are accepted. |
| 429 | RATE_LIMITED | More than 120 calls in a minute on this token. |
Duplicate order ids. If the same order id was booked more than once from the same warehouse (a re-uploaded sheet, for instance), the row that already has a waybill is returned, newest first.
Try it
Package Shipment Creation
AdvancedManifests a shipment directly with the carrier and returns the waybill in the same call. Use this when you need the AWB synchronously and manage pickup locations yourself; for most store integrations Order to Dashboard is simpler and keeps your dashboard as the system of record.
https://api.wepicks.in/api/order-creationHow it behaves
- One call creates one single-piece shipment; a package may contain several items. A waybill is assigned automatically; pass
waybillonly if you pre-allocated one with Fetch WayBill. ordermust be unique per shipment on your account when the waybill is generated by WePicks.payment_modeisCODorPre-paidfor forward shipments,Pickupfor a reverse pickup from the customer, andREPLfor a replacement (forward and reverse in one life cycle).- The pickup location (
pnameand address fields) must match a registered warehouse name exactly; the name is case sensitive. pin,phoneandaddare mandatory in every flow. Ifcountryis omitted, India is assumed; for Bangladesh last-mile pass"BD"and a valid local pin.- Avoid
& # % ;and backslashes in free-text fields; the carrier rejects them. Optional fields you leave out take the defaults on your account.
GST details
seller_gst_tin (GSTIN of the seller) and hsn_code (HSN of the goods; several may be passed when quantity is above one) are mandatory. client_gst_tin, consignee_gst_tin (B2B) and invoice_reference are optional. These belong on the shipment, not on the warehouse. If you prefer to share GST details once with your account manager, they are applied on your account instead.
Reverse pickup and replacement
For a reverse pickup (payment_mode = Pickup) the shipment is collected from the customer and delivered to the return_* address when given, or to the warehouse when not. For a replacement (payment_mode = REPL) the payload is the same as a reverse shipment.
curl --request POST \
--url "https://api.wepicks.in/api/order-creation" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--header "Authorization: Token XXXXXXXXXXXXXXXXXX" \
--data '{
"name": "Asha Nair",
"add": "12, 3rd Cross, Indiranagar",
"pin": "560038",
"city": "Bengaluru",
"state": "Karnataka",
"country": "India",
"phone": "9876543210",
"order": "ORD-1001",
"payment_mode": "COD",
"return_pin": "",
"return_city": "",
"return_phone": "",
"return_add": "",
"return_state": "",
"return_country": "",
"products_desc": "Cotton kurta x2",
"hsn_code": "6204",
"cod_amount": "1499",
"order_date": "2026-10-07",
"total_amount": "1499",
"seller_add": "Plot 7, Guindy Industrial Estate, Chennai",
"seller_name": "Asha Traders",
"seller_inv": "INV-2026-0042",
"quantity": "2",
"waybill": "",
"shipment_width": "25",
"shipment_height": "5",
"weight": "500",
"seller_gst_tin": "33ABCDE1234F1Z5",
"shipping_mode": "Surface",
"address_type": "home",
"pname": "Main Warehouse",
"padd": "Plot 7, Guindy Industrial Estate",
"pcity": "Chennai",
"ppin_code": 600032,
"pcountry": "India",
"pphone": "9000000000"
}'
Response
The carrier's manifest response is returned as-is. The assigned waybill is packages[0].waybill; packages[0].status is "Success" or "Fail" with the reason in remarks.
{
"success": true,
"package_count": 1,
"packages": [{
"status": "Success",
"waybill": "1383541222369",
"refnum": "ORD-1001",
"payment": "COD",
"cod_amount": 1499,
"serviceable": true,
"remarks": [""]
}]
}
Shipment Updation
Corrects details on a shipment after it has been manifested. Updates are accepted while the package is Manifested, In Transit, Pending or Scheduled; they are refused once it is Delivered, Dispatched, Picked Up, Collected, Lost, RTO or DTO.
https://api.wepicks.in/api/order-edit| Field | Required | Type | Description |
|---|---|---|---|
waybill | Yes | string | Shipment to update. |
name | Optional | string | Consignee name. |
add | Optional | string | Consignee address. |
phone | Optional | string | Consignee phone. |
weight | Optional | string | Grams. |
shipment_length / shipment_width / shipment_height | Optional | number | Centimetres. Send as numbers, not strings. |
product_details | Optional | string | Contents description. |
pt | Optional | string | Payment mode: COD or Pre-paid. |
cod | Optional | string | COD amount, when pt is COD. |
curl --request POST \
--url "https://api.wepicks.in/api/order-edit" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--header "Authorization: Token XXXXXXXXXXXXXXXXXX" \
--data '{
"waybill": "1383541222369",
"phone": "9876543210",
"name": "Asha Nair",
"add": "12, 3rd Cross, Indiranagar, Bengaluru",
"product_details": "Cotton kurta x2",
"shipment_length": 30,
"shipment_width": 25,
"shipment_height": 5,
"weight": "500",
"pt": "COD",
"cod": "1499"
}'
The carrier's response is returned as-is.
Cancellation
Cancels a shipment that has not yet moved: allowed while it is Manifested, In Transit, Pending, Open or Scheduled. A cancelled Prepaid or COD package goes to Returned; a cancelled Pickup goes to Cancelled. Orders can also be cancelled from the merchant portal.
https://api.wepicks.in/api/order-cancel| Field | Required | Type | Description |
|---|---|---|---|
waybill | Yes | string | Shipment to cancel. |
cancellation | Yes | string | Must be "true". |
curl --request POST \
--url "https://api.wepicks.in/api/order-cancel" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--header "Authorization: Token XXXXXXXXXXXXXXXXXX" \
--data '{"waybill": "1383541222369", "cancellation": "true"}'
{ "status": true, "remark": "Package cancelled successfully" }
Pin-code Serviceability
Tells you whether a destination pincode is serviced, and for which modes (Pre-paid, COD, pickup, replacement). Check it before you offer shipping options at checkout. An empty delivery_codes list means the pincode is not serviceable.
https://api.wepicks.in/api/Pin-code-Serviceability?filter_codes={pincode}| Parameter | Required | Type | Description |
|---|---|---|---|
filter_codes | Yes | integer | One 6-digit pincode per call. |
curl --request GET \ --url "https://api.wepicks.in/api/Pin-code-Serviceability?filter_codes=560038" \ --header "Authorization: Token XXXXXXXXXXXXXXXXXX" \ --header "Accept: application/json"
{
"delivery_codes": [{
"postal_code": {
"pin": 560038, "district": "Bangalore", "state_code": "KA",
"pre_paid": "Y", "cod": "Y", "pickup": "Y", "repl": "Y", "cash": "Y",
"is_oda": "N", "max_weight": 10, "max_amount": 50000
}
}]
}
?token= is still accepted on this endpoint but deprecated — see Authentication.
Fetch WayBill (bulk pre-allocation)
AdvancedReserves waybill numbers in advance so you can print labels before manifesting and pass the number in Package Shipment Creation. Most integrations do not need this: a waybill is assigned automatically at manifest, and Fetch AWB by Order ID reads it back. Not for multi-piece shipments.
https://api.wepicks.in/api/fetch-waybill?client_name={client}&count={n}| Parameter | Required | Type | Description |
|---|---|---|---|
count | Yes | integer | How many waybills to reserve. Up to 10,000 per call; 50,000 per 5 minutes, after which the IP is throttled for a minute. |
client_name | Optional | string | Your registered client name. |
curl --request GET \ --url "https://api.wepicks.in/api/fetch-waybill?client_name=Asha%20Traders&count=2" \ --header "Authorization: Token XXXXXXXXXXXXXXXXXX" \ --header "Accept: application/json"
"13835412223690,13835412223701"
The body is a JSON string; with count above 1 the numbers are comma-separated. Reserved numbers differ from any list shared at onboarding.
Shipment Tracking
Returns the current status and every scan on a waybill. Works for Pre-paid, COD and Pickup shipments. Limit: 750 requests per 5 minutes per IP. For a customer-facing page you can link to tracking_url from Fetch AWB instead of calling this.
https://api.wepicks.in/api/tracking-order?waybill={waybill}| Parameter | Required | Type | Description |
|---|---|---|---|
waybill | Yes | string | Waybill number to track. |
curl --request GET \ --url "https://api.wepicks.in/api/tracking-order?waybill=1383541222369" \ --header "Authorization: Token XXXXXXXXXXXXXXXXXX" \ --header "Accept: application/json"
{
"ShipmentData": [{
"Shipment": {
"AWB": "1383541222369",
"ReferenceNo": "ORD-1001",
"Status": {
"Status": "In Transit", "StatusType": "UD",
"StatusDateTime": "2026-10-07T14:02:11.000", "StatusLocation": "Bengaluru_Hub (Karnataka)",
"Instructions": "Shipment in transit"
},
"Scans": [{
"ScanDetail": {
"Scan": "Manifested", "StatusCode": "X-UCI",
"ScanDateTime": "2026-10-07T10:15:00.000", "ScannedLocation": "Chennai_Hub (Tamil Nadu)"
}
}]
}
}]
}
Scans[].ScanDetail.StatusCode is what the NDR action rules refer to. ?token= is still accepted here but deprecated.
Calculate Shipping Cost
Returns what your account will be charged for a lane, weight and payment mode — the same formula that debits your wallet, including your account's margins, fuel and COD fee and GST. Treat it as an estimate: the final charge follows the carrier's measured weight. Limit: 40 requests per minute.
https://api.wepicks.in/api/invoice-shipping-charge?md=S&cgm=500&o_pin=600032&d_pin=560038&pt=COD&cod=1499&ss=Delivered| Parameter | Required | Type | Values | Description |
|---|---|---|---|---|
md | Yes | string | S / E | Surface or Express. |
cgm | Yes | integer | grams | Chargeable weight. Volumetric weight (L×W×H / 5000) applies when higher. |
o_pin | Yes | integer | 6 digits | Origin (pickup) pincode. |
d_pin | Yes | integer | 6 digits | Destination pincode. |
pt | Yes | string | COD / Pre-paid | Payment mode. |
cod | Optional | number | INR | Amount to collect; used only when pt is COD. |
ss | Yes | string | Delivered / RTO / DTO | Leg to price: forward delivery, return to origin, or a reverse pickup. |
curl --request GET \ --url "https://api.wepicks.in/api/invoice-shipping-charge?md=S&cgm=500&o_pin=600032&d_pin=560038&pt=COD&cod=1499&ss=Delivered" \ --header "Authorization: Token XXXXXXXXXXXXXXXXXX" \ --header "Accept: application/json"
[{
"charge_DL": 62.00,
"charge_COD": 30.00,
"charge_RTO": 0, "charge_DTO": 0,
"gross_amount": 92.00,
"tax_data": { "CGST": 8.28, "SGST": 8.28, "IGST": 0 },
"total_amount": 108.56,
"zone": "C", "charged_weight": 500
}]
One row is returned. The freight for the requested leg is in charge_DL, charge_RTO or charge_DTO; total_amount is what the wallet is debited.
Generate Shipping Label
Token now enforcedReturns a link to the printable shipping label for a waybill, with the barcode, sort code, consignee and return address laid out. Labels can also be downloaded from the merchant portal.
https://api.wepicks.in/api/package-slip?wbns={waybill}| Parameter | Required | Type | Description |
|---|---|---|---|
wbns | Yes | string | Waybill to print. |
curl --request GET \ --url "https://api.wepicks.in/api/package-slip?wbns=1383541222369" \ --header "Authorization: Token XXXXXXXXXXXXXXXXXX"
The response body is text/plain: a single URL to the rendered label page. Open it in a browser or print it headless.
Breaking change (October 2026). This endpoint used to answer without a token. It now requires one like every other endpoint, because a label carries the consignee's name, phone and address. Add the Authorization header to existing label jobs.
Pickup Request Creation
Asks WePicks to collect packed shipments from one of your warehouses. One open pickup request per warehouse at a time; schedule the next after the first has been completed. Different warehouses can have requests open simultaneously. Pickups can also be scheduled from the portal.
https://api.wepicks.in/api/pickup-request| Field | Required | Type | Description |
|---|---|---|---|
pickup_location | Yes | string | Registered warehouse name, exactly as in the portal. |
pickup_date | Yes | date | YYYY-MM-DD |
pickup_time | Yes | time | hh:mm:ss, 24-hour. |
expected_package_count | Yes | integer | How many packages will be ready. |
curl --request POST \
--url "https://api.wepicks.in/api/pickup-request" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--header "Authorization: Token XXXXXXXXXXXXXXXXXX" \
--data '{
"pickup_location": "Main Warehouse",
"pickup_date": "2026-10-08",
"pickup_time": "14:00:00",
"expected_package_count": "12"
}'
A successful response contains the carrier's pickup_id together with the date, time and warehouse echoed back.
Response encoding quirk. This endpoint returns the carrier's JSON as a JSON-encoded string. Decode the body once to get a string, then decode that string to get the object. Kept for compatibility with existing integrations.
Client Warehouse Creation
Registers a pickup location. Orders can only be booked from registered warehouses, and the name you give here is what pickup_location / warehousename must match on every other call. Our team can also create warehouses for you; integrate this only if you add pickup locations dynamically. Only the fields below are accepted.
https://api.wepicks.in/api/warhouse-creationNote the spelling warhouse in the path; it is part of the API and will not change.
| Field | Required | Type | Description |
|---|---|---|---|
name | Yes | string | Warehouse name. Unique on your account; used as the pickup location everywhere else. |
registered_name | Optional | string | Legal name printed on labels. |
email | Yes | string | Contact email. |
phone | Yes | string | Contact phone for the pickup team. |
address | Yes | string | Street address. |
city / country / pin | Yes | string | Location of the warehouse. |
return_address / return_pin / return_city / return_state / return_country | Optional | string | Where RTO shipments go, if not the warehouse itself. |
curl --request POST \
--url "https://api.wepicks.in/api/warhouse-creation" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--header "Authorization: Token XXXXXXXXXXXXXXXXXX" \
--data '{
"name": "Main Warehouse",
"email": "ops@ashatraders.in",
"phone": "9000000000",
"address": "Plot 7, Guindy Industrial Estate",
"city": "Chennai",
"country": "India",
"pin": "600032",
"return_address": "Plot 7, Guindy Industrial Estate",
"return_pin": "600032",
"return_city": "Chennai",
"return_state": "Tamil Nadu",
"return_country": "India"
}'
On success the carrier echoes the saved fields with "success": true; on failure error explains which field was rejected.
Client Warehouse Updation
Changes the address or contact details of an existing warehouse. The warehouse is identified by name, which cannot itself be changed.
https://api.wepicks.in/api/warhouse-edit| Field | Required | Type | Description |
|---|---|---|---|
name | Yes | string | Existing warehouse name. |
pin | Yes | string | Pincode of the warehouse. |
registered_name | Optional | string | Legal name. |
address | Optional | string | New street address. |
phone | Optional | string | New contact phone. |
curl --request POST \
--url "https://api.wepicks.in/api/warhouse-edit" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--header "Authorization: Token XXXXXXXXXXXXXXXXXX" \
--data '{
"name": "Main Warehouse",
"registered_name": "Asha Traders Pvt Ltd",
"address": "Plot 7A, Guindy Industrial Estate",
"pin": "600032",
"phone": "9000000001"
}'
NDR Package Action
Acts on a shipment that failed delivery (non-delivery report): re-attempt, defer the delivery date, or correct the consignee's details. The call is asynchronous — the carrier accepts the request and returns a request id; the outcome shows up in tracking. Only shipments on your own account can be acted on.
https://api.wepicks.in/api/NDR-api| Field | Required | Type | Description |
|---|---|---|---|
waybill | Yes | string | Shipment in NDR. |
act | Yes | string | RE-ATTEMPT, DEFER_DLV or EDIT_DETAILS. |
deferred_date | DEFER_DLV | date | YYYY-MM-DD, between today and 6 days from the first pending date. |
name / phone / add | EDIT_DETAILS | string | At least one of the three. |
When each action is allowed
- RE-ATTEMPT
- Package pending with StatusCode in EOD-74, EOD-15, EOD-104, EOD-43, EOD-86, EOD-11, EOD-16, EOD-69, EOD-6, ST-108. Moves the order to Reattempt in your dashboard.
- DEFER_DLV
- Package pending with StatusCode in EOD-74, EOD-15, EOD-11, EOD-3, EOD-16, EOD-6, ST-108.
- EDIT_DETAILS
- Package in pending status.
curl --request POST \
--url "https://api.wepicks.in/api/NDR-api" \
--header "Content-Type: application/json" \
--header "Authorization: Token XXXXXXXXXXXXXXXXXX" \
--data '{"waybill": "1383541222369", "act": "RE-ATTEMPT"}'
curl --request POST \
--url "https://api.wepicks.in/api/NDR-api" \
--header "Content-Type: application/json" \
--header "Authorization: Token XXXXXXXXXXXXXXXXXX" \
--data '{"waybill": "1383541222369", "act": "DEFER_DLV", "deferred_date": "2026-10-10"}'
curl --request POST \
--url "https://api.wepicks.in/api/NDR-api" \
--header "Content-Type: application/json" \
--header "Authorization: Token XXXXXXXXXXXXXXXXXX" \
--data '{"waybill": "1383541222369", "act": "EDIT_DETAILS", "phone": "9876543211", "add": "Flat 4B, 12, 3rd Cross, Indiranagar"}'
{
"success": true,
"waybill": "1383541222369",
"act": "RE-ATTEMPT",
"request_id": "UPL8f3a1c2e",
"message": "Request submitted to the courier. This is asynchronous — track the shipment for the outcome."
}
Errors: 400 for a bad act, date or missing fields; 404 when the waybill is not on your account; 502 when the carrier did not accept the request (the carrier's reply is included).
Weight Mismatch Charges
Lists shipments on your account where the carrier's measured weight exceeded the declared weight and an extra charge was applied — the same records as Dispute → Weight Mismatch in the portal. Weights are grams, amounts INR.
https://api.wepicks.in/api/weight-mismatch?page=1&limit=50| Parameter | Required | Type | Description |
|---|---|---|---|
page | Optional | integer | 1-based page number. Default 1. |
limit | Optional | integer | Rows per page, 1–200. Default 50. |
waybill | Optional | string | Restrict to one shipment. |
curl --request GET \ --url "https://api.wepicks.in/api/weight-mismatch?page=1&limit=50" \ --header "Authorization: Token XXXXXXXXXXXXXXXXXX" \ --header "Accept: application/json"
{
"success": true, "total": 1, "page": 1, "limit": 50,
"disputes": [{
"waybill": "1383541222369",
"order_id": "ORD-1001",
"declared_weight_g": 500,
"charged_weight_g": 900,
"original_amount": 108.56,
"revised_amount": 142.78,
"amount_deducted": 34.22,
"processed_at": "2026-10-05 11:42:10"
}]
}
?token= is still accepted here but deprecated.
Changelog
October 2026
- New: Fetch AWB by Order ID — read the waybill WePicks assigned to an order by order id and pickup location.
- Security: every endpoint now verifies the token with a parameterised lookup, scopes lookups to the calling account and returns a uniform JSON error envelope with a
request_id. - Security: per-token rate limit (120/min) and per-IP limit on failed authentication (20/min), with
X-RateLimit-*andRetry-Afterheaders. - Security: Generate Shipping Label now requires the API token.
- Deprecated:
?token=in the query string. Still accepted on the older GET endpoints, flagged with aDeprecationheader; not accepted on new endpoints. - Accepted:
Authorization: BearerandX-Api-Keyas alternatives toAuthorization: Token. - Write endpoints reject non-POST requests with
405instead of acting on an empty body. - This documentation page replaced the previous site; old section links continue to work.