BIR EIS Guide

Developer reference

BIR EIS API documentation

How to connect an invoicing system to the BIR Electronic Invoicing System: authentication, request signing, the three endpoints, every field in the v2.01 e-invoice JSON, and the result codes EIS sends back.

Read first

This reference follows the structure of the BIR EIS API Guide and e-invoice JSON format v2.01. Endpoint paths, header names and algorithm details shown here are illustrative. Build against the official API Guide you download from the EIS Certification Portal after sign-up.

Downloads

Official EIS API guides

PDF

EIS e-invoice API Development Guide

The full API reference: authentication, HMAC signing, invoice issuance, inquiry result and callback APIs, JSON format, JWS signature, AES-256 encryption, error codes and Java code samples.

Ver. 2.0 · Feb 2022 · 61 pages · 2.4 MB

Download PDF
XLSX

e-invoice JSON File Format v2.01

Field-by-field spec for CAS and CRM/POS invoices: field names, data types, lengths, mandatory rules, code values (DocType, TransClass, CorrectionCd) and formulas.

Ver. 2.01 · 25 Mar 2022 · Excel workbook · 160 KB

Download Excel
PDF

EIS Certification User Guide

Step-by-step screens for the EIS Certification Portal: sign-up, creating an application, generating keys, sandbox tests, requesting the EIS Certificate and the Permit to Transmit.

Ver. 1.2 · May 2022 · 31 pages · 5.7 MB

Download PDF

Documents from the EIS project team, as published on the BIR EIS Certification Portal (Downloads). Check the portal for newer versions before you build.

Overview

How an EIS integration works

An EIS integration is a server-to-server connection between your certified invoicing system (CAS, CBA or CRM/POS) and the BIR. Your system authenticates once every few hours, then sends batches of signed and encrypted invoices, then checks whether each one passed validation.

ProtocolHTTPS + JSON
Token life6 hours
Clock drift±10 min
Per request1–100 invoices
Items per invoice1–1,000
Deadline to send3 days

Environments

Sandbox and production

EnvironmentBase URLWho can call itUse
Certification / sandboxhttps://eis-cert.bir.gov.phApproved portal accounts with sandbox accessKeys, mandatory tests, certificate and PTT requests
Productionhttps://eis.bir.gov.phHolders of a PTT, from whitelisted IPs onlyLive invoice transmission

The mandatory sandbox tests are Authentication (2 steps), Invoice Issuance (1 step, or 3 with callback) and Inquiry Result (2 steps). You must pass all of them before requesting the EIS Certificate.

Authentication

Getting an auth token

  1. Generate a session key

    Create a random 32-byte AES-256 key in memory. It encrypts everything you send and receive until the token expires.

  2. Encrypt the login body with the BIR public key

    Put your user ID, password and the session key in a JSON body and encrypt it with RSA using the BIR public key from the portal. RSA is used for this call only.

  3. Call the authentication endpoint

    Send the encrypted body with the common headers. The response, encrypted with your session key, contains the auth token and its expiry.

  4. Reuse the token, refresh before expiry

    Send the token on every call for up to 6 hours. Request a new one shortly before it expires, or set forceRefreshToken to replace an active token.

POST/api/authentication

Get an auth token

// Headers: accreditationId, applicationId, datetime, Authorization (HMAC)
{
  "data": "base64( RSA_OAEP(BIR_PUBLIC_KEY, json_body) )"
}

Request headers

Headers and the HMAC signature

HeaderDescription
accreditationIdrequiredYour EIS certification / accreditation identifier
applicationIdrequiredID of the application you created on the Certification Portal
datetimerequiredCurrent timestamp, within ±10 minutes of BIR server time
AuthorizationrequiredHMAC-SHA256 signature of the request, keyed with your Application Key
authTokenafter authToken from the authentication call, valid for 6 hours
Content-Typerequiredapplication/json

