Skip to content

Docs: by job

Keys and your account

How a call is authorized, what each answer carries, and the routes that manage your keys and your account.

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.

Every call but GET /v1/health sends a key as Authorization: Bearer pw_test_… or pw_live_…. A test key is free from the developers page, for invented data only, and writes test files only; a live key needs a signed business associate agreement first. Your key is a bearer key: keep it on your server, never in browser code.

Every answer carries x-request-id, and every refusal carries the same id as request_id inside the error. Quote it when you write to us. A POST, and PUT /v1/account/webhook, may carry an Idempotency-Key, unless its route says it takes none: a retry with the same key and request within 24 hours is answered as the first call was, by running it again, because Payerworks never keeps an answer.

Routes

Each route shows its call with curl and with the two clients, then its real answer, shortened, and the fields it holds. The client calls assume one client made once, const pw = new Payerworks() in JavaScript or pw = payerworks.Payerworks() in Python, each reading PAYERWORKS_API_KEY and PAYERWORKS_BASE_URL, and body is the request.json shown.

GET/v1/health

Health

Whether the API is answering. No key needed.

Request

curl -sS -X GET "$PAYERWORKS_BASE_URL/v1/health"
The answer (200)JSON
{
  "ok": true,
  "service": "Payerworks",
  "version": "v1",
  "transmits": false
}
Field, Type, What it is
FieldTypeWhat it is
okboolean
servicestring
versionstring
transmitsthe value falseNo route transmits to a payer yet.

GET/v1/account

Your account

The key’s account, label, mode and rate, the calls it made on each day of this month (counted by UTC day) and the calls refused before they ran, and its webhook if one is set, with what its last delivery did.

Request

curl -sS -X GET "$PAYERWORKS_BASE_URL/v1/account" \
  -H "Authorization: Bearer $PAYERWORKS_API_KEY"
The answer (200)JSON
{
  "key_id": "pwk_0123456789abcdef",
  "account": "Sample Billing Co",
  "label": "Self-serve",
  "mode": "test",
  "rpm": 60,
  "usage": {
    "month": "2026-10",
    "days": [
      {
        "date": "2026-10-18",
        "calls": 12,
        "refused": 0
      },
      {
        "date": "2026-10-19",
        "calls": 4,
        "refused": 1
      }
    ],
    "total": 16,
    "refused": 1
  },
  "webhook": {
    "url": "https://hooks.example.com/payerworks/events",
    "secret_last_four": "Osk=",
    "created_at": "2026-10-19T15:00:00.000Z",
    "previous_secret_expires_at": null,
    "last_delivery": {
      "at": "2026-10-19T15:00:00.000Z",
      "trigger": "sandbox",
      "first_event_id": "evt_cc264f7536a9315a0c6fe09f",
      "events": 3,
      "delivered": 3,
      "failed": 0,
      "status": 200,
      "error": null
    }
  }
}
Field, Type, What it is
FieldTypeWhat it is
key_idstring
accountstring
labelstring
modeone of "test", "live"
rpmintegerCalls a minute.
usageobjectThis month to date, by UTC day.
webhookobject or null

GET/v1/account/contact

Your notice address

Where Payerworks emails you about this key: when one of its webhook destinations keeps failing, and when one of its enrollment requests moves without your doing it. A test key from this page starts with the address its link was sent to, the only address it may set.

Request

curl -sS -X GET "$PAYERWORKS_BASE_URL/v1/account/contact" \
  -H "Authorization: Bearer $PAYERWORKS_API_KEY"
The answer (200)JSON
{
  "email": "dev@example.com",
  "updated_at": "2026-10-20T19:12:00.052Z"
}
Field, Type, What it is
FieldTypeWhat it is
emailstring or null
updated_atstring or null

PUT/v1/account/contact

Set your notice address

