Skip to content

Quickstart

Following an event

A webhook set, a sandbox run that makes events, each signature checked on your own server, and the event log read back.

Read as markdown

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) and PAYERWORKS_BASE_URL (the base URL shown with your key).

The steps

  1. 1. Set your webhook with PUT /v1/account/webhook: an https address at a public hostname. The answer shows its signing secret once; store it.
  2. 2. Run the claims sandbox. Each answer is recorded as an event on your account and posted to your webhook: the 999, each claim’s 277CA, and each check’s 835.
  3. 3. On your server, check each delivery’s signature over the raw body before you parse it (readDelivery in the example), and skip a webhook-id you have already handled: a delivery may arrive more than once.
  4. 4. List what was recorded with GET /v1/events, read one with GET /v1/events/{id}, and send one again with POST /v1/events/{id}/redeliver. Events are kept for 30 days.

The code

events.mjs runs every step below against the API with a test key. It needs payerworks.mjs and sample-data.mjs beside it.

events.mjsJavaScript
// Payerworks example: events, signed, listed and sent again. Docs: https://payerworks.com/docs/events
//
// 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 events.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, verifyStandardWebhook } from './payerworks.mjs';
import { SENDER_ID, claimEndingIn, refusalOf } from './sample-data.mjs';

/**
 * On YOUR server, for each delivery: check the signature over the raw body, before you parse it.
 * `secret` is the whsec_ secret PUT /v1/account/webhook answered once; `headers` the request's headers.
 * A delivery may arrive more than once: skip a webhook-id you have handled.
 * @param {string} secret @param {Record<string, string>} headers @param {string} rawBody
 */
export function readDelivery(secret, headers, rawBody, seen = new Set()) {
  if (!verifyStandardWebhook(secret, headers, rawBody)) return { ok: false, reason: 'signature' };
  const id = headers['webhook-id'];
  if (seen.has(id)) return { ok: true, duplicate: true };
  seen.add(id);
  return { ok: true, event: JSON.parse(rawBody) };
}

/** @param {Payerworks} pw */
export async function run(pw) {
  // 1. Your webhook: an https address of yours. The signing secret is shown once: store it.
  const hook = await pw.putAccountWebhook({ url: 'https://hooks.example.com/payerworks' });

  // 2. A sandbox run makes events: the 999, each claim's 277CA, and each check's 835.
  const sandbox = await pw.postSandboxClaims({ sender_id: SENDER_ID, claims: [claimEndingIn('')] });

  // 3. Every event is kept for 30 days: list them, read one, and send one again.
  const listed = await pw.getEvents({ query: { limit: 10 } });
  const one = await pw.getEventsById(listed.data[0].id);
  const again = await pw.postEventsByIdRedeliver(one.id);

  // 4. The failure path: an id this key never had.
  const refused = await refusalOf(() => pw.getEventsById(`evt_${'0'.repeat(24)}`), { PayerworksError });

  return {
    secret_starts: hook.secret.slice(0, 6),
    made: sandbox.events.map((e) => e.type),
    listed: listed.data.length,
    redelivered: Boolean(again),
    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
{
  "secret_starts": "whsec_",
  "made": [
    "sandbox.file.acknowledged",
    "sandbox.claim.acknowledged",
    "sandbox.remittance.received"
  ],
  "listed": 3,
  "redelivered": true,
  "refused": {
    "status": 404,
    "code": "event_not_found",
    "request_id": "req_6"
  }
}

What you should see

  • made lists the three event types one paid claim makes; refused is an event id the key never had.

Next

Talk to us

What happens next

  1. 1

    A person at Payerworks reads what you sent, usually within a business day.

  2. 2

    One reply by email names the next step: our trading partner details, where each of your payers stands, or a key for the API.

  3. 3

    Nothing follows unless you answer. There is no sequence behind this form.

Or write to hello@payerworks.com.

Talk to Payerworks

Who you are and what you want to connect. A person replies by email, usually within a business day, and there is no follow-up sequence.

Used to reply to you and for nothing else.