Skip to main content
QCSQuick Courier ServiceQCS — Quick Courier Service, home

Developers

Endpoint reference

Generated from the v1 schemas: every endpoint, its scope, its validated fields and a cURL example.

Merchant developers9 min readGenerated from the live v1 schemasPrintable handbook

Every version 1 endpoint, with the scope it needs, the fields it validates and a runnable example. The field tables and the examples on this page are generated from the same schema constants the API validates against, so they cannot drift from the live contract.

Reference

GET /api/v1/me

Confirms the key works and reports the merchant, the environment and the scopes it carries.

Scope
rates:read — Quote a delivery charge
Idempotency
Not applicable. This call changes nothing.
URL
https://qcs.com.pk/api/v1/me
cURL
curl -sS -X GET 'https://qcs.com.pk/api/v1/me' \
  -H 'Authorization: Bearer qcs_live_your_key_id.qcss_your_key_secret'

GET /api/v1/cities

Lists the cities QCS delivers into, with the cityId every booking needs.

Scope
zones:read — Look up cities, service areas and addresses
Idempotency
Not applicable. This call changes nothing.
URL
https://qcs.com.pk/api/v1/cities
cURL
curl -sS -X GET 'https://qcs.com.pk/api/v1/cities' \
  -H 'Authorization: Bearer qcs_live_your_key_id.qcss_your_key_secret'

GET /api/v1/zones

Lists the service areas inside a city, including which are extended area.

Scope
zones:read — Look up cities, service areas and addresses
Idempotency
Not applicable. This call changes nothing.
URL
https://qcs.com.pk/api/v1/zones?cityId=<cityId>
cURL
curl -sS -X GET 'https://qcs.com.pk/api/v1/zones?cityId=<cityId>' \
  -H 'Authorization: Bearer qcs_live_your_key_id.qcss_your_key_secret'

POST /api/v1/zones

Places one address in a service area before you book, so you never book into a zone QCS does not serve.

Scope
zones:read — Look up cities, service areas and addresses
Idempotency
Not applicable. This call changes nothing.
URL
https://qcs.com.pk/api/v1/zones
Request body
{
  "cityId": "<cityId>",
  "addressLine": "House 14, Street 7, Block C, Johar Town",
  "area": "Johar Town"
}
cURL
curl -sS -X POST 'https://qcs.com.pk/api/v1/zones' \
  -H 'Authorization: Bearer qcs_live_your_key_id.qcss_your_key_secret' \
  -H 'Content-Type: application/json' \
  -d '{
  "cityId": "<cityId>",
  "addressLine": "House 14, Street 7, Block C, Johar Town",
  "area": "Johar Town"
}'

POST /api/v1/addresses/lookup

Suggests addresses for a partial query and returns a pin for each one.

Scope
zones:read — Look up cities, service areas and addresses
Idempotency
Not applicable. This call changes nothing.
URL
https://qcs.com.pk/api/v1/addresses/lookup
Request body
{
  "cityId": "<cityId>",
  "query": "Johar Town block C"
}
cURL
curl -sS -X POST 'https://qcs.com.pk/api/v1/addresses/lookup' \
  -H 'Authorization: Bearer qcs_live_your_key_id.qcss_your_key_secret' \
  -H 'Content-Type: application/json' \
  -d '{
  "cityId": "<cityId>",
  "query": "Johar Town block C"
}'

Pricing

POST /api/v1/rates/quote

Returns the exact charge, the chargeable weight and the weight basis, from the same engine that bills the parcel.

