Agency API · v1

Integrate COD reconciliation
into your ops stack.

A single POST endpoint reconciles any Shopify export against any courier remittance file. It returns structured flags, shortfall amounts, and overdue timelines your team can act on immediately.

Typical response in 800ms–2s
HTTPS only · Bearer auth
JSON in · JSON out
Try it free

Try it before you subscribe.

The GET /demo endpoint runs a full reconciliation against a real sample dataset — no account, no API key, no credit card required. It uses an anonymised Shopify export and Delhivery remittance file covering Feb–Mar 2026, with every flag type represented.

One-line demo call

No request body. No auth header. Returns the same { results } shape as a live reconciliation run.

curl https://api.paytrace.in/demo
No auth required
All flag types present
Anonymised orders only
Same response schema as live

Evaluating for your agency? Call GET /demo to see exactly what a reconciliation response looks like before writing any integration code. The dataset includes MISSING, SHORT_PAID, OVERDUE, RTO_ANOMALY, MINOR_DIFF, OVERPAID, and RECONCILED rows so you can build and test your downstream flag-handling logic end-to-end.

Authentication

Bearer token, nothing else.

Every request must include your API key as a Bearer token in the Authorization header. Live keys are generated post-subscription from the Agency → API panel.

HTTP Header
Authorization: Bearer pt_live_your_key_here
Content-Type: application/json

Keep your live key secret. It has full access to all brands under your agency account. Never expose it in client-side code or public repos. Rotate it from the API panel if compromised. The old key is instantly invalidated.

Quickstart

Reconcile in one call.

Pass your Shopify orders export and the courier remittance file as CSV strings. The API parses, matches, and returns a structured array of every order with its reconciliation status.

cURL
curl -X POST https://api.paytrace.in/reconcile \
  -H "Authorization: Bearer pt_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "shopify": "Name,Email,Financial Status,Paid at,Fulfillment Status,...\n#1001,...",
    "courier": "AWB No,Order ID,COD Amount,Remitted Amount,Remittance Date,...\nDEL123,...",
    "courierName": "delhivery",
    "brand": "brand_nykaa_01"
  }'

Example response

JSON Response
{
  "results": [
    {
      "awb": "DEL1234567890",
      "order_id": "#1082",
      "cod_amount": 899,
      "remitted": 0,
      "shortfall": 899,
      "days_overdue": 18,
      "flag": "MISSING",
      "flag_reason": "Not remitted",
      "status": "fulfilled",
      "match_mode": "awb"
    },
    {
      "awb": "DEL9876543210",
      "order_id": "#1097",
      "cod_amount": 1499,
      "remitted": 999,
      "shortfall": 500,
      "days_overdue": 0,
      "flag": "SHORT_PAID",
      "flag_reason": "Shortfall detected",
      "status": "fulfilled",
      "match_mode": "awb"
    },
    {
      "awb": "DEL5551234567",
      "order_id": "#1043",
      "cod_amount": 599,
      "remitted": 599,
      "shortfall": 0,
      "days_overdue": 0,
      "flag": "RECONCILED",
      "flag_reason": "Fully remitted",
      "status": "fulfilled",
      "match_mode": "awb"
    }
    // ... remaining results
  ]
}
Endpoint

POST /reconcile

The primary endpoint. Accepts a Shopify CSV and a courier remittance CSV. Reconciles them order-by-order and returns every flag with shortfall and timeline data.

POST https://api.paytrace.in/reconcile Reconcile Shopify + courier

Request body

