CD CargoDash Hub

API Reference

Documentation

The CargoDash Hub REST API for wallet balance, metered billing, transaction history and recharge. Every endpoint is scoped to the calling organisation, derived from the bearer token — there is no tenant parameter to send, and none is accepted.

Base URL https://hub-api.cargodash.in/api/v1 Auth Bearer <token> Format JSON (UTF-8)

Overview

CargoDash Hub is the wallet and billing control plane behind CargoDash services. Partners use it to check a prepaid balance, report metered consumption, review transaction history and top up.

All requests and responses are JSON over HTTPS. A successful response carries success, message and data; list endpoints add pagination.

Tenancy is implicit. Your organisation is read from the token on every call. There is no customer or organisation parameter, so one partner can never address another's wallet.

Authentication

Exchange your credentials for a bearer token, then send it on every subsequent request.

POST /api/v1/login Public

Request

curl -X POST 'https://hub-api.cargodash.in/api/v1/login' \
  -H 'Content-Type: application/json' \
  -d '{
        "username": "YOUR_USERNAME",
        "password": "YOUR_PASSWORD"
      }'

Response 200 OK

{
  "success":   true,
  "token":     "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9....",
  "expiry":    "2026-09-13 11:13:41",
  "expiresIn": 864000
}

Using the token

Send it as a bearer token on every call:

Authorization: Bearer <token>
Store and reuse the token. It is valid for 10 days (expiresIn: 864000 seconds). Do not log in before each request — the login endpoint is rate limited. On 401, log in again and retry.

Roles & access

Every route is guarded by role. Your credentials determine which of the three you hold.

Role Name Scope
1 Super Admin Platform-wide administration, dashboards and revenue reporting
2 Customer Admin Manages their own organisation, users, clients and wallet
3 Customer User Operational access to wallet and service endpoints

A call made with an insufficient role returns 403.

Wallet balance

Returns your current balance. Takes no parameters — the wallet is resolved from your token.

GET /api/v1/accounts/balance Bearer

Request

curl -X GET 'https://hub-api.cargodash.in/api/v1/accounts/balance' \
  -H 'Authorization: Bearer YOUR_TOKEN'

Response 200 OK

{
  "success": true,
  "message": "Wallet balance",
  "data": {
    "balance":  "1250.00",
    "currency": "INR",
    "status":   "Active",
    "as_of":    "2026-09-01T04:52:31.000Z"
  }
}

Fields

Field Type Description
balance string Current available balance
currency string ISO currency code
status string Active, Inactive or Frozen
as_of string ISO-8601 UTC timestamp of the last wallet movement, or null if never used

List transactions

Your wallet transaction history, newest first.

GET /api/v1/accounts/transactions Bearer

Query parameters

Parameter Type Description
page integer Optional Page number, default 1
limit integer Optional Rows per page, 1–100, default 25
from date Optional Start date YYYY-MM-DD, inclusive
to date Optional End date YYYY-MM-DD, inclusive
transaction_type string Optional Credit or Debit
category string Optional Recharge, Service_Usage, Adjustment, Refund or Penalty
client_reference string Optional Look up one specific transaction you created

Request

curl -X GET 'https://hub-api.cargodash.in/api/v1/accounts/transactions?page=1&limit=25&from=2026-09-01&to=2026-09-30' \
  -H 'Authorization: Bearer YOUR_TOKEN'

# Or look up a single transaction by your own reference
curl -X GET 'https://hub-api.cargodash.in/api/v1/accounts/transactions?client_reference=ORDER-8891' \
  -H 'Authorization: Bearer YOUR_TOKEN'

Response 200 OK

{
  "success": true,
  "message": "Wallet transactions",
  "data": [
    {
      "transaction_id":   "TXN228083272651",
      "client_reference": "ORDER-8891",
      "transaction_type": "Debit",
      "category":         "Service_Usage",
      "amount":           "30.00",
      "balance_after":    "70.00",
      "currency":         "INR",
      "description":      "AWB lookup",
      "unit_consumed":    5,
      "status":           "Success",
      "processed_at":     "2026-09-03T11:13:41.000Z"
    }
  ],
  "pagination": {
    "page": 1, "limit": 25, "total": 141, "total_pages": 6
  }
}
This is the partner-facing history. It is deliberately separate from the internal dashboard endpoint, which returns PII and raw upstream payloads.

Adjust balance

Debits your wallet for consumption, or credits a refund. You state what was consumed, how much of it, and in which direction — the price is resolved server-side.

POST /api/v1/accounts/adjust-balance Bearer
Pricing is server-side. An amount field is rejected with 400. The charge is computed from the catalogue and your negotiated rate, so a caller cannot underbill a debit or mint balance on a credit.

Body parameters