Scope
rates:read — Quote a delivery charge
Idempotency
Not applicable. This call changes nothing.
URL
https://qcs.com.pk/api/v1/rates/quote
POST /api/v1/rates/quote fields
FieldRequiredAccepts
weightKgRequired0.05 to 200 kg, three decimal places
lengthCmOptional1 to 500 cm, one decimal place. All three dimensions or none.
widthCmOptional1 to 500 cm, one decimal place. All three dimensions or none.
heightCmOptional1 to 500 cm, one decimal place. All three dimensions or none.
serviceTypeOptionalOne of STANDARD, EXPRESS_SAME_DAY. Defaults to STANDARD.
cityIdRequiredA city id from GET /api/v1/cities.
addressLineOptionalThe delivery address. Without it, or without coordinates, the city default zone is used.
areaOptionalText, up to 120 characters.
latOptionalLatitude, sent with lng, to place the address exactly.
lngOptionalLongitude, sent with lat, to place the address exactly.
codAmountRupeesOptionalwhole rupees, up to 500000
declaredValueRupeesOptionalwhole rupees, up to 1000000
Request body
{
  "weightKg": "1.25",
  "lengthCm": "30",
  "widthCm": "20",
  "heightCm": "10",
  "serviceType": "STANDARD",
  "cityId": "<cityId from /api/v1/cities>",
  "addressLine": "House 14, Street 7, Block C, Johar Town",
  "area": "Johar Town",
  "codAmountRupees": "3500",
  "declaredValueRupees": "3500"
}
cURL
curl -sS -X POST 'https://qcs.com.pk/api/v1/rates/quote' \
  -H 'Authorization: Bearer qcs_live_your_key_id.qcss_your_key_secret' \
  -H 'Content-Type: application/json' \
  -d '{
  "weightKg": "1.25",
  "lengthCm": "30",
  "widthCm": "20",
  "heightCm": "10",
  "serviceType": "STANDARD",
  "cityId": "<cityId from /api/v1/cities>",
  "addressLine": "House 14, Street 7, Block C, Johar Town",
  "area": "Johar Town",
  "codAmountRupees": "3500",
  "declaredValueRupees": "3500"
}'

Orders

POST /api/v1/orders

Books one parcel and freezes its charge. Returns the QCS tracking number.

Scope
orders:write — Book orders, singly or in bulk
Idempotency
Required. Send idempotency-key so a retry after a timeout cannot double-book.
URL
https://qcs.com.pk/api/v1/orders
POST /api/v1/orders fields
FieldRequiredAccepts
merchantOrderRefOptionalYour own reference, up to 64 characters of letters, digits, dots, dashes, slashes and underscores. Unique per merchant.
consigneeNameRequiredText, up to 120 characters.
consigneePhoneRequiredA Pakistani mobile number, such as 03001234567.
consigneeAltPhoneOptionalA second Pakistani mobile number.
consigneeEmailOptionalAn email address.
addressLineRequiredText, 10 to 320 characters.
areaOptionalText, up to 120 characters.
landmarkOptionalText, up to 160 characters.
cityIdRequiredA city id from GET /api/v1/cities.
latOptionalLatitude. Send it together with lng or not at all.
lngOptionalLongitude. Send it together with lat or not at all.
pieceCountOptionalWhole number from 1 to 50. Defaults to 1.
weightKgRequired0.05 to 200 kg, three decimal places
lengthCmOptional1 to 500 cm, one decimal place. All three dimensions or none.
widthCmOptional1 to 500 cm, one decimal place. All three dimensions or none.
heightCmOptional1 to 500 cm, one decimal place. All three dimensions or none.
itemsDescriptionOptionalText, up to 320 characters.
declaredValueRupeesOptionalwhole rupees, up to 1000000
serviceTypeOptionalOne of STANDARD, EXPRESS_SAME_DAY. Defaults to STANDARD.
isFragileOptionalBoolean. Defaults to false.
allowToOpenOptionalBoolean. Defaults to false.
isExchangeOptionalBoolean. Defaults to false. An exchange parcel must carry no COD amount.
specialInstructionsOptionalText for the rider, printed on the label.
codAmountRupeesRequiredwhole rupees, up to 500000. Send 0 for a prepaid parcel.
Request body
{
  "merchantOrderRef": "SHOP-1042",
  "consigneeName": "Hira Shahid",
  "consigneePhone": "03001234567",
  "addressLine": "House 14, Street 7, Block C, Johar Town",
  "area": "Johar Town",
  "cityId": "<cityId from /api/v1/cities>",
  "pieceCount": 1,
  "weightKg": "1.25",
  "lengthCm": "30",
  "widthCm": "20",
  "heightCm": "10",
  "itemsDescription": "Two kurtas",
  "declaredValueRupees": "3500",
  "serviceType": "STANDARD",
  "allowToOpen": false,
  "specialInstructions": "Call before arriving",
  "codAmountRupees": "3500"
}
cURL
curl -sS -X POST 'https://qcs.com.pk/api/v1/orders' \
  -H 'Authorization: Bearer qcs_live_your_key_id.qcss_your_key_secret' \
  -H 'Content-Type: application/json' \
  -H 'idempotency-key: your-own-unique-key' \
  -d '{
  "merchantOrderRef": "SHOP-1042",
  "consigneeName": "Hira Shahid",
  "consigneePhone": "03001234567",
  "addressLine": "House 14, Street 7, Block C, Johar Town",
  "area": "Johar Town",
  "cityId": "<cityId from /api/v1/cities>",
  "pieceCount": 1,
  "weightKg": "1.25",
  "lengthCm": "30",
  "widthCm": "20",
  "heightCm": "10",
  "itemsDescription": "Two kurtas",
  "declaredValueRupees": "3500",
  "serviceType": "STANDARD",
  "allowToOpen": false,
  "specialInstructions": "Call before arriving",
  "codAmountRupees": "3500"
}'