Field Type Required Description
shopify string required Full text content of the Shopify orders export CSV. UTF-8 encoded. Maximum 50,000 rows.
courier string required Full text content of the courier remittance CSV. Supported couriers: Delhivery, Shiprocket, XpressBees, Shadowfax, Ekart, Ecom Express. Maximum 50,000 rows.
courierName string optional Courier identifier string (e.g. delhivery, shiprocket). Always stored in audit history so you can filter and group runs by courier. On Enterprise plans, also used to save and re-use detected column mappings across runs — skipping re-detection on subsequent calls for the same courier. Has no column-mapping effect on Agency plan.
brand string optional Your brand label for this run (e.g. "brand_nykaa_01" or "Nykaa Fashion"). Stored in audit history so you can filter runs by brand. Defaults to "default" if omitted.
overdue_threshold_days integer optional Days after delivery before an unremitted COD is flagged OVERDUE. Defaults to 7. Range: 1–30.
minor_gap_threshold integer optional Shortfall in rupees below which a discrepancy is flagged MINOR_DIFF instead of SHORT_PAID. Defaults to 2 (₹2). Range: 0–10.

Response fields

FieldTypeDescription
resultsarrayArray of reconciliation result objects, one per order row. Always present on a 200 response.
duplicatebooleanPresent and true when an identical run was detected within the last 30 seconds. Match is on: same user + brand + courierName + identical row and flag counts. Results are still returned and the run is not counted against your monthly limit.
run_idstringUUID identifying this reconciliation run. Included when a duplicate is detected. Use for support queries.
results[].awbstringCourier AWB / tracking number.
results[].order_idstringShopify order name (e.g. #1082).
results[].cod_amountnumberCOD amount collected on delivery, in rupees (₹).
results[].remittednumberAmount the courier has remitted so far, in rupees (₹). 0 if not yet remitted.
results[].shortfallnumberUnrecovered amount in rupees (₹). Positive = courier owes money. Negative = courier overpaid. 0 if fully reconciled.
results[].days_overdueintegerDays past the expected remittance window. Non-zero only on OVERDUE and MISSING rows.
results[].flagstringReconciliation status. One of: RECONCILED MISSING SHORT_PAID OVERDUE RTO_ANOMALY MINOR_DIFF OVERPAID
results[].flag_reasonstringHuman-readable explanation for the flag (e.g. "Shortfall detected", "Not remitted"). Useful for display in client-facing dashboards without needing to map flag codes yourself.
results[].statusstringShopify fulfilment status for this order (e.g. fulfilled, unfulfilled). Useful for filtering RTO and cancelled orders.
results[].match_modestringHow this row was matched between the two files. awb = matched on tracking number (preferred). order_id = matched on Shopify order ID (fallback when AWB not present in Shopify export).
Endpoint

POST /generate-api-key

Generates a new live API key for your agency account. Requires an active Agency plan subscription. Any previously issued key for your account is immediately deactivated — there is always only one active key per account.

POST https://api.paytrace.in/generate-api-key Issue a new live API key

This endpoint must be called with a Supabase session token, not a pt_live_* API key. Use your dashboard session from the browser. The returned key is shown exactly once — store it securely. Calling this endpoint rotates your key immediately.

Request body

No request body required. The authenticated user's email is used to identify the account.

Response

JSON Response
{
  "key":    "pt_live_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",  // full key — shown once, store immediately
  "prefix": "pt_live_a1b2c"                             // safe prefix for display / identification
}

All pt_live_* keys are passed as a Bearer token in subsequent API calls. Only the SHA-256 hash of the key is stored — PayTrace cannot recover a lost key. If you lose it, call this endpoint again to rotate.

Coming Soon

POST /reconcile/batch

Process multiple brands in a single call. Results will be delivered via webhook or polled with GET /status/{batch_id}. Ideal for agencies running weekly reconciliations across many brands.

This endpoint is not yet available. Batch processing is on the roadmap for Agency plan users. In the meantime, call POST /reconcile once per brand in sequence. Email help@paytrace.in to register your interest and get notified on launch.

POST https://api.paytrace.in/reconcile/batch Multi-brand async run — coming soon
FieldTypeRequiredDescription
jobs array required Array of reconciliation jobs. Each job has the same fields as POST /reconcile plus a required brand. Max 20 per batch.
webhook_url string (url) optional Called once all jobs complete. Payload contains the full batch results array.
Batch response
{
  "ok": true,
  "batch_id": "batch_b2f1a9c3_1712345678",
  "jobs": 5,
  "status": "queued",
  "estimated_completion_ms": 12000
}
Coming Soon

GET /status/{job_id}

Poll the status of an async batch job. Will return queued, processing, or complete, with the full results payload once done. Available when POST /reconcile/batch launches.

GET https://api.paytrace.in/status/{job_id} Poll async job status — coming soon

Not yet available. This endpoint will be released alongside POST /reconcile/batch. The current POST /reconcile endpoint is synchronous and returns results directly in the response body.

Reference

Flag types: what each means.

Every order in the results array carries exactly one flag. Here's what each flag means and what action it implies for your clients.

Flag Meaning Shortfall Recommended action
MISSING Courier delivered the order and collected COD, but no remittance appears in the courier report at all. 100% of cod_amount Raise a dispute immediately. Include the AWB, days_overdue and order date in your escalation letter.
SHORT_PAID Courier remitted a lower amount than the COD collected. Common due to manual entry errors or partial cycles. cod_amount − remitted Dispute the delta. Attach the remittance entry showing the low amount. Most couriers resolve in 7–14 days.
OVERDUE No remittance received within the courier's standard SLA window (typically 7 days post-delivery). 100% of cod_amount Follow up with courier's ops team. May resolve in the next remittance cycle without a formal dispute.
RTO_ANOMALY Order shows as RTO (returned) in the courier system but COD was still collected. Courier remitted nothing. High-severity. 100% of cod_amount Escalate to courier's fraud team. Request delivery proof (OTP, signature). Absence is grounds for full recovery.
MINOR_DIFF Remittance is slightly below COD amount, within the minor_gap_threshold (default ₹2). Likely a rounding difference. ≤ threshold (default ₹2) Monitor but usually not worth disputing. Batch with next cycle's discrepancies if your courier allows it.
OVERPAID Courier remitted more than the COD amount collected. Can happen due to duplicate remittance runs or manual credit errors. Negative (courier paid excess) Verify against bank statement. If confirmed, acknowledge to courier to offset against a future cycle rather than raising a dispute.
RECONCILED COD amount matches remittance exactly. No action required. ₹0 None. These orders are fully settled.
Reference

Error codes.

All errors return a JSON object with a single error field containing a human-readable message string.

Error shape
{ "error": "Plain English description of what went wrong" }
HTTPWhen it occursFix
200 Successful reconciliation. results array is present. n/a
400 Invalid JSON body, missing shopify or courier fields, either CSV exceeds 50,000 rows, or a CSV column that can't be detected or validated. Check the error message — it names the missing or ambiguous column. If hitting the row limit, split your export into smaller date ranges. Verify your CSV exports match the expected formats for your courier.
401 API key missing, malformed, or expired. Check Authorization: Bearer <key> header. Regenerate from Agency → API panel if needed.
403 Subscription has ended, account setup is incomplete, or account does not have Agency access. Check subscription status in the dashboard. Contact help@paytrace.in if you believe this is an error.
403 phone_not_verified Phone number on the account has not been verified. All API calls are blocked until verification is complete. Log into the dashboard and complete phone OTP verification under Account Settings. Takes under 60 seconds.
415 Content-Type header is missing or not application/json on a POST request. Add Content-Type: application/json to your request headers.
413 Request body exceeds 10 MB. Split into smaller date ranges or reduce the number of rows per call.
429 rate limit More than 10 requests in a 60-second window. Key is blocked for 5 minutes on breach. Implement a 0.5s delay between sequential calls. Check the Retry-After header for the exact block duration in seconds.
429 run limit Monthly reconciliation run cap reached. Agency plan: 16 runs/month. Solo plan: 4 runs/month. Resets on your billing cycle date. Wait for the next billing cycle, or contact help@paytrace.in to discuss higher limits. The error message includes the exact limit: "Run limit of 16/month reached".
500 Unexpected server error. Retry once after 5s. If persistent, contact help@paytrace.in.
Reference

Rate limits.

Rate limits are per API key, enforced on a rolling 60-second window. Exceeding the limit returns a 429 and blocks the key for 5 minutes.

Agency plan
10
requests / minute
Breach penalty
5 min
key blocked on breach
Monthly run cap
16
reconciliation runs

No rate-limit headers are sent. The API does not return X-RateLimit-* headers. If you receive a 429, respect the Retry-After header value (seconds) before retrying. For scripted multi-brand workflows, add a 0.5s pause between calls to stay well within limits.

GET /demo limits

GET /demo is rate-limited per IP: 20 requests/minute, with a 60-second block on breach. No auth required. Returns Retry-After on a 429.

429 Response
HTTP/1.1 429 Too Many Requests
Retry-After: 300   // seconds blocked (5 minutes on breach)

{ "error": "Rate limit exceeded" }
Reference

Supported couriers.

PayTrace auto-detects column names from common export formats. These are the accepted values for the courier parameter and the columns we look for in each report.

CourierParameterAWB columnCOD amount columnRemittance date column
Delhivery delhivery AWB No COD Amount Remittance Date
Shiprocket shiprocket AWB Code Total Amount Payment Date
XpressBees xpressbees Waybill Number COD Collected Settlement Date
Ecom Express ecom_express AWB Number COD Amount Remittance Date
Shadowfax shadowfax AWB Number COD Amount (INR) Remittance Date
Ekart ekart AWB Number COD Amount (INR) Remittance Date

Courier not listed? Email help@paytrace.in with a sample remittance CSV. We typically add support within 48 hours. You can also pass "courier": "custom" with explicit column overrides. See custom courier docs →

Guide

Agency integration pattern.

Most agencies integrate PayTrace into their weekly ops cadence — fetching Shopify exports per brand, pulling courier remittances, running reconciliations sequentially and surfacing flags in a Notion or Google Sheet for client review.

Python: weekly batch script
import requests, time

PAYTRACE_KEY = "pt_live_your_key_here"
BASE_URL      = "https://api.paytrace.in"

def run_weekly_reconciliation(brands):
    # brands = [{ brand, shopify_csv, courier_csv, courierName }, ...]
    all_flagged = []

    for b in brands:
        resp = requests.post(
            f"{BASE_URL}/reconcile",
            headers={"Authorization": f"Bearer {PAYTRACE_KEY}"},
            json={
                "shopify":     b["shopify_csv"],
                "courier":     b["courier_csv"],
                "courierName": b["courierName"],
                "brand":       b["brand"],
            }
        )
        resp.raise_for_status()
        results = resp.json()["results"]

        # Collect actionable flags for this brand
        flagged = [
            {**r, "brand": b["brand"]}
            for r in results
            if r["flag"] in ("MISSING", "SHORT_PAID", "RTO_ANOMALY", "OVERDUE")
        ]
        all_flagged.extend(flagged)

        # Be a good API citizen — small pause between brands
        time.sleep(0.5)

    return all_flagged
Coming Soon

Webhooks.

Outbound webhooks — where PayTrace POSTs results to your endpoint on job completion — are planned for release alongside the batch endpoint.

Not yet available for API users. The current POST /reconcile endpoint is synchronous — results come back in the response body within 800ms–2s, so no polling or webhook is needed for single-brand runs. Email help@paytrace.in to register interest.

When webhooks ship, the payload schema will look like this:

Planned webhook payload
{
  "event": "reconciliation.complete",
  "job_id": "recon_a7f2c1d9_1712345678",
  "brand": "brand_nykaa_01",
  "results": [ /* same as /reconcile response results array */ ],
  "signature": "sha256=abc123..."  // HMAC-SHA256 of payload body using your API key
}
Guide

White-label reports.

Agency plan accounts can configure a white-label profile. Your agency name and email appear on all exported Excel reports and dispute letters instead of "PayTrace". Set it once via the dashboard or via API.

Agency plan feature. White-label branding is available on the Agency plan (₹3,999/month). Configure it from Agency → White-label Settings in the dashboard, or by passing white_label: { agency_name, agency_email } in any reconcile call to override per-brand.