How to Integrate E-Way Bill API in Node.js?

ewaybill
E-Way Bill

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.

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.

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.

Leave your thought here

Your email address will not be published. Required fields are marked *