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. Check the claim with POST /v1/claims/validate. A claim that validates is well formed and valid on its date; it is not yet paid.
- 2. Send it to the sandbox payer with POST /v1/sandbox/claims. One call answers what a payer and its front end would over days: a 999 for the file, a 277CA for each claim, and an 835 for every claim it adjudicated, each already explained.
- 3. Read the explained answers:
explained.acknowledgment_999,explained.claim_acknowledgment_277caandexplained.remittance. Each file is also infiles, and reads the same when you explain it again later. - 4. Change how the member ID ends to see another answer: REJ is rejected at the 277CA, DENY is denied on the 835, PEND waits with no 835. The whole list is on the claims page.
The code
sandbox-claim.mjs runs every step below against the API with a test key. It needs payerworks.mjs and sample-data.mjs beside it.
// Payerworks example: a sandbox claim, to its 835. Docs: https://payerworks.com/docs/quickstart-sandbox-claim
//
// 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 sandbox-claim.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 { SENDER_ID, claimEndingIn, refusalOf } from './sample-data.mjs';
/** @param {Payerworks} pw */
export async function run(pw) {
// 1. Check the claim first: a claim that validates is well formed, not yet paid.
const claim = claimEndingIn('');
const checked = await pw.postClaimsValidate({ claim });
// 2. The sandbox payer answers it in one call: a 999 for the file, a 277CA for the claim, an 835 for the money.
const run1 = await pw.postSandboxClaims({ sender_id: SENDER_ID, claims: [claim] });
const { acknowledgment_999: file, claim_acknowledgment_277ca: ack, remittance: paid } = run1.explained;
// 3. Each file is also yours to read again later: the 835 explained from the file alone.
const again = await pw.postRemittancesExplain({ x12: run1.files.remittance_835 });
// 4. The failure path: the same reference twice in one file is refused, because answers match back on it.
const refused = await refusalOf(() => pw.postSandboxClaims({ sender_id: SENDER_ID, claims: [claim, claim] }), { PayerworksError });
return {
valid: checked.valid,
file: file.groups[0].verdict,
claim: ack.claims[0].verdict,
paid: paid.claims[0].paid,
same_reading: again.claims[0].paid === paid.claims[0].paid,
transmitted: run1.transmitted,
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));
}
{
"valid": true,
"file": "A",
"claim": "A",
"paid": 103.2,
"same_reading": true,
"transmitted": false,
"refused": {
"status": 422,
"code": "duplicate_reference",
"request_id": "req_4"
}
}What you should see
fileandclaimare A, accepted;paidis what the 835 paid;refusedis the failure path, the same reference sent twice.
Next
- Set a webhook and the same run posts each answer to you as an event: Following an event.
- Track the claim from the files you hold with POST /v1/claims/track: Acknowledgments.