POST /api/v1/orders/bulk

Books up to two hundred parcels in one call. Every accepted row returns a tracking number and every rejected row returns its reason.

Scope
orders:write — Book orders, singly or in bulk
Idempotency
Required. Send idempotency-key so a retry after a timeout cannot double-book.
URL
https://qcs.com.pk/api/v1/orders/bulk
POST /api/v1/orders/bulk fields
FieldRequiredAccepts
ordersRequiredAn array of order objects with the fields above, from 1 to 200 entries. Every entry should carry merchantOrderRef so a partial failure is unambiguous.
Request body
{
  "orders": [
    {
      "merchantOrderRef": "SHOP-1042",
      "consigneeName": "Hira Shahid",
      "consigneePhone": "03001234567",
      "addressLine": "House 14, Street 7, Block C, Johar Town",
      "area": "Johar Town",
      "cityId": "<cityId from /api/v1/cities>",
      "pieceCount": 1,
      "weightKg": "1.25",
      "lengthCm": "30",
      "widthCm": "20",
      "heightCm": "10",
      "itemsDescription": "Two kurtas",
      "declaredValueRupees": "3500",
      "serviceType": "STANDARD",
      "allowToOpen": false,
      "specialInstructions": "Call before arriving",
      "codAmountRupees": "3500"
    }
  ]
}
cURL
curl -sS -X POST 'https://qcs.com.pk/api/v1/orders/bulk' \
  -H 'Authorization: Bearer qcs_live_your_key_id.qcss_your_key_secret' \
  -H 'Content-Type: application/json' \
  -H 'idempotency-key: your-own-unique-key' \
  -d '{
  "orders": [
    {
      "merchantOrderRef": "SHOP-1042",
      "consigneeName": "Hira Shahid",
      "consigneePhone": "03001234567",
      "addressLine": "House 14, Street 7, Block C, Johar Town",
      "area": "Johar Town",
      "cityId": "<cityId from /api/v1/cities>",
      "pieceCount": 1,
      "weightKg": "1.25",
      "lengthCm": "30",
      "widthCm": "20",
      "heightCm": "10",
      "itemsDescription": "Two kurtas",
      "declaredValueRupees": "3500",
      "serviceType": "STANDARD",
      "allowToOpen": false,
      "specialInstructions": "Call before arriving",
      "codAmountRupees": "3500"
    }
  ]
}'