The HMAC proves the request came from your application and was not altered on the way. Your system builds a string from request values (such as the IDs, the datetime and the body), signs it with the Application Key, and puts the result in Authorization. The exact string-to-sign is defined in the API Guide.

Common failure

Servers with a drifting clock get every request refused. Sync your transmitting servers with NTP and send the datetime header in the format the API Guide specifies.

Endpoints

Submitting invoices and reading results

POST/api/invoices

Submit e-invoices

Send 1 to 100 signed invoices per call. submitId identifies the batch on your side and must be unique. EIS accepts the batch, returns a reference number, and validates each invoice on its own.

// Headers: accreditationId, applicationId, datetime, Authorization, authToken
{
  "submitId": "SUB-20261007-000123",
  "data": "AES256(sessionKey, [ JWS(invoice_1), JWS(invoice_2), ... ])"
}
POST/api/inquiry-result

Check validation results

Look up a submission by reference number. Each invoice in the batch returns its own result code.

{
  "data": "AES256(sessionKey, { \"refNo\": \"EIS2026100700045821\" })"
}
POSTyour-callback-url

Result callback (optional)

If you register a callback URL, EIS pushes the validation result to your server instead of you polling. The Invoice Issuance sandbox test then has 3 steps instead of 1. Your endpoint must be reachable over HTTPS and should acknowledge quickly, then process the result.

Request sequence

End-to-end request flow

sequenceDiagram
  participant S as Your system
  participant E as BIR EIS
  S->>E: Authenticate (RSA-encrypted session key)
  E-->>S: authToken (valid 6h)
  S->>S: Invoice to JSON, sign (JWS), encrypt (AES-256)
  S->>E: Submit 1-100 invoices + HMAC header
  E-->>S: Accepted (refNo)
  S->>E: Inquire result (refNo)
  E-->>S: Per-invoice code (SUC001 / SYN / ERR)
      

e-Invoice JSON v2.01

Invoice field reference

The same structure serves CAS and CRM/POS invoices; POS invoices also carry the PTU number. When a field doesn't apply, strings take null or blank and numbers take 0.00.

EisUniqueId (24 characters)

20261007
Issue date · YYYYMMDD
A1B2C3D4
EIS Cert ID · 8 chars
0000012F
Control value · 8 chars

The date part must match IssueDtm (else ERR002). Reusing an ID returns SYN003. Build or decode one →

Document

FieldTypeDescription
CompInvoiceIdstringYour own invoice number as printed on the invoice
IssueDtmdateIssue date. Cannot be later than transmission; must match the EisUniqueId date
EisUniqueIdstring(24)Unique EIS identifier for this invoice
DocTypecodeSales Invoice, Debit Memo, Credit Memo, Service Billing or Official Receipt
TransClasscodeVATable, Zero-Rated or VAT Exempt. Mixed classes need separate invoices
CorrYNY / NWhether this invoice corrects a previous one
CorrectionCdcodeType of correction, when CorrYN is Y
PrevUniqueIdstring(24)EisUniqueId of the invoice being corrected
Rmk1stringRemarks
PtuNumstringPermit to Use number (CRM/POS invoices)

SellerInfo

FieldTypeDescription
Tin9 digitsSeller TIN without dashes or branch code, e.g. 123456789
BranchCd5 digitsIssuing branch. 00000 is the head office
TypecodeVAT registration type (VAT or non-VAT)
RegNmstringRegistered name per BIR Form 2303
BusinessNmstringTrade or business name
EmailstringSeller email
RegAddrstringRegistered address

BuyerInfo

FieldTypeDescription
Tin · BranchCd9 · 5 digitsBuyer TIN and branch. Required for B2B; null convention when the buyer has none
RegNm · BusinessNmstringBuyer registered and business names
Email · RegAddrstringBuyer email and registered address
DevAddrstringDelivery address
AirNum · AirNumDtstring · dateAir waybill number and date (shipped goods)
LadNum · LadNumDtstring · dateBill of lading number and date (shipped goods)

