FShip

FShip courier aggregator REST API, authenticated by a static signature header: rates, serviceability, AWB, labels, pickup, tracking, NDR.

FShip is an Indian courier aggregator for B2C and D2C sellers. One account and one integration cover a panel of courier partners (Xpressbees, Delhivery and others), with allocation driven by a priority matrix the seller configures on the FShip panel rather than chosen per request. It is a carrier layer, not a sales channel: there is no catalogue, price or stock surface. FShip publishes a versioned API guide as a downloadable PDF from its own site, which makes it one of the better documented small aggregators, and it runs a named staging environment alongside production.

At a glance

What it is

FShip (fship.in) is an AI positioned e-commerce shipping aggregator for India, selling to B2C and D2C sellers. Alongside plain aggregation it sells custom COD validation, a branded tracking page, bulk order shipping ("Fship Bulkit"), same day and next day delivery, and a post purchase product called PostShip. It is a seller side logistics tool: not a marketplace, not quick commerce, not social commerce.

The structural fact that matters most for an integrator comes from Unicommerce's own integration note: rather than adding each underlying courier separately, the seller adds FShip once and "the system will allocate the correct shipping company through a single Fship added in Uniware based on the priority set on Fship seller panel which is as per the shipping matrices like Rating, Pricing or Delivery time". In other words, carrier selection is a panel configuration, not an API parameter, although the create order call does accept an optional courierId to override it.

Both forward and reverse shipments are supported. Reverse orders carry a quality check flow: the qcParameters field on reverse order creation submits QC validations such as "Take a picture of the item you are returning", structured as question id, question and value triples mapped from a subcategory sheet.

API access

Credentials are issued by the vendor, not self generated. The guide states plainly: "You will be shared Staging and Production API keys/signature from the FShip Team." So the sequence is: open an FShip seller account, ask for API access, receive two keys, and develop against staging first.

  • Environments are cleanly separated: https://capi-qc.fship.in for staging and test, https://capi.fship.in for production, with the same paths on both. Both hosts were confirmed live on 2026-09-22, returning RFC 9110 style 401 Unauthorized JSON to unauthenticated requests.
  • The guide references a Swagger UI at /swagger/index.html on both hosts. As of 2026-09-22 both return 404, so the interactive reference is not currently available and the PDF is the only usable specification.
  • The PDF carries its own revision history, which is a useful signal of where the API is moving: RTO action added 1 February 2024 to handle courier raised exceptions, and shippinglabelbypickupid plus createreverseorder added 25 July 2025.
  • No API version appears in any path, and no deprecation policy is published.
  • No SDK, Postman collection or OpenAPI file is published in any language.
  • Endpoint paths are case insensitive in practice: the guide's tables use lower case (/api/createforwardorder) while its cURL samples use mixed case (/api/RateCalculator, /api/ShipmentSummary).
Warning

Several cURL samples in the guide are wrong and will not run as printed. The courier list sample uses --request POST against an endpoint documented as GET (a live probe confirms GET returns 401 and POST returns 405). The cancel order and register pickup samples point at an internal host name, http://fship-client-api-qc, rather than a public one. The tracking history sample writes the header as signature: bearer XXXX while every other sample omits the word bearer. Trust the "Basic Information" tables over the cURL blocks, and confirm the exact signature header format with FShip before going live.

Authentication

There is no token exchange and no login call. Every request carries a static shared secret.

  1. Obtain the staging and production signature keys from the FShip team.
  2. Send them on every request as the header signature, alongside Content-Type: application/json.

The guide's terminology section defines it directly: "Each FShip API request requires an Authentication Token called as signature, to process your API request in our system", and the protocol section says "Authentication is specified with HTTP Token Authentication" with request bodies "encoded as standard application/json".

No expiry, rotation procedure, scope model or refresh mechanism is published. Multi account handling is one signature key per FShip seller account, per environment. There is no application level delegation across sellers.

curl https://capi.fship.in/api/getallcourier \
  -H 'signature: <SECURITY TOKEN KEY>' \
  -H 'Content-Type: application/json'
curl -X POST https://capi.fship.in/api/trackinghistory \
  -H 'signature: <SECURITY TOKEN KEY>' \
  -H 'Content-Type: application/json' \
  -d '{"waybill":"143455210101006"}'

Documented status codes are the standard set, with 401 Unauthorized: Authentication was incorrect called out explicitly. Note that most calls also carry a status boolean and a response string inside a 200 body, so success must be checked at both levels.

Objects we can read

Almost every read is a POST with a JSON body rather than a GET with query parameters, which is unusual but consistent across the API.

Shipments and tracking

POST /api/trackinghistory with {"waybill": "..."} returns the full scan history for one waybill. One waybill per call.