GET /api/v1/orders

Lists your parcels newest first, with cursor pagination and status filters.

Scope
orders:read — Read orders and their status
Idempotency
Not applicable. This call changes nothing.
URL
https://qcs.com.pk/api/v1/orders?status=OUT_FOR_DELIVERY&limit=50
GET /api/v1/orders fields
FieldRequiredAccepts
cursorOptionalThe cursor returned by the previous page.
limitOptionalWhole number from 1 to 200. Defaults to 50.
statusOptionalOne of DRAFT, BOOKED, PICKUP_REQUESTED, PICKUP_ASSIGNED, PICKED_UP, PICKUP_FAILED, AT_WAREHOUSE, DISPATCH_ASSIGNED, OUT_FOR_DELIVERY, DELIVERED, ON_HOLD, REFUSED, RETURNING_TO_WAREHOUSE, CANCELLED, RTS_ASSIGNED, RTS_IN_TRANSIT, RTS_DELIVERED, LOST, DAMAGED.
fromOptionalA calendar date as YYYY-MM-DD, inclusive.
toOptionalA calendar date as YYYY-MM-DD, inclusive.
merchantOrderRefOptionalYour own reference, matched exactly.
cURL
curl -sS -X GET 'https://qcs.com.pk/api/v1/orders?status=OUT_FOR_DELIVERY&limit=50' \
  -H 'Authorization: Bearer qcs_live_your_key_id.qcss_your_key_secret'

GET /api/v1/orders/{orderRef}

Reads one parcel and its full status history.

Scope
orders:read — Read orders and their status
Idempotency
Not applicable. This call changes nothing.
URL
https://qcs.com.pk/api/v1/orders/{orderRef}

orderRef accepts the QCS tracking number or your own order reference.

cURL
curl -sS -X GET 'https://qcs.com.pk/api/v1/orders/{orderRef}' \
  -H 'Authorization: Bearer qcs_live_your_key_id.qcss_your_key_secret'

POST /api/v1/orders/{orderRef}/cancel

Cancels a parcel that has not been collected yet.

Scope
orders:cancel — Cancel a booked order before pickup
Idempotency
Optional but recommended. Send idempotency-key to make a retry safe.
URL
https://qcs.com.pk/api/v1/orders/{orderRef}/cancel

orderRef accepts the QCS tracking number or your own order reference.

POST /api/v1/orders/{orderRef}/cancel fields
FieldRequiredAccepts
reasonCodeRequiredA cancellation reason code. The active list is on the parcel screen.
reasonTextOptionalFree text explaining the cancellation.
Request body
{
  "reasonCode": "CUST_CANCELLED",
  "reasonText": "Customer changed their mind"
}
cURL
curl -sS -X POST 'https://qcs.com.pk/api/v1/orders/{orderRef}/cancel' \
  -H 'Authorization: Bearer qcs_live_your_key_id.qcss_your_key_secret' \
  -H 'Content-Type: application/json' \
  -H 'idempotency-key: your-own-unique-key' \
  -d '{
  "reasonCode": "CUST_CANCELLED",
  "reasonText": "Customer changed their mind"
}'

GET /api/v1/tracking/{trackingNumber}

Returns the customer-facing timeline for one tracking number.

Scope
tracking:read — Read the public tracking timeline
Idempotency
Not applicable. This call changes nothing.
URL
https://qcs.com.pk/api/v1/tracking/{trackingNumber}
cURL
curl -sS -X GET 'https://qcs.com.pk/api/v1/tracking/{trackingNumber}' \
  -H 'Authorization: Bearer qcs_live_your_key_id.qcss_your_key_secret'

Documents

POST /api/v1/labels

Queues a label batch and returns a document id. Poll the document, then fetch the PDF.