Parameter Type Description
client_reference string Required Your own unique id for this operation, max 100 characters. See Idempotency.
sub_service_id string Required The catalogue sub-service that was consumed
quantity integer Required Whole number of units consumed, minimum 1. Fractional values are rejected.
transaction_type string Required Debit to deduct, Credit to refund
parent_transaction_id string Credit only The charge this refund reverses. Required when transaction_type is Credit; it caps the refund amount.
description string Optional Free text shown on the transaction
service_details object Optional What the call actually did — the identifier looked up, what the upstream returned. Stored on the service log.

Request — debit for usage

curl -X POST 'https://hub-api.cargodash.in/api/v1/accounts/adjust-balance' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
        "client_reference": "ORDER-8891",
        "sub_service_id":   "12",
        "quantity":         5,
        "transaction_type": "Debit",
        "description":      "AWB lookup"
      }'

Request — credit a refund

curl -X POST 'https://hub-api.cargodash.in/api/v1/accounts/adjust-balance' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
        "client_reference":      "REFUND-8891",
        "sub_service_id":        "12",
        "quantity":              5,
        "transaction_type":      "Credit",
        "parent_transaction_id": "TXN228083272651",
        "description":           "Refund for failed lookup"
      }'

Response 201 Created — new transaction

{
  "success": true,
  "message": "Wallet updated",
  "data": {
    "transaction_id":   "TXN228083272651",
    "client_reference": "ORDER-8891",
    "transaction_type": "Debit",
    "amount":           "30.00",
    "balance_after":    "70.00",
    "currency":         "INR"
  }
}

Response 402 Payment Required — insufficient balance

Nothing was charged. Top up and retry.

{
  "success": false,
  "message": "Insufficient balance",
  "data": {
    "balance":  "10.00",
    "required": "50.00",
    "currency": "INR"
  }
}

The debit is guarded in SQL, so the wallet can never go negative and two concurrent calls cannot both overdraw it.

Idempotency

Every adjustment carries a client_reference that you choose. It is deduplicated per organisation, so a retry after a network timeout returns the original result instead of charging twice.

Response 200 OK — replay, not charged again

{
  "success": true,
  "message": "Already processed",
  "data": {
    "transaction_id":    "TXN228083272651",
    "transaction_type":  "Debit",
    "amount":            "30.00",
    "balance_after":     "70.00",
    "idempotent_replay": true
  }
}
Retry with the same reference. A 201 means the transaction was created; a 200 with idempotent_replay means it already existed. A 409 means a concurrent request with that reference is still in flight — wait briefly and retry with the same client_reference, never a new one.

Wallet & rate

Returns your wallet alongside your rate for a given sub-service — useful for showing a price before consuming, or checking affordability in one call.

POST /api/v1/accounts/balance-and-rate Bearer

Request

curl -X POST 'https://hub-api.cargodash.in/api/v1/accounts/balance-and-rate' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{ "sub_service_id": "12" }'

Response 200 OK

{
  "success": true,
  "message": "Wallet balance and rate",
  "data": {
    "wallet":     { /* your wallet record */ },
    "subService": { /* sub-service with your negotiated rate */ }
  }
}

An unknown or unassigned sub-service returns 406; a missing wallet returns 400.

Recharge

Top-ups are processed through Razorpay in two steps: create an order, then verify the payment signature. The wallet is credited only after verification succeeds.

POST /api/v1/create-order Bearer

Creates a payment order for the amount being added, returning the order the checkout needs.

POST /api/v1/verify-payment Bearer

Confirms the payment signature returned by the gateway and credits the wallet. The resulting movement appears in transactions under the Recharge category.

Checking the balance after a top-up? Credit is applied on verification, so read /accounts/balance after /verify-payment returns, not before.

Rate limits

Polling endpoints are limited per credential rather than per IP, so partners behind a shared egress address or NAT each get their own quota — one partner's polling cannot exhaust another's.

Scope Limit Window
Balance & transactions 60 requests per minute, per credential
Login & password reset 10 attempts per 15 minutes
OTP requests 3 requests per 5 minutes
General API 100 requests per 15 minutes

Responses carry standard RateLimit-* headers. Exceeding a limit returns 429 — back off and retry rather than looping.

Error handling

Errors return the appropriate HTTP status with success: false and a message naming the problem. Validation failures name the offending field rather than silently correcting it.

Status Meaning What to do
400 Validation error — bad date, limit out of range, unknown category, or an amount field that is no longer accepted Fix the named field and resend
401 Token missing, invalid or expired Log in again and retry
402 Insufficient balance — nothing was charged Top up, then retry
403 Your role does not permit this endpoint Check your access level
404 Wallet not found — no active wallet for your organisation Contact support
406 Sub-service not found or not assigned to you Verify the sub_service_id
409 A concurrent request with the same client_reference is in flight Wait briefly, retry with the same reference
429 Rate limit exceeded Back off, then retry

Example

Status: 401 Unauthorized
{
  "status":  false,
  "message": "Token expired"
}
Retry deliberately. 401, 409 and 429 are worth retrying; 400, 403 and 406 will fail identically until the request itself changes.