The address told when a destination has failed for 2 hours, for 24 hours, and when it was disabled after its last attempt, and sent one email for every enrollment request that moved without your doing it inside the same 15 minutes. Send email: null to remove it, and nothing is emailed. Only the address that asked for this account’s test key by email (any key of the account may set it), or null; any other address is refused 403 contact_not_proved. A key issued by Payerworks has its address set by us: write to us.

Request

curl -sS -X PUT "$PAYERWORKS_BASE_URL/v1/account/contact" \
  -H "Authorization: Bearer $PAYERWORKS_API_KEY" \
  -H "Content-Type: application/json" \
  -d @request.json
request.jsonJSON
{
  "email": "dev@example.com"
}
The answer (200)JSON
{
  "email": "dev@example.com",
  "updated_at": "2026-10-20T19:12:00.052Z"
}
Field, Type, What it is
FieldTypeWhat it is
emailstring or null
updated_atstring or null

GET/v1/keys

Your account’s keys

Every key of your account in your key’s own mode (a test key lists the test keys, a live key the live ones): its name, mode, last four characters, when it was made, when it expires, when it was last rotated, until when its previous secret is accepted, whether it has expired, when it was revoked, and which one is the key asking, beside the account’s id. A revoked key is listed too. Never a key itself.

Request

curl -sS -X GET "$PAYERWORKS_BASE_URL/v1/keys" \
  -H "Authorization: Bearer $PAYERWORKS_API_KEY"
The answer (200)JSON
{
  "account_id": "pwk_0123456789abcdef01",
  "data": [
    {
      "key_id": "pwk_0123456789abcdef01",
      "name": "Server",
      "mode": "test",
      "last_four": "aaaa",
      "created_at": "2026-10-19T12:00:00.000Z",
      "expires_at": null,
      "expired": false,
      "revoked_at": null,
      "rotated_at": null,
      "previous_secret_accepted_until": null,
      "current": true
    },
    {
      "key_id": "pwk_153493376889aa3239d7aab0",
      "name": "CI runner",
      "mode": "test",
      "last_four": "khYc",
      "created_at": "2026-10-20T19:12:00.100Z",
      "expires_at": "2027-01-18T19:12:00.100Z",
      "expired": false,
      "revoked_at": null,
      "rotated_at": null,
      "previous_secret_accepted_until": null,
      "current": false
    }
  ]
}
Field, Type, What it is
FieldTypeWhat it is
account_idstringThe account: the keys one key started.
datalist of AccountKey

POST/v1/keys

Make a key

A named key of your key’s own mode and rate, shown once. expires_in_days (1 to 365) makes it stop on its own. A key never outlives the key that made it: its expiry is the sooner of expires_in_days and the making key’s own, and the making key’s when none is asked. An account holds 3 test keys or 25 live ones that are not revoked. Every key of an account may manage its keys, unless the account’s organization chose members only.

Request

curl -sS -X POST "$PAYERWORKS_BASE_URL/v1/keys" \
  -H "Authorization: Bearer $PAYERWORKS_API_KEY" \
  -H "Content-Type: application/json" \
  -d @request.json
request.jsonJSON
{
  "name": "CI runner",
  "expires_in_days": 90
}
The answer (201)JSON
{
  "key_id": "pwk_153493376889aa3239d7aab0",
  "name": "CI runner",
  "mode": "test",
  "last_four": "khYc",
  "created_at": "2026-10-20T19:12:00.100Z",
  "expires_at": "2027-01-18T19:12:00.100Z",
  "expired": false,
  "revoked_at": null,
  "rotated_at": null,
  "previous_secret_accepted_until": null,
  "current": false,
  "key": "pw_test_pBP8..."
}
Field, Type, What it is
FieldTypeWhat it is
key_idstring
namestring
modeone of "test", "live"
last_fourstring
created_atstring
expires_atstring or null
expiredboolean
revoked_atstring or null
rotated_atstring or null
previous_secret_accepted_untilstring or null
currentbooleanTrue for the key this call was made with.
keystringpw_test_ or pw_live_ and the secret: only in the answer that made it (POST /v1/keys, or a rotation).
overlap_hoursinteger

