← Back to panel

Kashly API Hub — Documentation

A multi-tenant gateway that lets you hand out ONE base URL to any partner or mobile app. They call third-party services (PAN, bank, CRIF, Aadhaar, Account Aggregator…) by just changing the path — your real vendor credentials never leave this server.

Contents
What it isHow it worksRunning it Admin panel guideCompanies & keysVendors & services Per-company overridesQuotasAlerts Consumer integrationService catalogService reference SecurityDeploymentFAQ

1. What it is

The Hub sits between your consumers (mobile app, partner companies) and the third-party vendors you pay for (Signzy, CRIF, Finduit, etc.).

[ Mobile app / Partner ]  --x-api-key-->  [ API HUB ]  --vendor creds-->  [ Signzy / CRIF / Finduit ]
                                              │
                                        MySQL: companies, keys,
                                        usage, quotas, alerts

2. How it works

A consumer makes one request:

POST https://your-domain/gw/pan
x-api-key: <the company's key>
Content-Type: application/json

{ "panNumber": "ABCDE1234F" }

The Hub then:

  1. Looks up the API key → resolves which company it belongs to (rejects if revoked/disabled).
  2. Checks the company's quota for today / this month.
  3. Resolves the service (pan) → its vendor (signzy), base URL, path and default body.
  4. Applies any per-company override (custom base URL / credentials).
  5. Injects the vendor credentials (as the header that vendor expects) and forwards the request.
  6. Returns the vendor's response, and logs the call (status, latency, bytes).

3. Running it

cd api-hub
cp .env.example .env      # fill in DB + admin + vendor creds
npm install
npm start                 # boots, auto-creates the DB + tables, seeds vendors/services

Open http://localhost:6200/ and log in with the ADMIN_USERNAME / ADMIN_PASSWORD from your .env. Change the password immediately under Settings.

The database (DB_NAME) and all tables are created automatically on first boot. Vendor credentials from .env are seeded once, then managed from the panel.

4. Admin panel guide

Seven sections in the sidebar:

5. Companies & API keys

Add a company → you get its first API key instantly. Copy it and hand it over — it goes in the x-api-key header of every request.

6. Vendors & services

Vendor = a third-party provider (Signzy, Finduit, MoneyOne). It holds the base URL + credentials + an auth type that decides how creds are injected:

Auth typeHow creds are sent
signzyAuthorization: <authToken>
finduitdynamic Bearer token (auto-fetched from the auth endpoint)
moneyoneheaders: x-client-id, x-client-secret, x-organisation-id, x-app-identifier

Service = one callable endpoint (the URL end). It points at a vendor, has a path, an optional base-URL override, and a default_body (static fields merged into every request). Change a base URL or path here anytime — it takes effect within ~15 seconds (catalog cache).

Add a new third-party API in seconds: Services → “+ Add service” → pick a vendor, set the path. Done — it's live at /gw/<your-key>.

7. Per-company overrides

By default every company uses the global vendor config. If one company needs something different, open the company → “Add override”:

Resolution order: service override → service config → vendor override → vendor default.

8. Quotas

Each company has a daily and monthly limit (0 = unlimited). When exceeded, requests get 429 Quota exceeded and a quota_breach alert can fire. Usage counters roll over automatically by calendar day/month.

9. Alerts

Channel is email (needs SMTP in .env) or webhook (any URL — receives a JSON POST). Alerts are throttled to once per window to avoid spam.

10. Consumer integration guide

Hand your partner exactly this: the base URL, their API key, and the service list below. Every call is POST, JSON, with the key header.

curl -X POST https://your-domain/gw/pan \
  -H "x-api-key: THEIR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"panNumber":"ABCDE1234F"}'

Response shape is always:

{ "success": true, "service": "pan", "data": { ...vendor's raw response... } }

Errors: 401 bad/missing key, 403 disabled, 429 quota, 404 unknown service, 503 service not configured, 502 upstream failure.

Self-service developer portal

Every company also gets its own login-protected portal at /portal (separate from the admin panel). There they can, for themselves only:

The admin invites a portal user from the company's page (“+ Invite user”), which generates a temporary password to hand over. Portal users only ever see their own company's data.

11. Service catalog (default)

PathVendorPurpose
/gw/panSignzyPAN verification
/gw/bankSignzyBank account verification
/gw/penny-dropSignzyPenny-drop verification
/gw/digilocker-createSignzyCreate Aadhaar Digilocker URL
/gw/digilocker-eaadhaarSignzyFetch eAadhaar
/gw/crifSignzyCRIF credit bureau report
/gw/bureau-encryptSignzyBureau consent — encrypt
/gw/bureau-consentSignzyBureau consent — create
/gw/bureau-decryptSignzyBureau consent — decrypt
/gw/aa-authFinduitAA authenticate
/gw/aa-redirectFinduitAA consent redirect URL
/gw/aa-consent-dataFinduitAA fetch consent data
/gw/aa-fi-dataFinduitAA fetch financial statements

Live list (with per-company status) is always available at GET /gw/_health and inside the panel under Services.

12. Per-service reference (request body + curl)

Every call is POST, JSON, with the x-api-key header. Below, replace YOUR_KEY with the company's key and use your own domain instead of localhost:6200. The response is always wrapped as { "success", "service", "data" } where data is the vendor's raw response.

PAN — /gw/pan

curl -X POST http://localhost:6200/gw/pan \
  -H "x-api-key: YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"panNumber":"ABCDE1234F"}'

Body: panNumber (10-char PAN). Returns name, DOB, status, address.

Bank account verify — /gw/bank

curl -X POST http://localhost:6200/gw/bank \
  -H "x-api-key: YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"beneficiaryAccount":"1234567890","beneficiaryIFSC":"HDFC0000001","beneficiaryName":"John Doe"}'

Body: beneficiaryAccount, beneficiaryIFSC (required); beneficiaryName, beneficiaryMobile (optional, enable name match).

Penny drop — /gw/penny-drop

curl -X POST http://localhost:6200/gw/penny-drop \
  -H "x-api-key: YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"beneficiaryAccount":"1234567890","beneficiaryIFSC":"HDFC0000001"}'

Same body as bank verify. Does a ₹1 credit to confirm the account is live; returns beneficiary name + RRN.

Aadhaar (Digilocker) — 2-step flow

Step 1 — create the consent URL (/gw/digilocker-create):

curl -X POST http://localhost:6200/gw/digilocker-create \
  -H "x-api-key: YOUR_KEY" -H "Content-Type: application/json" \
  -d '{
    "signup": false,
    "callbackUrl": "https://your-domain/api/digilocker/webhook",
    "successRedirectUrl": "https://your-domain/digilocker/close",
    "failureRedirectUrl": "https://your-domain/digilocker/close?status=failed",
    "docType": ["ADHAR"],
    "purpose": "kyc",
    "getScope": true,
    "internalId": "user-123",
    "getEAadhaarPdf": true,
    "getEAadhaarJpeg": true,
    "pinlessAuthentication": true
  }'

Returns { data: { result: { url, requestId } } }. Open url in a WebView / browser for the user to give Aadhaar consent. Save requestId.

Step 2 — fetch eAadhaar after consent completes (/gw/digilocker-eaadhaar):

curl -X POST http://localhost:6200/gw/digilocker-eaadhaar \
  -H "x-api-key: YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"requestId":"<requestId from step 1>"}'

Returns name, DOB, gender, address, photo, and the eAadhaar PDF/JPEG. Call it only after the user finishes step 1 (else you'll get a "pending" response).

This is a redirect flow: the mobile app opens the url (in-app browser / WebView) and comes back via a deep link to your successRedirectUrl. The Hub just brokers the two API calls.

CRIF credit bureau — /gw/crif

Served via Signzy's bureau endpoint (/api/v3/bureau/crif); the Hub injects the shared Signzy Authorization token. Body:

{
  "phoneNumber": "9999999999",
  "pan": "ABCDE1234F",
  "firstName": "First",
  "lastName": "Last",
  "dateOfBirth": "1990-01-01",   // yyyy-mm-dd
  "pincode": "641001",
  "gender": "Male",             // Male / Female
  "address": "Coimbatore",
  "consent": {
    "consentFlag": true,
    "consentTimestamp": 1690215946415,
    "consentIpAddress": "192.168.0.1",
    "consentMessageId": "CM_1"
  }
}

Account Aggregator (Finduit) — 3-step flow

  1. /gw/aa-redirect — create a consent + get the AA redirect URL (user approves bank-data sharing).
  2. /gw/aa-consent-data — poll/fetch consent status with the consent handle.
  3. /gw/aa-fi-data — fetch the financial statements once consent is active.

Bodies pass through to Finduit (txnid / consentId / sessionId); the Hub auto-fetches the Finduit bearer token for you.

Account Aggregator — async FI-data webhook

The final bank-statement (FI) data is pushed by Finduit, not returned synchronously. Register this single URL with Finduit as your FIU callback:

<APP_PUBLIC_URL>/hooks/finduit  (optionally protect with FINDUIT_WEBHOOK_TOKEN → sent as header x-webhook-token).

How it routes to the right consumer, with no data loss:

  1. When a company calls /gw/aa-redirect / /gw/aa-fi-data, the Hub records the returned consentHandle / txnid / sessionId against that company (aa_sessions).
  2. Finduit later POSTs the FI data to /hooks/finduit. The Hub correlates the payload's ids back to the owning company, ACKs Finduit instantly, and enqueues a delivery.
  3. The Hub forwards the payload to that company's webhook URL (set in the panel per company, or by the company itself in the developer portal), signed with their secret, retrying with backoff until it succeeds.

Delivery signature: header X-Hub-Signature: sha256=<hmac> where the HMAC-SHA256 is over <X-Hub-Timestamp>.<raw body> using the company's webhook_secret. Failed deliveries retry automatically (30s → 1h backoff) and are visible in the portal.

13. Security notes

14. Deployment

# run under a process manager
pm2 start src/server.js --name api-hub

# nginx: expose the gateway + panel on your domain
location / {
    proxy_pass http://127.0.0.1:6200;
    proxy_set_header X-Forwarded-For $remote_addr;
}

Consumers then use https://your-domain/gw/<service>. The panel is at https://your-domain/ (protect it — restrict by IP or keep it on an internal host if possible).

15. FAQ

Ek nayi third-party API kaise add karu?

Agar vendor already hai (e.g. Signzy): Services → “+ Add service”, path daal do. Naya vendor hai: pehle DB me vendor add karo (ya code me auth builder), phir service.

Kisi company ki API kaise band karu?

Uski key “Revoke” karo, ya poori company “disabled” kar do. Turant band.

Base URL change karna hai (sandbox → prod)?

Vendors ya Services me base URL edit karo — ~15 sec me live. Kisi ek company ke liye alag chahiye to uska override use karo.

Kis company ne kitni API hit ki?

Dashboard → Top companies, ya company kholo → “Usage by service”. Detailed row-level: Logs (+ CSV export).