Boni
Boni
Browse documentation
Boni Verification API·api-reference·Version 1

Boni Verification API

Verify Aadhaar, PAN, GSTIN, vehicle records and recent FASTag toll observations through one simple tenant-scoped API.

Start here

Boni gives you a separate client ID and client secret for each activated environment. Use the sandbox while integrating; it returns fixed test records and never calls production data sources.

EnvironmentBase URL
Sandboxhttps://sandbox.api.boni.one/v1
Productionhttps://api.boni.one/v1

Send these headers on every request:

x-boni-client-id: YOUR_CLIENT_ID
x-boni-client-secret: YOUR_CLIENT_SECRET
Content-Type: application/json
Idempotency-Key: a-unique-key-for-this-request

Keep credentials on your server. Do not put them in browser code, mobile apps, URLs or public repositories. Reuse an Idempotency-Key only when retrying the exact same request body.

First request

curl https://sandbox.api.boni.one/v1/verify/gstin \
  -X POST \
  -H 'x-boni-client-id: YOUR_SANDBOX_CLIENT_ID' \
  -H 'x-boni-client-secret: YOUR_SANDBOX_CLIENT_SECRET' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: gstin-demo-0001' \
  -d '{"gstin":"22AAAAA0000A1Z5"}'
{
  "success": true,
  "request_id": "req_...",
  "environment": "sandbox",
  "endpoint": "gstin",
  "status": "verified",
  "data": {
    "gstin": "22AAAAA0000A1Z5",
    "legal_name": "BONI SANDBOX PRIVATE LIMITED",
    "trade_name": "BONI SANDBOX",
    "status": "ACTIVE",
    "taxpayer_type": "Regular",
    "registration_date": "2019-07-01",
    "e_invoice_enabled": true,
    "principal_place": {"state": "Chhattisgarh", "pincode": "492001"},
    "sandbox": true
  }
}

Endpoints and input

Every verification is a POST. Unknown fields are rejected. Spaces and hyphens in vehicle identifiers are normalized.

WhatEndpointJSON input
Aadhaar/verify/aadhaaraadhaar, name, date_of_birth, gender, mobile, consent
PAN/verify/panpan plus all Aadhaar input fields
GSTIN/verify/gstingstin
Vehicle/verify/vahanvehicle_number
FASTag/verify/fastagexactly one of vehicle_number or chassis_number

date_of_birth uses YYYY-MM-DD, gender is M or F, and consent must be true. Aadhaar and PAN requests must be made with the document owner's consent.

Sandbox test values

FieldValue
Aadhaar999999990019
PANABCDE1234F
GSTIN22AAAAA0000A1Z5
Vehicle numberKA01AB1234
Chassis numberMA1AA2BB3CC444444
NameSandbox User
Date of birth1990-01-01
Mobile9999999999

Sandbox Aadhaar and PAN finish immediately and do not require an OTP. Other valid-looking sandbox values return status: not_found so you can test that branch.

Aadhaar input and output

{
  "aadhaar": "999999990019",
  "name": "Sandbox User",
  "date_of_birth": "1990-01-01",
  "gender": "F",
  "mobile": "9999999999",
  "consent": true
}

A successful response uses the common envelope and returns the complete approved data payload:

{
  "success": true,
  "request_id": "req_...",
  "environment": "sandbox",
  "endpoint": "aadhaar",
  "status": "verified",
  "data": {
    "aadhaar": "999999990019",
    "name": "Sandbox User",
    "date_of_birth": "1990-01-01",
    "gender": "F",
    "status": "VERIFIED",
    "sandbox": true
  }
}

Production data preserves the complete provider data structure. Boni removes only upstream authentication credentials and tokens, which are Boni platform secrets rather than verification data.

PAN input and output

