What a 270/271 Eligibility Check Returns in JSON
A 270/271 eligibility transaction is the standard EDI format for real-time insurance verification. The 270 is the request you send to a payer. The 271 is the response you get back.
The problem: raw X12 271 responses are not human-readable, and they're not machine-friendly either — at least not without a parser. Here's what a 270/271 transaction actually contains, and what that looks like when it's returned as clean JSON through a modern eligibility API.
What the 270 Request Contains
The 270 (Eligibility Benefit Inquiry) sends the payer a question: "Is this patient covered, and what are their benefits?"
Required fields:
- NPI — the National Provider Identifier of the requesting provider
- Member ID — the patient's insurance ID from their card
- Payer ID — identifies the insurance company (e.g.,
00001for Blue Cross) - Patient name — first name, last name
- Date of birth — used to match the member record
- Date of service (optional) — some payers return benefit-specific responses tied to a service date
What the 271 Response Contains
The 271 (Eligibility Benefit Information) is the payer's answer. Raw, it looks like this:
ISA*00* *00* *ZZ*ELIGIBILITY *ZZ*BCBS *260501*1200*^*00501*000000001*0*P*:~
GS*HB*ELIGIBILITY*BCBS*20260501*1200*1*X*005010X279A1~
ST*271*0001*005010X279A1~
BHT*0022*11*10001234*20260501*1200~
HL*1**20*1~
NM1*PR*2*BLUE CROSS BLUE SHIELD*****PI*00001~
HL*2*1*21*1~
NM1*1P*2*ACME MEDICAL GROUP*****XX*1234567890~
HL*3*2*22*0~
NM1*IL*1*DOE*JANE****MI*XYZ123456~
DTP*346*D8*20260101~
EB*1*IND*30*MC*BLUE CROSS PPO SELECT****30~
EB*C*IND*30**CALENDAR YEAR DEDUCTIBLE*****1500~
EB*G*IND*30**CALENDAR YEAR DEDUCTIBLE*****400~
SE*14*0001~
GE*1*1~
IEA*1*000000001~
Nobody wants to parse that mid-conversation.
The Same Data as JSON
Through Eligibility.dev, the same 271 response is returned as structured JSON:
{
"coverage_status": "active",
"plan_name": "Blue Cross PPO Select",
"group_number": "GRP-00123",
"member_id": "XYZ123456",
"effective_date": "2026-01-01",
"termination_date": null,
"payer_name": "Blue Cross Blue Shield",
"payer_id": "00001",
"deductible_individual": 1500,
"deductible_individual_met": 400,
"deductible_individual_remaining": 1100,
"deductible_family": 3000,
"deductible_family_met": 400,
"deductible_family_remaining": 2600,
"out_of_pocket_max_individual": 5000,
"out_of_pocket_max_individual_met": 400,
"out_of_pocket_max_individual_remaining": 4600,
"copay_primary_care": 30,
"copay_specialist": 60,
"coinsurance": 20,
"service_type": "30"
}
Same data. No EDI parser required.
Key Fields and What They Mean
coverage_status
Whether the patient has active coverage. Values: active, inactive, unknown. Branch on this first — if it's not active, route to manual verification before booking.
deductible_individual / deductible_individual_remaining
The patient's annual deductible and how much is left to meet. If the remaining amount is high, surface it before the visit so the practice can collect a payment estimate.
out_of_pocket_max_individual_remaining
How much the patient still owes before the payer covers 100%. Patients near their out-of-pocket max are low collection risk.
copay_primary_care / copay_specialist
The fixed amount the patient pays per visit. Practices collect this at check-in.
coinsurance
The percentage the patient pays after the deductible is met. Common values: 10, 20, 30 (percent).
effective_date
When coverage started. If this is in the future, the patient isn't covered yet.
termination_date
When coverage ends. null means no end date on file (ongoing coverage).
service_type
The X12 service type code. 30 is Health Benefit Plan Coverage (general). You can request specific service types — professional, inpatient, outpatient — depending on the visit type.
Why This Matters for AI Agents
A Voice AI agent can read coverage_status and respond naturally in under a second:
active→ "Your Blue Cross coverage is active. Your copay for today's visit is $30."inactive→ "I wasn't able to verify active coverage with that insurance. Let me connect you with our billing team."unknown→ "We had trouble confirming your coverage. Can you double-check your member ID?"
The agent doesn't need to understand EDI. It reads JSON fields and branches accordingly.
Making the Request
You don't send a raw 270 transaction. You call a REST endpoint:
GET /api/eligibility/check
Authorization: Bearer <your-api-key>
{
"npi": "1234567890",
"member_id": "XYZ123456",
"payer_id": "00001",
"first_name": "Jane",
"last_name": "Doe",
"date_of_birth": "1985-04-12"
}
Eligibility.dev builds the X12 270, sends it to the payer, parses the 271, and returns the JSON. You get the data in under 1 second without touching EDI.
Testing Without a Real Payer
The mock endpoint returns a realistic 271-equivalent JSON response without hitting a real payer:
GET https://www.eligibility.dev/api/eligibility/check/mock
Use it to build your parsing logic and test your workflow branches before you go live.
FAQ
Do I need to understand X12 EDI to use this API?
No. Eligibility.dev handles all EDI translation. You send JSON, you receive JSON.
What's a payer ID?
A 5-digit code that identifies the insurance company. The full list of supported payers and their IDs is at eligibility.dev/payers.
Can I request a specific service type?
Yes. Pass a service_type field in the request body with the X12 service type code for the visit type you're checking.
How quickly does the response come back?
Under 1 second for most payers. A small number of payers have slower response times — these are documented in the payer list.
What if the payer returns an error instead of benefit data?
Common errors: member not found, NPI not on file, payer unavailable. The API returns structured error codes so your workflow can handle each case without crashing.