Scope
labels:read — Fetch label and load sheet PDFs
Idempotency
Optional but recommended. Send idempotency-key to make a retry safe.
URL
https://qcs.com.pk/api/v1/labels
POST /api/v1/labels fields
FieldRequiredAccepts
orderRefsRequiredAn array of tracking numbers or your own references, from 1 to 500 entries.
labelPaperOptionalOne of THERMAL, SHEET. Defaults to THERMAL.
Request body
{
  "orderRefs": ["QCS-250105-000123"],
  "labelPaper": "THERMAL"
}
cURL
curl -sS -X POST 'https://qcs.com.pk/api/v1/labels' \
  -H 'Authorization: Bearer qcs_live_your_key_id.qcss_your_key_secret' \
  -H 'Content-Type: application/json' \
  -H 'idempotency-key: your-own-unique-key' \
  -d '{
  "orderRefs": ["QCS-250105-000123"],
  "labelPaper": "THERMAL"
}'

GET /api/v1/documents/{documentId}

Reports whether a queued document has finished rendering.

Scope
labels:read — Fetch label and load sheet PDFs
Idempotency
Not applicable. This call changes nothing.
URL
https://qcs.com.pk/api/v1/documents/{documentId}
cURL
curl -sS -X GET 'https://qcs.com.pk/api/v1/documents/{documentId}' \
  -H 'Authorization: Bearer qcs_live_your_key_id.qcss_your_key_secret'

GET /api/v1/documents/{documentId}/file

Streams the rendered PDF.

Scope
labels:read — Fetch label and load sheet PDFs
Idempotency
Not applicable. This call changes nothing.
URL
https://qcs.com.pk/api/v1/documents/{documentId}/file
cURL
curl -sS -X GET 'https://qcs.com.pk/api/v1/documents/{documentId}/file' \
  -H 'Authorization: Bearer qcs_live_your_key_id.qcss_your_key_secret'

Pickups

POST /api/v1/pickups

Forwards booked parcels for collection. Send the references, or forwardEverything to send every booked parcel.

Scope
pickups:write — Raise a pickup request
Idempotency
Required. Send idempotency-key so a retry after a timeout cannot double-book.
URL
https://qcs.com.pk/api/v1/pickups
POST /api/v1/pickups fields
FieldRequiredAccepts
orderRefsOptionalAn array of references to forward, up to 500 entries.
forwardEverythingOptionalBoolean. True forwards every booked parcel on your account instead of a named list.
requestedDateOptionalA calendar date as YYYY-MM-DD for the collection.
noteOptionalA short note for the pickup desk and the rider.
Request body
{
  "orderRefs": ["QCS-250105-000123"],
  "forwardEverything": false,
  "note": "Ready after 14:00"
}
cURL
curl -sS -X POST 'https://qcs.com.pk/api/v1/pickups' \
  -H 'Authorization: Bearer qcs_live_your_key_id.qcss_your_key_secret' \
  -H 'Content-Type: application/json' \
  -H 'idempotency-key: your-own-unique-key' \
  -d '{
  "orderRefs": ["QCS-250105-000123"],
  "forwardEverything": false,
  "note": "Ready after 14:00"
}'

GET /api/v1/pickups

Lists your pickup requests and the rider assigned to each one.

Scope
pickups:read — Read pickup requests
Idempotency
Not applicable. This call changes nothing.
URL
https://qcs.com.pk/api/v1/pickups?limit=20
cURL
curl -sS -X GET 'https://qcs.com.pk/api/v1/pickups?limit=20' \
  -H 'Authorization: Bearer qcs_live_your_key_id.qcss_your_key_secret'

Finance

GET /api/v1/statements/cod

Returns the COD ledger: cash collected, charges cut and the running balance QCS owes you.

