# A first 271, explained

> An eligibility question written as a 270, answered by the eligibility sandbox as a 271, and that 271 said per patient in words.

Page: https://payerworks.com/docs/quickstart-first-271 · Markdown: https://payerworks.com/docs/quickstart-first-271.md

> Payerworks writes and explains files; it sends nothing to a payer. Every file a route writes says `transmitted: false`, and is yours to send on your own connection. A test key is for invented data only, never a real patient.

## What you need

- A test key, from [the developers page](https://payerworks.com/developers). It is for invented data only.
- Node 18 or later, the JavaScript client [payerworks.mjs](https://payerworks.com/sdk/payerworks.mjs), and [sample-data.mjs](https://payerworks.com/docs/examples/sample-data.mjs), the invented patient and clinic every example uses, in one folder.
- Two environment variables: `PAYERWORKS_API_KEY` (your key) and `PAYERWORKS_BASE_URL` (the base URL shown with your key).

## The steps

1. Write the question as a 270 with POST /v1/eligibility/270: the payer, the provider, the subscriber, the day and the service types, as the JSON most clearinghouse APIs take. The 270 is yours to send on your own connection.
2. Send the same question to the eligibility sandbox (POST /v1/sandbox/eligibility). It answers as a payer would, with a 271 in `files.eligibility_271`.
3. Explain that 271 with POST /v1/eligibility/explain, naming what you asked about in `asked`. Read `members[0].coverage.state`, then each service’s deductible and out-of-pocket figures, in and out of network.
4. A member ID ending in NOTFOUND is not found, BADDOB has a birth date that does not match: each refusal is said as its reason and the field to fix.

## The code

[eligibility.mjs](https://payerworks.com/docs/examples/eligibility.mjs) runs every step below against the API with a test key. It needs [payerworks.mjs](https://payerworks.com/sdk/payerworks.mjs) and [sample-data.mjs](https://payerworks.com/docs/examples/sample-data.mjs) beside it.

eligibility.mjs

```js
// Payerworks example: eligibility, a 270 written and a 271 explained. Docs: https://payerworks.com/docs/eligibility
//
// Run it with Node 18 or later, with the JavaScript client (https://payerworks.com/sdk/payerworks.mjs)
// and sample-data.mjs beside this file:
//   PAYERWORKS_API_KEY=pw_test_... PAYERWORKS_BASE_URL=<the base URL shown with your key> node eligibility.mjs
// A test key and invented data only. Payerworks sends nothing to a payer: every file it writes is yours.
import { pathToFileURL } from 'node:url';
import { Payerworks, PayerworksError } from './payerworks.mjs';
import { ELIGIBILITY_QUESTION, SENDER_ID, PAYER_ID, copy, endingIn, refusalOf } from './sample-data.mjs';

/** @param {Payerworks} pw */
export async function run(pw) {
  // 1. Write the question as a 270. The file is yours to send on your own connection.
  const written = await pw.postEligibility270({ sender_id: SENDER_ID, receiver_id: PAYER_ID, control_number: 12, request: copy(ELIGIBILITY_QUESTION) });

  // 2. The eligibility sandbox answers the same question as a payer would: a 270 and its 271.
  const sandbox = await pw.postSandboxEligibility({ request: copy(ELIGIBILITY_QUESTION) });
  const the271 = sandbox.files.eligibility_271;

  // 3. Explain the 271 per patient, for the services and the day you asked about.
  const explained = await pw.postEligibilityExplain({ x12: the271, asked: { service_type_codes: ['30'], date_of_service: '2026-10-20' } });
  const member = explained.members[0];

  // 4. A member ID ending in NOTFOUND: the payer cannot find the subscriber, and the answer says why in words.
  const notFound = await pw.postSandboxEligibility({ request: endingIn(ELIGIBILITY_QUESTION, 'NOTFOUND') });

  // 5. The failure path: an NPI that fails its check digit is refused before anything is written.
  const refused = await refusalOf(() => pw.postEligibility270({
    sender_id: SENDER_ID, receiver_id: PAYER_ID, control_number: 13,
    request: { ...copy(ELIGIBILITY_QUESTION), provider: { organizationName: 'SAMPLE FAMILY MEDICINE', npi: '1234567890' } },
  }), { PayerworksError });

  return {
    written: { transmitted: written.transmitted, starts: written.x12.slice(0, 3) },
    coverage: member.coverage.state,
    not_found: notFound.outcomes[0].outcome,
    refused,
  };
}

// Run as a script: node <this file>, with PAYERWORKS_API_KEY and PAYERWORKS_BASE_URL set.
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
  console.log(JSON.stringify(await run(new Payerworks()), null, 2));
}
```

What it answered, run against the API in Payerworks’ own tests (your request ids will differ)

```json
{
  "written": {
    "transmitted": false,
    "starts": "ISA"
  },
  "coverage": "active",
  "not_found": "subscriber_not_found",
  "refused": {
    "status": 422,
    "code": "invalid_requests",
    "request_id": "req_5"
  }
}
```

## What you should see

- `coverage` is active; `not_found` is the sandbox’s outcome for NOTFOUND; `refused` is a 270 with an NPI that fails its check digit, refused before anything is written.

## Next

- Use a real 271 the same way: explain accepts any 271, as X12 or as JSON. [Eligibility](https://payerworks.com/docs/eligibility) has every field.