ItemList (1 to 1,000 items)

FieldTypeDescription
Nm · DescstringItem name and description
Qty · Unitnumber · stringQuantity and unit of measure
UnitCostnumberUnit price, net of VAT for VATable items
SalesAmtnumberQty × UnitCost, net of VAT
RegDscntAmtnumberRegular discount on the item
SpeDscntAmtnumberSpecial discount on the item (e.g. SC/PWD)
NetSalesnumberSalesAmt − RegDscntAmt − SpeDscntAmt

Totals, discounts and taxes

FieldTypeDescription
TotNetItemSalesnumberSum of item NetSales
Discount.ScAmt · PwdAmtnumberSenior citizen and PWD discounts
Discount.RegAmt · SpeAmtnumberRegular and other special discounts
Discount.Rmk2stringDiscount remarks
OtherTaxRevnumberOther taxable revenue
TotNetSalesAftDisctnumberNet sales after discounts; the VAT base
VATAmtnumber12% of the VAT base for VATable sales; 0.00 for zero-rated or exempt
WithholdIncomenumberCreditable withholding income tax deducted by the buyer
WithholdBusVAT · WithholdBusPTnumberWithheld business VAT and percentage tax
OtherNonTaxChargenumberNon-taxable charges
NetAmtPaynumberAmount payable after VAT, withholding and other charges
ForCur.Currency · ConvRate · ForexAmtstring · numberForeign currency, conversion rate and foreign amount

Example

Sample CAS invoice

A VATable B2B sale with two items and 1% creditable withholding. Code values are illustrative. Load it into the validator to see each check pass.

{
  "CompInvoiceId": "SI-000123",
  "IssueDtm": "20261007",
  "EisUniqueId": "20261007A1B2C3D40000012F",
  "DocType": "SI",
  "TransClass": "VT",
  "CorrYN": "N", "CorrectionCd": null, "PrevUniqueId": null, "Rmk1": "",
  "SellerInfo": {
    "Tin": "123456789", "BranchCd": "00000", "Type": "V",
    "RegNm": "Sample Trading Corp.", "BusinessNm": "Sample Trading",
    "Email": "billing@sample.ph", "RegAddr": "123 Ayala Ave, Makati City"
  },
  "BuyerInfo": {
    "Tin": "987654321", "BranchCd": "00000",
    "RegNm": "Example Retail Inc.", "BusinessNm": "Example Retail",
    "Email": "ap@example.ph", "RegAddr": "45 Ortigas Ave, Pasig City", "DevAddr": "",
    "AirNum": "", "AirNumDt": "", "LadNum": "", "LadNumDt": ""
  },
  "ItemList": [
    { "Nm": "Thermal paper roll 80mm", "Desc": "Box of 50", "Qty": 100, "Unit": "box",
      "UnitCost": 25.00, "SalesAmt": 2500.00, "RegDscntAmt": 0.00, "SpeDscntAmt": 0.00, "NetSales": 2500.00 },
    { "Nm": "Receipt printer", "Desc": "USB/LAN", "Qty": 2, "Unit": "pc",
      "UnitCost": 4750.00, "SalesAmt": 9500.00, "RegDscntAmt": 0.00, "SpeDscntAmt": 0.00, "NetSales": 9500.00 }
  ],
  "TotNetItemSales": 12000.00,
  "Discount": { "ScAmt": 0.00, "PwdAmt": 0.00, "RegAmt": 0.00, "SpeAmt": 0.00, "Rmk2": "" },
  "OtherTaxRev": 0.00,
  "TotNetSalesAftDisct": 12000.00,
  "VATAmt": 1440.00,
  "WithholdIncome": 120.00, "WithholdBusVAT": 0.00, "WithholdBusPT": 0.00,
  "OtherNonTaxCharge": 0.00,
  "NetAmtPay": 13320.00,
  "ForCur": { "Currency": "PHP", "ConvRate": 1.00, "ForexAmt": 0.00 },
  "PtuNum": ""
}