Scope
statements:read — Read the COD ledger and payout statements
Idempotency
Not applicable. This call changes nothing.
URL
https://qcs.com.pk/api/v1/statements/cod?from=2026-01-01&to=2026-01-31&limit=100
GET /api/v1/statements/cod fields
FieldRequiredAccepts
fromOptionalA calendar date as YYYY-MM-DD, inclusive.
toOptionalA calendar date as YYYY-MM-DD, inclusive.
cursorOptionalThe cursor returned by the previous page.
limitOptionalWhole number from 1 to 200. Defaults to 50.
cURL
curl -sS -X GET 'https://qcs.com.pk/api/v1/statements/cod?from=2026-01-01&to=2026-01-31&limit=100' \
  -H 'Authorization: Bearer qcs_live_your_key_id.qcss_your_key_secret'

Webhooks

GET /api/v1/webhooks

Lists your webhook endpoints, the events each covers and the signing scheme.

Scope
webhooks:read — Read webhook endpoints and the delivery log
Idempotency
Not applicable. This call changes nothing.
URL
https://qcs.com.pk/api/v1/webhooks
cURL
curl -sS -X GET 'https://qcs.com.pk/api/v1/webhooks' \
  -H 'Authorization: Bearer qcs_live_your_key_id.qcss_your_key_secret'

POST /api/v1/webhooks

Creates or edits an endpoint. The signing secret is returned exactly once, on creation or rotation.

Scope
webhooks:manage — Create, edit and replay webhook endpoints
Idempotency
Optional but recommended. Send idempotency-key to make a retry safe.
URL
https://qcs.com.pk/api/v1/webhooks
POST /api/v1/webhooks fields
FieldRequiredAccepts
subscriptionIdOptionalOmit to create an endpoint, send it to edit one.
targetUrlRequiredAn https URL on a public host. Private and loopback addresses are refused.
eventsRequiredAn array of one or more of order.booked, order.pickup_requested, order.pickup_assigned, order.picked_up, order.pickup_failed, order.at_warehouse, order.out_for_delivery, order.delivered, order.on_hold, order.refused, order.returning, order.cancelled, order.returned_to_shipper, order.lost, order.damaged, order.status_changed.
isActiveOptionalBoolean. Defaults to false on create.
rotateSecretOptionalBoolean. True returns a new signing secret, exactly once.
Request body
{
  "targetUrl": "https://your-shop.example/qcs/webhook",
  "events": ["order.picked_up", "order.delivered"],
  "isActive": true
}
cURL
curl -sS -X POST 'https://qcs.com.pk/api/v1/webhooks' \
  -H 'Authorization: Bearer qcs_live_your_key_id.qcss_your_key_secret' \
  -H 'Content-Type: application/json' \
  -H 'idempotency-key: your-own-unique-key' \
  -d '{
  "targetUrl": "https://your-shop.example/qcs/webhook",
  "events": ["order.picked_up", "order.delivered"],
  "isActive": true
}'

GET /api/v1/webhooks/deliveries

Lists delivery attempts with the HTTP status and the response body QCS saw.

Scope
webhooks:read — Read webhook endpoints and the delivery log
Idempotency
Not applicable. This call changes nothing.
URL
https://qcs.com.pk/api/v1/webhooks/deliveries?status=FAILED&limit=50
cURL
curl -sS -X GET 'https://qcs.com.pk/api/v1/webhooks/deliveries?status=FAILED&limit=50' \
  -H 'Authorization: Bearer qcs_live_your_key_id.qcss_your_key_secret'

POST /api/v1/webhooks/deliveries/{deliveryId}/replay

Queues one delivery for another attempt with a fresh signature.

Scope
webhooks:manage — Create, edit and replay webhook endpoints
Idempotency
Not applicable. This call changes nothing.
URL
https://qcs.com.pk/api/v1/webhooks/deliveries/{deliveryId}/replay
cURL
curl -sS -X POST 'https://qcs.com.pk/api/v1/webhooks/deliveries/{deliveryId}/replay' \
  -H 'Authorization: Bearer qcs_live_your_key_id.qcss_your_key_secret'

Next

Endpoint reference — QCS documentation · QCS