{
  "status": true,
  "error": false,
  "response": "Scan data available.",
  "summary": {
    "waybill": "143455210101006",
    "apiorderid": 123,
    "orderid": "APX12",
    "fulfilledby": "Xpressbees",
    "statusid": 9,
    "status": "In Transit",
    "lastscandate": "2023-07-23T15:27:27.003",
    "orderedon": "2021-09-01T20:19:09.659Z"
  },
  "trackingdata": [
    {
      "DateandTime": "2021-09-01 20:19:22",
      "Status": "In Transit",
      "Remark": "Shipment InScan from Manifest",
      "Location": "Muradnagar, MODINAGAR, UTTAR PRADESH",
      "shipmentJourney": 0
    },
    {
      "DateandTime": "2021-09-08 20:19:22",
      "Status": "Dispatched",
      "Remark": "Out for delivery",
      "Location": "DEL/GNA, NOIDA, UTTAR PRADESH",
      "shipmentJourney": 0
    }
  ]
}

summary.fulfilledby is the underlying carrier, which is how the aggregator's allocation decision becomes visible. statusid is a numeric status code, but the guide publishes no code table, so map on the status string and treat statusid as opaque until the vocabulary is obtained. Note the two timestamp formats in one response: trackingdata[].DateandTime is a naive YYYY-MM-DD HH:MM:SS string with no zone, while summary.orderedon is ISO 8601 with a Z. Parse per field and assume IST for the naive form.

POST /api/shipmentsummary with {"waybill": "..."} returns the latest status only, for when the full history is not needed. Also one waybill per call.

Rates

POST /api/ratecalculator takes source_Pincode, destination_Pincode, payment_Mode (COD or P), amount, express_Type, shipment_Weight, shipment_Length, shipment_Width, shipment_Height and volumetric_Weight.

{
  "status": true,
  "response": "",
  "shipment_rates": [
    { "courier_name": "Surface Xpressbees", "shipping_charge": 23, "cod_charge": 20.35, "rto_charge": 20.5, "service_mode": "surface" }
  ]
}

The guide warns that these are approximate charges excluding additional charges and GST, so they are a planning figure rather than a billable amount.

Note

payment_Mode takes different forms on different endpoints. Rate calculator documents it as the string COD or P, while forward order creation documents it as the integer 1 for COD and 2 for prepaid. This is a real source of bugs; keep the mapping per endpoint.

Serviceability

POST /api/pincodeserviceability with {"source_Pincode": "...", "destination_Pincode": "..."} returns {source, destination, pickup, reverse, prepaid, cod, status, response}. The four capability fields are typed as strings rather than booleans in the guide, so do not assume true or false.

Couriers

GET /api/getallcourier returns the list of couriers available on the account, each with fields including logoUrl. This is the source for courierId values used to override allocation on order creation.

Locations

Warehouses are created and updated through POST /api/addwarehouse and POST /api/updatewarehouse. The resulting address id is what order creation references as pick_Address_ID and return_Address_ID. No warehouse list endpoint appears in the guide, so address ids must be recorded at creation time.

Orders and order items

There is no standalone order read. An order exists as the products[] array supplied at creation and, afterwards, as the orderid and apiorderid echoed in the tracking summary.

Returns

Reverse shipments are created rather than read, through POST /api/createreverseorder, and are then tracked with the same tracking calls. Serviceability exposes a separate reverse flag per pincode pair.

Payments and settlements

Not exposed. cod_Amount is carried on the order and COD and RTO charges appear in the rate estimate, but there is no wallet, invoice, statement or COD remittance endpoint.

Products, listings, inventory, customers

Products exist only as order lines. Listings and inventory do not exist, as expected for a carrier. Customer data is present only as the consignee fields on an order and is not read back through any documented call.

Writing back: listings, price and stock

Not applicable, this is a carrier aggregator. FShip holds no catalogue, no price list and no stock. The write path is the shipment lifecycle.

Create forward order. POST /api/createforwardorder, single order per call (the guide directs bulk work to the dashboard's Bulk Order option rather than the API). Required fields are customer_Name, customer_Mobile (10 digits), customer_Address, customer_PinCode, payment_Mode (1 COD, 2 prepaid), express_Type (air or surface), total_Amount, cod_Amount when COD, shipment_Weight in kg, shipment_Length, shipment_Width and shipment_Height in cm, and pick_Address_ID. Optional fields include customer_Emailid, landMark, customer_Address_Type (default Home), customer_City, orderId (the seller's own reference), invoice_Number, is_Ndd for next day delivery, order_Amount, tax_Amount, extra_Charges, volumetric_Weight, latitude, longitude, return_Address_ID and courierId. Each products[] entry carries productId, productName, unitPrice, quantity, productCategory, hsnCode, sku, taxRate and productDiscount.