DELETE/v1/keys/{id}

Revoke a key

The key stops working within a minute, and its SFTP user, if it has one, is removed at once. Revoking a key that is already revoked is not an error.

Request

curl -sS -X DELETE "$PAYERWORKS_BASE_URL/v1/keys/pwk_153493376889aa3239d7aab0" \
  -H "Authorization: Bearer $PAYERWORKS_API_KEY"
The answer (200)JSON
{
  "key_id": "pwk_153493376889aa3239d7aab0",
  "name": "CI runner",
  "mode": "test",
  "last_four": "6NXM",
  "created_at": "2026-10-20T19:12:00.100Z",
  "expires_at": "2027-01-18T19:12:00.100Z",
  "expired": false,
  "revoked_at": "2026-10-20T19:12:00.111Z",
  "rotated_at": "2026-10-20T19:12:00.108Z",
  "previous_secret_accepted_until": "2026-10-21T19:12:00.108Z",
  "current": false
}
Field, Type, What it is
FieldTypeWhat it is
key_idstring
namestring
modeone of "test", "live"
last_fourstring
created_atstring
expires_atstring or null
expiredboolean
revoked_atstring or null
rotated_atstring or null
previous_secret_accepted_untilstring or null
currentbooleanTrue for the key this call was made with.
keystringpw_test_ or pw_live_ and the secret: only in the answer that made it (POST /v1/keys, or a rotation).
overlap_hoursinteger

POST/v1/keys/{id}/rotate

Rotate a key

A new secret for the same key id, shown once, so its webhooks, events, usage and enrollments carry on. The old secret is still accepted for overlap_hours, 0 to 720, 24 by default, and stops at once if the key is revoked. Two rotations at once: the first finishes, and the other answers 409 key_rotation_conflict and makes nothing.

Request

curl -sS -X POST "$PAYERWORKS_BASE_URL/v1/keys/pwk_153493376889aa3239d7aab0/rotate" \
  -H "Authorization: Bearer $PAYERWORKS_API_KEY" \
  -H "Content-Type: application/json" \
  -d @request.json
request.jsonJSON
{
  "overlap_hours": 24
}
The answer (200)JSON
{
  "key_id": "pwk_153493376889aa3239d7aab0",
  "name": "CI runner",
  "mode": "test",
  "last_four": "6NXM",
  "created_at": "2026-10-20T19:12:00.100Z",
  "expires_at": "2027-01-18T19:12:00.100Z",
  "expired": false,
  "revoked_at": null,
  "rotated_at": "2026-10-20T19:12:00.108Z",
  "previous_secret_accepted_until": "2026-10-21T19:12:00.108Z",
  "current": false,
  "key": "pw_test_OOHH...",
  "overlap_hours": 24
}
Field, Type, What it is
FieldTypeWhat it is
key_idstring
namestring
modeone of "test", "live"
last_fourstring
created_atstring
expires_atstring or null
expiredboolean
revoked_atstring or null
rotated_atstring or null
previous_secret_accepted_untilstring or null
currentbooleanTrue for the key this call was made with.
keystringpw_test_ or pw_live_ and the secret: only in the answer that made it (POST /v1/keys, or a rotation).
overlap_hoursinteger

POST/v1/mcp

The MCP server, hosted

The same tools as the downloadable MCP server, over MCP’s Streamable HTTP transport (2026-07-28, and the 2025 handshakes), with your key as the bearer. Each tool call is a call to its route under your key. With a live key no tool is called unless the request carries Payerworks-MCP-Allow-Live-Key: 1. Payerworks transmits nothing.

Request

curl -sS -X POST "$PAYERWORKS_BASE_URL/v1/mcp" \
  -H "Authorization: Bearer $PAYERWORKS_API_KEY" \
  -H "Content-Type: application/json" \
  -d @request.json
