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. It is for invented data only.
- Node 18 or later, the JavaScript client payerworks.mjs, and sample-data.mjs, the invented patient and clinic every example uses, in one folder.
- Two environment variables:
PAYERWORKS_API_KEY(your key) andPAYERWORKS_BASE_URL(the base URL shown with your key).
The steps
- 1. Create the provider once with POST /v1/providers: its name, NPI, tax id and a contact. Enrollment is the one part of the API that keeps what you send; it is for a practice’s business facts, never a patient’s.
- 2. Request enrollment with the sandbox payer: POST /v1/enrollments with
payer.idPWSANDBOX, a transaction, andsubmit: trueto hand it to Payerworks at once. - 3. The last word of the provider’s name picks the sandbox payer’s scenario. SLOW waits with the payer until you advance it with POST /v1/sandbox/enrollments/{id}/advance; TASKS raises tasks for you to answer; REJECT is refused with the payer’s words.
- 4. Every move is an event, and GET /v1/enrollments/{id} answers where the request is and whose turn it is.
The code
enrollment.mjs runs every step below against the API with a test key. It needs payerworks.mjs and sample-data.mjs beside it.
// Payerworks example: transaction enrollment with the sandbox payer. Docs: https://payerworks.com/docs/enrollment
//
// 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 enrollment.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 { PROVIDER, ENROLLMENT_CONTACT, copy, refusalOf } from './sample-data.mjs';
/** @param {Payerworks} pw */
export async function run(pw) {
// 1. The provider, once. Enrollment keeps what you send (a practice's business facts, never a patient's).
// The sandbox payer reads the last word of the provider's name: SLOW waits with the payer until you advance it.
const provider = await pw.postProviders({ ...copy(PROVIDER), name: `${PROVIDER.name} SLOW` });
// 2. Ask the sandbox payer PWSANDBOX for its remittances, and hand the request to Payerworks at once.
const requested = await pw.postEnrollments({
provider_id: provider.id, payer: { id: 'PWSANDBOX' }, transaction: 'remittances',
primary_contact: copy(ENROLLMENT_CONTACT), notify_email: 'dev@sampleclinic.example', submit: true,
});
// 3. The sandbox payer's next move: with the payer, then live. Each move is an event too.
const advanced = await pw.postSandboxEnrollmentsByIdAdvance(requested.id);
// 4. The failure path: a live request has nothing left for the sandbox payer to do.
const refused = await refusalOf(() => pw.postSandboxEnrollmentsByIdAdvance(requested.id), { PayerworksError });
return { submitted: requested.status, moved: advanced.moved, now: advanced.enrollment.status, events: advanced.events.map((e) => e.type), 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));
}
{
"submitted": "with_payer",
"moved": {
"from": "with_payer",
"to": "live"
},
"now": "live",
"events": [
"enrollment.live"
],
"refused": {
"status": 409,
"code": "sandbox_nothing_to_advance",
"request_id": "req_4"
}
}What you should see
submittedis with_payer; the advance moves it to live and makes one event;refusedis a second advance, with nothing left for the sandbox payer to do.
Next
- A real payer’s request waits with Payerworks today: Payerworks is registered with no payer yet. Transaction enrollment has every status.