How to Integrate E-Way Bill API in Node.js?
If your business ships goods worth more than Rs. 50,000 inter-state, every consignment legally requires an E-Way Bill before it moves. For companies dispatching hundreds of shipments daily, manually logging into the NIC portal for each one creates a serious operational bottleneck. Integrating the E-Way Bill API directly into your Node.js application eliminates that bottleneck entirely.
This guide walks you through every step of the integration from authentication to generation to lifecycle management with the exact headers, JSON payloads, error codes, and flow you need to build a production-ready implementation.
Before You Begin
You need a PeriOne developer account with E-Way Bill API access enabled, your GSTIN verified on the platform, and an API Key and Client Secret from the PeriOne developer console. On the Node.js side, install axios and dotenv:
npm install axios dotenv
Create a .env file in your project root to store credentials safely:
PERIONE_API_KEY=your_api_key_here
PERIONE_CLIENT_SECRET=your_client_secret_here
GSTIN=22AAAAA0000A1Z5
PERIONE_BASE_URL=https://api.perionetech.in/v1
Step 1 — Authenticate and Get Your Session Token
Every E-Way Bill API call requires a valid session token in the Authorization
header. Tokens are GSTIN-specific and expire after six hours. The right approach
is to cache the token with its expiry timestamp and refresh it proactively when
within five minutes of expiry — never re-authenticate before every single call,
as that triggers rate limiting almost immediately.
The authentication endpoint is:
POST /ewb/authenticate
Send the following headers with this request:
Content-Type: application/json
x-api-key: your_api_key_here
And this JSON body:
{
“gstin”: “22AAAAA0000A1Z5”,
“app_key”: “your_client_secret_here”
}
A successful authentication returns:
{
“status”: “success”,
“data”: {
“auth_token”: “eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…”,
“token_expiry”: “2024-11-15T20:00:00Z”,
“gstin”: “22AAAAA0000A1Z5”
}
}
Store the auth_token and parse token_expiry into a timestamp. Before every API
call, check if the current time is within five minutes of that expiry. If yes,
call authenticate again and update your cache. If no, use the stored token.
Step 2 — The Four Headers Every API Call Requires
Once you have a valid session token, every E-Way Bill API request must carry
exactly these four headers:
Content-Type: application/json
x-api-key: your_permanent_api_key
Authorization: Bearer eyJhbGciOiJSUzI1NiI…
gstin: 22AAAAA0000A1Z5
Missing any one of these returns a 401 Unauthorized response. The most common
production issue is a valid request body paired with an expired Authorization
token. Proactive token refresh prevents this entirely.
Step 3 — Generate the E-Way Bill
The generation endpoint is:
POST /ewb/generate
Send the following JSON payload. This covers the supply details, from and to
addresses, item list, and transporter information:
{
“supplyType”: “O”,
“subSupplyType”: “1”,
“docType”: “INV”,
“docNo”: “INV-2024-00451”,
“docDate”: “15/11/2024”,
“fromGstin”: “22AAAAA0000A1Z5”,
“fromTrdName”: “ABC Traders Pvt Ltd”,
“fromAddr1”: “Plot No. 45, Industrial Area”,
“fromAddr2”: “Phase 2”,
“fromPlace”: “Raipur”,
“fromPincode”: 492001,
“fromStateCode”: 22,
“toGstin”: “27BBBBB1111B1Z6”,
“toTrdName”: “XYZ Distributors Ltd”,
“toAddr1”: “Warehouse No. 12, Andheri East”,
“toAddr2”: “”,
“toPlace”: “Mumbai”,
“toPincode”: 400093,
“toStateCode”: 27,
“transactionType”: 1,
“itemList”: [
{
“itemNo”: 1,
“productName”: “Steel Pipes”,
“productDesc”: “MS ERW Steel Pipes 2 inch”,
“hsnCode”: “73063090”,
“quantity”: 100.00,
“qtyUnit”: “NOS”,
“cgstRate”: 0,
“sgstRate”: 0,
“igstRate”: 18,
“cessRate”: 0,
“taxableAmount”: 85000.00
}
],
“totalValue”: 85000.00,
“cgstValue”: 0,
“sgstValue”: 0,
“igstValue”: 15300.00,
“cessValue”: 0,
“totInvValue”: 100300.00,
“transMode”: “1”,
“transDistance”: “650”,
“transporterName”: “Fast Freight Logistics”,
“transporterId”: “29CCCCC2222C1Z7”,
“transDocNo”: “LR-20241115-001”,
“transDocDate”: “15/11/2024”,
“vehicleNo”: “MH04AB1234”,
“vehicleType”: “R”
}
A few fields that cause validation failures if you get them wrong. The qtyUnit
must use GSTN-approved codes — NOS not PCS, KGS not KG, MTR not MT. The
vehicleNo format must match patterns like MH04AB1234. The transDistance must be
the NIC PIN-to-PIN distance from their master, not an estimated value.
When the NIC processes the request successfully, the response is:
{
“status”: “success”,
“data”: {
“ewbNo”: 121012345678,
“ewbDt”: “15/11/2024 10:35:00”,
“ewbValidTill”: “17/11/2024 23:59:00”,
“supplyType”: “O”,
“docNo”: “INV-2024-00451”,
“fromTrdName”: “ABC Traders Pvt Ltd”,
“toTrdName”: “XYZ Distributors Ltd”,
“vehicleNo”: “MH04AB1234”,
“totInvValue”: 100300.00,
“distance”: 650,
“status”: “ACTIVE”
}
}
Save ewbNo and ewbValidTill to your database immediately. The EWB number goes
on the transport document before goods leave the premises. The ewbValidTill
timestamp must be monitored — validity is calculated at one day per 200 km for
regular vehicles, so a 650 km consignment gets approximately three days.
Step 4 — Update the Vehicle Details When Transport Changes
When a vehicle breaks down or goods are transshipped mid-transit, you must
update Part B of the active EWB. Missing this is a compliance violation.
The Part B update endpoint is:
PUT /ewb/update-part-b
Request body:
{
“ewbNo”: 121012345678,
“vehicleNo”: “MH12CD5678”,
“fromPlace”: “Nagpur”,
“fromState”: 27,
“reasonCode”: “1”,
“reasonRem”: “Vehicle breakdown at Nagpur”,
“transDocNo”: “LR-20241115-002”,
“transDocDate”: “15/11/2024”,
“transMode”: “1”
}
Successful response:
{
“status”: “success”,
“data”: {
“ewbNo”: 121012345678,
“updatedDate”: “15/11/2024 16:20:00”,
“newVehicleNo”: “MH12CD5678”
}
}
Build Part B update as a first-class operation in your system, not an
afterthought. Your operations team should trigger it directly from your TMS
or dispatch system without ever touching the government portal.
Error Codes You Will Encounter
Every error response follows this structure:
{
“status”: “error”,
“error_code”: “4002”,
“message”: “Invalid buyer GSTIN. Verify GSTIN registration status.”,
“http_status”: 400
}
The most common E-Way Bill errors and their fixes:
Error 4001 fires when a duplicate EWB already exists for the invoice. Always
check your database for an existing EWB before calling generate.
Error 4002 fires when the buyer or transporter GSTIN is inactive or invalid.
Validate all GSTINs using PeriOne’s GSTIN API before building the payload.
Error 4003 fires for an invalid HSN code. Cross-check product HSN codes
against the GSTN master at the product level, not at invoice generation time.
Error 4004 fires when the distance entered mismatches the NIC PIN-to-PIN
master for the entered source and destination PIN codes.
Error 4005 fires when the vehicle number format is invalid. The accepted format
is like MH04AB1234 — two letters, two digits, optional two letters, four digits.
A 401 response means your session token expired. Implement proactive refresh
to prevent this from ever occurring in production.
A 429 response means you hit the rate limit. Add a request queue that controls
the rate of API calls during high-volume dispatch windows.
A 503 response means the NIC portal is temporarily unavailable. Retry with
exponential backoff — five seconds, then ten, then twenty — before alerting
your operations team.
The Complete API Flow
The flow from your Node.js application to a registered EWB number looks like
this:
Your Node.js Application
|
|— POST /ewb/authenticate
| Body: { gstin, app_key }
| Header: x-api-key
| |
| Returns: { auth_token, token_expiry }
| Cache token. Check expiry before every call.
|
|— Build EWB JSON payload
| Map invoice data + logistics data
| Validate HSN codes, GSTINs, vehicle format
|
|— POST /ewb/generate
| Headers: x-api-key, Authorization: Bearer, gstin
| Body: Full EWB JSON payload
| |
| PeriOne –> NIC E-Way Bill Portal
| |
| Returns: { ewbNo, ewbDt, ewbValidTill }
|
|— Save ewbNo + ewbValidTill to database
| Print EWB number on transport document
|
|— If vehicle changes mid-transit:
| PUT /ewb/update-part-b
|
|— If EWB nears expiry before delivery:
| POST /ewb/extend
|
|— If order cancelled before dispatch:
POST /ewb/cancel (within 24 hours only)
Integrating E-Way Bill API in Node.js eliminates every manual step in your freight compliance workflow. Authenticate once, cache the token, build the payload from your existing invoice and logistics data, and let the API handle the rest. The integration covers not just generation but the full EWB lifecycle vehicle updates, extensions, and cancellations — so your operations team never needs to log into the government portal again.
PeriOne’s E-Way Bill API is built for enterprise-grade reliability with direct NIC connectivity, a full sandbox environment for testing, and the documentation your team needs to go live with confidence.
FAQ’s
How do I prevent token expiry errors in production?
Store the auth_token and token_expiry from the authentication response in module-level variables. Before every API call, calculate whether the current time is within five minutes of expiry. If yes, call authenticate, update the stored values, and proceed. If no, use the cached token directly.
Can I generate E-Way Bills in bulk using Node.js?
Yes. PeriOne’s E-Way Bill API supports a bulk generation endpoint that accepts an array of EWB payloads in one call. Each invoice in the batch receives an independent success or failure response, so partial batch success is handled cleanly.
What is the validity period of an E-Way Bill?
Validity is distance-based — one day per 200 km for regular vehicles and one day per 20 km for over-dimensional cargo. The API response always includes the exact ewbValidTill timestamp.
Categories
Latest Posts