Security

Signing and encryption in code

AES-256 encryption confidentiality · session key
JWS signature integrity & origin · your private key
Invoice JSON CAS or CRM/POS v2.01
// npm i jose · Algorithms, AES mode and the HMAC string-to-sign are placeholders:
// take the exact values from the official EIS API Guide.
import { CompactSign, importPKCS8 } from 'jose';
import crypto from 'node:crypto';

// 1) Login body, RSA-encrypted with the BIR public key (auth call only)
const sessionKey = crypto.randomBytes(32);
const loginData = crypto.publicEncrypt(
  { key: BIR_PUBLIC_KEY_PEM, padding: crypto.constants.RSA_PKCS1_OAEP_PADDING, oaepHash: 'sha256' },
  Buffer.from(JSON.stringify({ userId, password, sessionKey: sessionKey.toString('base64'), forceRefreshToken: false }))
).toString('base64');

// 2) Sign each invoice as a JWS with your private signing key
const signingKey = await importPKCS8(process.env.EIS_SIGNING_KEY, 'RS256');
const jws = await new CompactSign(new TextEncoder().encode(JSON.stringify(invoice)))
  .setProtectedHeader({ alg: 'RS256' })
  .sign(signingKey);

// 3) Encrypt the batch with the session key
function aesEncrypt(key, text) {
  const iv = crypto.randomBytes(16);
  const c = crypto.createCipheriv('aes-256-cbc', key, iv);
  return Buffer.concat([iv, c.update(text, 'utf8'), c.final()]).toString('base64');
}
const body = { submitId, data: aesEncrypt(sessionKey, JSON.stringify([jws])) };

// 4) HMAC-SHA256 Authorization header, keyed with the Application Key
const datetime = new Date().toISOString();
const toSign = [accreditationId, applicationId, datetime, JSON.stringify(body)].join('');
const authorization = crypto.createHmac('sha256', APP_KEY).update(toSign).digest('base64');
Keys

The private signing key is shown once on the portal. Keep it in a secrets manager or HSM, never in source control, and never paste a production key into a web tool. Use sandbox keys for testing.

Troubleshooting

EIS API response codes

CodeStatusMeaningWhat to fix
SUC001AcceptedAll validation checks passedNothing. Store the result with the invoice
SYN002RejectedInvalid digital signatureCheck the JWS algorithm and signing key, and that the payload wasn't changed after signing
SYN003RejectedDuplicate EisUniqueIdGenerate a new control value; never resend an accepted ID
SYN004RejectedSchema errorMissing or extra fields, wrong data type or format
ERR001RejectedSeller TIN not registeredConfirm the 9-digit TIN and branch code match BIR records
ERR002RejectedInvalid issuance datetimeDate is later than transmission or doesn't match the EisUniqueId date
ERR004RejectedTotal sales / VAT errorRe-check totals; VAT must be 0.00 for exempt or zero-rated items

Catch SYN004, ERR002 and ERR004 before you submit →

Before go-live

Go-live checklist

  • All sandbox tests passed

    Authentication, Invoice Issuance and Inquiry Result, on the Certification Portal.

  • EIS Certificate and PTT approved

    EIS Certification Number issued and Permit to Transmit approved by email.

  • Production IPs whitelisted

    Fixed public IPs of every transmitting server registered on the portal.

  • Keys stored securely

    Signing private key and Application Key in a secrets manager, with rotation documented.

  • Servers synced to NTP

    Clock drift stays well inside ±10 minutes.

  • Token refresh automated

    New token requested before the 6-hour expiry.

  • Retry and resubmission flow

    Rejected invoices are fixed and resent within the 3-day window; network failures retry without creating duplicate EisUniqueIds.

  • Results stored for 10 years

    Invoice JSON, JWS, BIR reference numbers and result codes kept with the audit trail.