request.jsonJSON
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2025-06-18",
    "capabilities": {},
    "clientInfo": {
      "name": "example-client",
      "version": "1"
    }
  }
}
The answer (200)JSON
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2025-06-18",
    "capabilities": {
      "tools": {
        "listChanged": false
      },
      "prompts": {
        "listChanged": false
      }
    },
    "serverInfo": {
      "name": "payerworks",
      "title": "Payerworks",
      "version": "1.0.0"
    },
    "instructions": "Each tool calls one route of the Payerworks API with the key this connection presents. Payerworks validates claims, writes and reads X12 files and explains each answer in plain words. It transmits nothing: no file reaches a payer. post_sand…"
  }
}

Shortened here: lists show their first two items and long strings are cut. The whole answer is this route’s example in /openapi.json.

Field, Type, What it is
FieldTypeWhat it is
jsonrpcthe value "2.0"
idobject
resultobject
errorobjectA JSON-RPC error: never the API’s error shape.

GET/v1/audit-log

Your account’s audit log

Every change to this account, newest first: keys made, rotated, revoked or expired; the webhook, destinations and the notice address; providers, enrollment requests, tasks and documents; the SFTP user and its SSH keys; batch jobs; the organization and its members. Each entry says what, when, who (a key, a member, Payerworks, or Payerworks automatically), through which door, the object’s id, and the fields that changed by name only, never a value; a web address by its host. limit 1 to 100 (25), type (an entry type, or its family before the dot), created_gte and created_lt, starting_after. Each entry is kept 365 days, then deleted, and never changed before then. Every key of the account reads the same log.

Request

curl -sS -X GET "$PAYERWORKS_BASE_URL/v1/audit-log" \
  -H "Authorization: Bearer $PAYERWORKS_API_KEY"
The answer (200)JSON
{
  "object": "list",
  "data": [
    {
      "id": "aud_aeb4acb2fdf610d4bc531306",
      "type": "webhook_destination.removed",
      "words": "Webhook destination removed",
      "at": "2026-10-20T19:12:00.114Z",
      "actor": {
        "type": "key",
        "id": "pwk_0123456789abcdef01"
      },
      "door": "api",
      "object": {
        "kind": "webhook_destination",
        "id": "wd_4e1687f5d8638cbd"
      },
      "changed": [],
      "url_host": null,
      "count": null,
      "request_id": "req_example_15"
    },
    {
      "id": "aud_a08c0b0cd9c2ce25b9ef59ab",
      "type": "key.revoked",
      "words": "API key revoked",
      "at": "2026-10-20T19:12:00.111Z",
      "actor": {
        "type": "key",
        "id": "pwk_0123456789abcdef01"
      },
      "door": "api",
      "object": {
        "kind": "key",
        "id": "pwk_153493376889aa3239d7aab0"
      },
      "changed": [],
      "url_host": null,
      "count": null,
      "request_id": "req_example_14"
    }
  ],
  "has_more": true,
  "next_cursor": "acur_412331373932353233353230313038236175645f663663623031613433613161613366356130353463653832",
  "retention_days": 365
}

Shortened here: lists show their first two items and long strings are cut. The whole answer is this route’s example in /openapi.json.

Field, Type, What it is
FieldTypeWhat it is
objectthe value "list"
datalist of AuditEntryNewest first.
has_moreboolean
next_cursorstring or nullPass as starting_after.
retention_daysthe value 365Each audit log entry is kept for 365 days (one year) from the moment of the change, then deleted. No entry is overwritten: each is written once, only where no entry of its id is.

GET/v1/audit-log/export

Download the audit log

The same entries and filters as a CSV file in the answer (csv, filename, columns), at most 5,000 entries a call; next_cursor names where the rest start. No cell opens as a formula in a spreadsheet.

Request

curl -sS -X GET "$PAYERWORKS_BASE_URL/v1/audit-log/export" \
  -H "Authorization: Bearer $PAYERWORKS_API_KEY"