{
  "pan": "ABCDE1234F",
  "aadhaar": "999999990019",
  "name": "Sandbox User",
  "date_of_birth": "1990-01-01",
  "gender": "F",
  "mobile": "9999999999",
  "consent": true
}
{
  "success": true,
  "request_id": "req_...",
  "environment": "sandbox",
  "endpoint": "pan",
  "status": "verified",
  "match": {"pan": true},
  "data": {
    "pan": "ABCDE1234F",
    "name": "SANDBOX USER",
    "status": "VALID",
    "category": "Individual",
    "sandbox": true
  }
}

Vehicle input and output

{"vehicle_number": "KA01AB1234"}
{
  "success": true,
  "request_id": "req_...",
  "environment": "sandbox",
  "endpoint": "vahan",
  "status": "verified",
  "data": {
    "registration_number": "KA01AB1234",
    "registration_date": "2022-04-18",
    "owner_name": "SANDBOX OWNER",
    "vehicle_class": "Goods Carrier",
    "fuel_type": "DIESEL",
    "maker_model": "BONI SANDBOX TRUCK",
    "registration_status": "ACTIVE",
    "fitness_upto": "2027-04-17",
    "insurance_upto": "2027-01-31",
    "pucc_upto": "2026-12-31",
    "sandbox": true
  }
}

FASTag input and output

Use either a vehicle number:

{"vehicle_number": "KA01AB1234"}

or a chassis number:

{"chassis_number": "MA1AA2BB3CC444444"}
{
  "success": true,
  "request_id": "req_...",
  "environment": "sandbox",
  "endpoint": "fastag",
  "status": "verified",
  "data": {
    "vehicle_number": "KA01AB1234",
    "lookback_hours": 72,
    "events": [
      {"plaza": "Boni Sandbox Toll Plaza A", "event_time": "2026-08-16T08:30:00+05:30", "direction": "EAST"}
    ],
    "sandbox": true
  }
}

FASTag is a sparse toll-observation feed for the rolling 72-hour window. It is not GPS tracking and does not return wallet balances, recharges or debit transactions. An empty observation result is a valid result.

Production OTP flow

Production Aadhaar or PAN may return HTTP 202 with an OTP challenge:

{
  "success": true,
  "request_id": "req_...",
  "environment": "production",
  "endpoint": "aadhaar",
  "status": "otp_required",
  "verification_id": "ver_...",
  "expires_at": "2026-08-17T12:05:00.000Z"
}

Send the received OTP within five minutes to /verify/aadhaar/otp or /verify/pan/otp with a new idempotency key:

{"verification_id": "ver_...", "otp": "123456"}

A challenge allows at most three attempts and is bound to the same client, subscription and environment.

Common results

HTTPMeaningWhat to do
200 + verifiedData returnedUse data and keep request_id for support
200 + not_foundNo matching recordTreat as a normal no-record result
202 + otp_requiredOwner must provide OTPCall the matching /otp endpoint
400Invalid or unknown inputFix the request; do not retry unchanged
401Missing or invalid credentialsCheck the client ID and secret
403Environment, scope or endpoint not enabledUse the correct credential or ask Boni to activate access
409Idempotency or session conflictReuse a key only with its original body
422Provider rejected the requestCheck consent/input and follow the returned code
429A quota window is fullWait for Retry-After or the indicated reset
503 or 504Temporary service/provider issueRetry the same body with the same idempotency key

Errors use one shape:

{
  "success": false,
  "request_id": "req_...",
  "error": {"code": "rate_limit_exceeded", "message": "The minute request limit has been reached.", "retry_after_seconds": 12}
}

Quota headers report the configured second, minute, hour and day limits, remaining calls and reset times. Limits are assigned to your subscription and can differ by environment or endpoint.

Usage

Call GET /usage with the same environment credential and the verification.usage.read scope. Optional query parameters are from, to, and endpoint; a query can cover up to 31 days. The response separates total requests from metered production units and groups them by endpoint and outcome. Sandbox calls, validation failures, no-record results, rate-limit responses and upstream failures have zero billable units.

OpenAPI

Download the complete Boni Verification API V1 OpenAPI file for schemas, response types and code generation.