{
  "route_code": "string",
  "order_status": "string",
  "apiorderid": 0,
  "waybill": "string",
  "status": true,
  "response": "string"
}

The AWB (waybill) comes back on the create call, so there is no separate AWB assignment step. apiorderid is FShip's internal id and is the key several other calls take instead of the waybill.

Create reverse order. POST /api/createreverseorder, added July 2025, with the same general shape plus a qcParameters array of {questionId, question, value} for return quality checks.

Cancel. POST /api/cancelorder. The guide restricts it: "The order should be in Booked or Manifested state only, to get cancelled."

Register pickup. POST /api/registerpickup with {"waybills": ["..."]}. This one is genuinely batched, and returns apipickuporderids[] of {pickupOrderId, waybills[]}. Note the guide's parameter definitions under this endpoint describe apiorderid and courierId while the sample body and cURL both send waybills, a contradiction to resolve with support.

Labels. POST /api/shippinglabel accepts comma separated multiple waybill numbers to fetch several labels in one call. POST /api/shippinglabelbypickupid, added July 2025, fetches labels for a whole registered pickup instead.

NDR and RTO action. POST /api/reattemptorder, allowed "only when Courier Company raises Exception". Supported action types are re-attempt, change-address, change-phone and rto. The body carries apiorderid, action, reattempt_date, contact_name, complete_address, landmark, mobilenumber and remarks.

Webhooks and notifications

None. The FShip API guide contains no webhook, callback or push notification mechanism of any kind: no subscription endpoint, no event catalogue, no signature scheme, no retry policy. Tracking is pull only.

Unicommerce's integration note confirms the same picture indirectly, describing tracking as something Uniware fetches rather than receives.

Recommended polling, given the constraints:

  • Keep a local table of open waybills from the create order responses, since there is no list endpoint to recover them from.
  • Poll POST /api/shipmentsummary per open waybill on a slow loop to detect change cheaply, and call POST /api/trackinghistory only when the summary status has moved, to fetch the new scans. Both are one waybill per call, so this two tier approach is what keeps the call volume sane.
  • Hourly per open shipment is a defensible starting cadence for surface shipments. With no published rate limit, keep concurrency low and back off on any 5xx.
  • Watch for an exception status, since that is the precondition for the NDR and RTO action call.

Rate limits and pagination

Neither is published. The guide lists HTTP status code meanings, including 401, but no 429, no quota headers, no per key ceiling and no burst allowance. There is no pagination model anywhere, because there is no list endpoint that could need one: couriers return a bounded array, and everything else is keyed on a waybill or an order id.

Practical consequences:

  • No backfill route. Record apiorderid, waybill and the seller orderId at creation, because history cannot be enumerated later.
  • Batch where the API allows it: shippinglabel takes comma separated waybills, registerpickup takes a waybill array, and shippinglabelbypickupid collapses a whole pickup into one call. Everything else is strictly one at a time.
  • Bulk order creation is not available through the API at all; the guide routes it to the dashboard. A high volume seller will be making one HTTP call per order.
  • Serialise per signature key and treat unspecified limits as strict until FShip confirms otherwise.

Mapping to the unified model

Gaps and open questions

  • No webhooks at all, and one waybill per tracking call, which makes status a polling cost that scales linearly with open shipments.
  • No rate limits, quota headers or throttling response documented.
  • The statusid numeric status vocabulary is used in responses but never published.
  • No bulk order creation through the API; the guide routes bulk work to the dashboard.
  • The registerpickup documentation contradicts itself, defining apiorderid and courierId while the sample sends a waybills array.
  • The signature header format is ambiguous: one sample prefixes it with bearer, the rest do not.
  • The Swagger UI referenced in the guide returns 404 on both hosts as of 2026-09-22, so the PDF cannot be cross checked against a live specification.
  • No proof of delivery artefact (signature, photograph) is mentioned anywhere, even though reverse orders capture QC photographs on the way back.
  • No COD remittance data, and rate figures explicitly exclude GST and additional charges, so billed freight cannot be reconciled through the API.
  • No warehouse list endpoint, so address ids are unrecoverable if not stored at creation.

Sources

  • FShip API guide (PDF), version 1.2.3.3 dated 25 July 2025, read end to end on 2026-09-22. Note the copy at api.fship.in/upload/documents/api_document.pdf returns 404; the app. host is the working one
  • Unicommerce support: Integration with FShip for the allocation model, the credential issuance route, and confirmation that forward and reverse are both supported and that FShip supplies the label PDF while Uniware supplies the manifest
  • fship.in for the product line and positioning
  • Live probes on 2026-09-22: capi.fship.in and capi-qc.fship.in both return RFC 9110 401 Unauthorized JSON to an unauthenticated GET /api/getallcourier and 405 to a POST, and /swagger/index.html returns 404 on both hosts