The answer (200)JSON
{
  "object": "audit_log_export",
  "content_type": "text/csv",
  "filename": "payerworks-audit-log-2026-10-20.csv",
  "row_count": 7,
  "columns": [
    "id",
    "at"
  ],
  "csv": "id,at,type,words,actor_type,actor_id,door,object_kind,object_id,changed,url_host,count,request_id\r\naud_aeb4acb2fdf610d4bc531306,2026-10-20T19:12:00.114Z,webhook_destination.removed,Webhook destination removed,key,pwk_0123456789abcdef01,api,…",
  "has_more": false,
  "next_cursor": null,
  "retention_days": 365
}

Shortened here: lists show their first two items and long strings are cut. The whole answer is this route’s example in /openapi.json.

Field, Type, What it is
FieldTypeWhat it is
objectthe value "audit_log_export"
content_typethe value "text/csv"
filenamestring
row_countintegerAt most 5,000.
columnslist of one of "id", "at", "type", "words", "actor_type", "actor_id", "door", "object_kind", "object_id", "changed", "url_host", "count", "request_id"
csvstringThe file, CRLF line ends; no cell opens as a formula in a spreadsheet.
has_moreboolean
next_cursorstring or nullPass as starting_after for the rest.
retention_daysthe value 365Each audit log entry is kept for 365 days (one year) from the moment of the change, then deleted. No entry is overwritten: each is written once, only where no entry of its id is.

Reading the answer

  • GET /v1/account answers the key’s rate a minute and its usage this month to date, by UTC day, with refused calls counted apart.
  • A rotation (POST /v1/keys/{id}/rotate) keeps the key id, so webhooks, events, usage and enrollments carry on; the old secret is accepted only inside the overlap you choose. Every key of an account may manage its keys, unless the account’s organization chose that only its signed-in members do (see Organizations and members).
  • GET /v1/audit-log answers who changed what on the account, when and through which door, by field name only, never a value; each entry is kept one year. GET /v1/audit-log/export gives the same entries as a CSV file.

Troubleshooting

  • invalid_key (401): The key is not valid, or was revoked: a revoked key stops within a minute.
  • rate_limited (429): Over the key’s calls a minute. Wait the seconds retry-after names; the clients do this for you, at most twice.
  • idempotency_key_reused (422): That Idempotency-Key was used in the last 24 hours for a different request. Make a new key for each new request.
  • too_large (413): A request body is at most 2 MB. Larger work is split across calls.
  • invalid_audit_type (400): type names an entry type (key.created) or its family (key).
  • keys_managed_by_members (403): The account’s organization chose that only its signed-in members make, rotate and revoke keys: do it in the console, or ask an owner to switch it back.

Every refusal these routes may answer, with its status. Any route may also answer the codes every route shares, on Every error.

Code, Status, What it means
CodeStatusWhat it means
invalid_audit_cursor400starting_after is the next_cursor of an earlier page of this audit log.
invalid_audit_type400type is one of the audit log's entry types, or the part before its dot (key, webhook, enrollment...), as the developers page lists them.
invalid_concurrency400concurrency is a whole number from 1 to 10: how many deliveries this destination takes at once.
invalid_contact_email400email is an address of at most 254 characters, or null to remove it.
invalid_destination_id400A destination id is wd_ followed by 16 lowercase hexadecimal characters.
invalid_destination_name400A destination's name is 1 to 80 characters.
invalid_enabled400enabled is true or false, or left out.
invalid_event_types400event_types is a list of the event types the developers page lists; an empty list, or leaving it out, receives every type.
invalid_expires_in_days400expires_in_days is a whole number from 1 to 365, or left out for a key that does not expire.
invalid_idempotency_key400An Idempotency-Key is 1 to 255 visible characters, with no spaces, quotes or backslashes. A UUID is a good one.
invalid_json400The body must be a JSON object.
invalid_key_id400A key id is pwk_ followed by 16 to 40 letters and digits.
invalid_key_name400A key's name is 1 to 80 characters.
invalid_overlap_hours400overlap_hours is a whole number from 0 to 720: how long the old secret is still accepted after a rotation.
invalid_key401That key is not valid. Keys are issued by Payerworks; a revoked key stops within a minute.
no_key401Send your API key as Authorization: Bearer <key>.
contact_not_proved403Notices go only to an address Payerworks has proved: the one that asked for this account's test key by email and opened the link we sent. Send that address, or null to stop the notices. To use another, write to us from it.
keys_managed_by_members403This account's organization chose that only its signed-in members manage keys. Make, rotate or revoke the key at payerworks.com/console.
destination_not_found404This key has no webhook destination with that id.
key_not_found404This account has no key with that id.
not_at_destination404That event was never sent to this destination (it was made before the destination was added, or its type is filtered out). A ping or a new event will be.
destination_conflict409The destination changed while this request ran, so nothing was saved. Send the request again.
destination_disabled409This destination is disabled. Enable it with PUT /v1/webhook-destinations/{id} and enabled: true first.
destination_limit_reached409A key holds at most 10 webhook destinations. Remove one to add another.
idempotency_in_flight409The first request with this Idempotency-Key is still running. Retry after the seconds retry-after names.
key_limit_reached409An account holds at most 3 test keys or 25 live keys that are not revoked. Revoke one to make another.
key_revoked409That key is revoked, so it cannot be rotated. Make a new key with POST /v1/keys.
key_rotation_conflict409Another rotation of this key finished while this one ran, so this one made nothing: the secret that other request showed is the key's current one. List the keys with GET /v1/keys, and rotate again if that secret was lost.
key_settings_out_of_range409The key's stored rate or account name is outside what a key may hold, so nothing was made or rotated; reason says which. Ask Payerworks to correct the key: sending the request again answers the same.
too_large413A request body may be at most 2 MB.
idempotency_key_reused422This Idempotency-Key was used in the last 24 hours for a different request. Send a new key for a new request.
rate_limited429Over this key's calls a minute. Wait the seconds retry-after names.
store_unavailable503We could not read or write this key's records just now; the message says what was not done. Retry in a moment.

Code lists

The headers on every answer

Header, What it says
HeaderWhat it says
x-request-idThe request’s id. Quote it when you write to Payerworks.
x-ratelimit-limitThe key’s calls a minute.
x-ratelimit-remainingCalls left in this UTC minute.
x-ratelimit-resetSeconds until the window resets.
RateLimitThe same figures in the IETF draft’s form.
RateLimit-PolicyThe key’s policy in the IETF draft’s form.
idempotent-replayedtrue when this is the first answer to an Idempotency-Key request, given again.
retry-afterSeconds to wait before a retry.

The audit log’s entry types

An entry names what changed by field name only, never a value: no name, address, note or answer is kept. A web address is kept as its host alone. Each audit log entry is kept for 365 days (one year) from the moment of the change, then deleted. No entry is overwritten: each is written once, only where no entry of its id is.

Type, What changed, Fields it may name
TypeWhat changedFields it may name
key.createdAPI key createdname, mode, rpm, expires_at
key.rotatedAPI key secret rotatedsecret, overlap_hours
key.revokedAPI key revokednone
key.expiredAPI key expirednone
webhook.setAccount webhook seturl, secret
webhook.changedAccount webhook changedurl, secret, overlap_hours
webhook.removedAccount webhook removednone
webhook_destination.createdWebhook destination addedname, url, event_types, enabled, concurrency, secret
webhook_destination.changedWebhook destination changedname, url, event_types, enabled, concurrency, secret, overlap_hours
webhook_destination.removedWebhook destination removednone
contact.changedNotice contact setemail
contact.removedNotice contact removedemail
provider.createdProvider addedname, npi, tax_id, tax_id_type, contacts
provider.changedProvider changedname, npi, tax_id, tax_id_type, contacts
provider.removedProvider removednone
enrollment.createdEnrollment request createdprovider_id, payer, transaction, primary_contact, notify_email, requested_effective_date, era_aggregation, ptan, note
enrollment.changedEnrollment request changedprovider_id, payer, transaction, primary_contact, notify_email, requested_effective_date, era_aggregation, ptan, note
enrollment.submittedEnrollment request submittednone
enrollment.withdrawnEnrollment request withdrawnreason
enrollment.withdrawal_requestedWithdrawal of an enrollment request asked of Payerworksreason
enrollment.removedEnrollment request deletednone
enrollment.status_changedEnrollment request status changedstatus
enrollment.importedEnrollment requests imported from a filenone
enrollment.note_addedNote added to an enrollment requestnone
enrollment_task.answeredEnrollment task answeredvalues
enrollment_task.addedEnrollment task addednone
enrollment_task.supersededEnrollment task replaced by anothernone
enrollment_task.completedEnrollment task marked donenone
enrollment_document.requestedEnrollment document upload startednone
enrollment_document.addedEnrollment document addednone
enrollment_document.removedEnrollment document removednone
sftp_user.addedSFTP user addedacknowledgment_999
sftp_user.changedSFTP user changedacknowledgment_999
sftp_user.removedSFTP user removednone
sftp_ssh_key.addedSFTP SSH key addednone
sftp_ssh_key.removedSFTP SSH key removednone
job.createdBatch job createdroute
job.canceledBatch job cancelednone
job.removedBatch job and its files deletednone
account_baa.recordedBusiness associate agreement recordedsigner_name, signer_title, organization, signed_on, baa_version, reference_prefix
account_baa.withdrawnBusiness associate agreement withdrawnnone
org.createdOrganization createdname
org.updatedOrganization changedname, key_management
member.invitedMember invitedemail, role
member.invitation_canceledMember invitation cancelednone
member.joinedMember joinednone
member.role_changedMember role changedrole
member.removedMember removedkeys_revoked

Example

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

keys.mjsJavaScript
// Payerworks example: keys and your account. Docs: https://payerworks.com/docs/keys
//
// 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 keys.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 { refusalOf } from './sample-data.mjs';

/** @param {Payerworks} pw */
export async function run(pw) {
  // 1. Health needs no key, and says the API transmits nothing.
  const health = await pw.getHealth();

  // 2. Your key's rate a minute, and its calls this month to date by UTC day.
  const account = await pw.getAccount();

  // 3. A named key for one job, shown once, then revoked. Every key of an account may manage its keys,
  //    unless the account's organization chose that only its signed-in members do.
  const made = await pw.postKeys({ name: 'Example job', expires_in_days: 1 });
  const revoked = await pw.deleteKeysById(made.key_id);

  // 4. The account's audit log: who made and revoked that key, when, and through which door, newest first.
  const log = await pw.getAuditLog({ query: { limit: 2 } });

  // 5. The failure path: a key id this account never had.
  const refused = await refusalOf(() => pw.deleteKeysById('pwk_0000000000000000'), { PayerworksError });

  return {
    transmits: health.transmits,
    mode: account.mode,
    rpm: account.rpm,
    made: { key_id: made.key_id.startsWith('pwk_'), shown_once: typeof made.key === 'string' },
    revoked: Boolean(revoked),
    audit: log.data.map((e) => ({ type: e.type, by: e.actor.type, door: e.door })),
    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
{
  "transmits": false,
  "mode": "test",
  "rpm": 600,
  "made": {
    "key_id": true,
    "shown_once": true
  },
  "revoked": true,
  "audit": [
    {
      "type": "key.revoked",
      "by": "key",
      "door": "api"
    },
    {
      "type": "key.created",
      "by": "key",
      "door": "api"
    }
  ],
  "refused": {
    "status": 404,
    "code": "key_not_found",
    "request_id": "req_6"
  }
}

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.