Skip to content

Docs: by job

Remittances and denials

What the payer paid and why it did not, said claim by claim, with the next step on every denial.

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.

An 835 is the payer’s remittance: what it paid, allowed and adjusted, claim by claim and line by line. POST /v1/remittances/explain reads it check by check, says each claim’s verdict in words, and checks that each check adds up to the claims it pays. POST /v1/denials/next-step says each adjustment as what the payer did, whether the patient may be billed, and the next step, with every deadline and where it comes from.

POST /v1/appeals/letter writes an appeal letter from the facts you send, by a fixed template, and never adds a code, an amount or a date you did not give. The routes after it work across several 835s: duplicates, deposits matched to checks, recoupments matched to the claims they take back, and an 835 split by payee or rendering provider.

New here? Start with A sandbox claim, to its 835.

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.

POST/v1/remittances/explain

Explain a remittance

An 835 claim by claim: what was paid, allowed and written off, the patient’s share, the verdict in words, each service line, every adjustment and remark code in words, and whether each check adds up to the claims it pays.

Request

curl -sS -X POST "$PAYERWORKS_BASE_URL/v1/remittances/explain" \
  -H "Authorization: Bearer $PAYERWORKS_API_KEY" \
  -H "Content-Type: application/json" \
  -d @request.json
request.jsonJSON
{
  "x12": "ISA*00*          *00*          *ZZ*SAMPLEPAYER    *ZZ*SAMPLEBILLER   *261018*0900*^*00501*000000001*0*T*:~\nGS*HP*SAMPLEPAYER*SAMPLEBILLER*20261018*0900*1*X*005010X221A1~\nST*835*0001~\nBPR*I*1260*C*ACH*CCP*01*999999999*DA*123456*1234567890**01*999999999*DA*654321*20261018~\nTRN*1*EFT-20261018-01*1234567890~\nN1*PR*SAMPLE HEALTH PLAN*PI*99999~\nN1*PE*SAMPLE SLEEP DENTISTRY*XX*1234567893~\nLX*1~\nCLP*PW-1001*1*2900*1260*240*12*PAYER-CN-1*11~\nCAS*CO*45*1400~\nCAS*PR*2*240~\nNM1*QC*1*PATIENT*SAMPLE~\nDTM*472*20261001~\nSVC*HC:E0486*2900*1260~\nAMT*B6*1500~\nCLP*PW-1002*4*350*0*0*12*PAYER-CN-2*11~\nCAS*CO*50*350~\nNM1*QC*1*PATIENT*SECOND~\nDTM*472*20261002~\nSVC*HC:95800*350*0~\nLQ*HE*N115~\nSE*20*0001~\nGE*1*1~\nIEA*1*000000001~"
}
The answer (200)JSON
{
  "check": {
    "number": "EFT-20261018-01",
    "date": "20261018",
    "amount": "1260",
    "method_flag": "C",
    "payer": "SAMPLE HEALTH PLAN",
    "payee_ids": {
      "npis": [
        "1234567893"
      ],
      "tins": []
    }
  },
  "checks": [
    {
      "number": "EFT-20261018-01",
      "date": "20261018",
      "amount": "1260",
      "method_flag": "C",
      "payer": "SAMPLE HEALTH PLAN",
      "payee_ids": {
        "npis": [
          "1234567893"
        ],
        "tins": []
      },
      "references": [
        "PW-1001",
        "PW-1002"
      ],
      "balance": {
        "stated": 1260,
        "claims_net": 1260,
        "provider_adjustments_net": 0,
        "variance": 0,
        "ties": true,
        "words": "The claims, less the provider-level adjustments, add up to the check."
      },
      "provider_adjustments": []
    }
  ],
  "claims": [
    {
      "reference": "PW-1001",
      "payer_claim_number": "PAYER-CN-1",
      "status_code": "1",
      "status": "processed as primary",
      "service_date": "20261001",
      "billed": 2900,
      "paid": 1260,
      "allowed": 1500,
      "patient_responsibility": 240,
      "amounts": {
        "billed": 2900,
        "paid": 1260,
        "allowed": 1500,
        "allowed_basis": "stated",
        "patient_responsibility": 240,
        "patient_basis": "stated",
        "adjustment": 1400,
        "adjustment_basis": "stated",
        "write_off": 1400,
        "below_allowed": 0,
        "not_paid": 0,
        "shortfall": 0
      },
      "adjustments": [
        {
          "group": "CO",
          "code": "45",
          "amount": 1400,
          "label": "Charge exceeds the fee schedule / contracted amount",
          "category": "Underpayment",
          "known": true,
          "label_source": "paraphrase",
          "patient_billable": false
        }
      ],
      "patient_adjustments": [
        {
          "group": "PR",
          "code": "2",
          "amount": 240,
          "label": "Coinsurance amount",
          "category": "Other",
          "known": true,
          "label_source": "paraphrase",
          "patient_billable": true
        }
      ],
      "remark_codes": [],
      "primary_reason": null,
      "crossover_carrier": "",
      "service_lines": [
        {
          "procedure_code": "E0486",
          "modifiers": [],
          "billed": 2900,
          "paid": 1260,
          "allowed": 1500
        }
      ],
      "check_number": "EFT-20261018-01",
      "index": 0,
      "claim_filing_indicator": "12",
      "verdict": "paid",
      "verdict_words": "Paid: the payer paid $1,260.00, the patient owes $240.00 (patient responsibility), and $1,400.00 is a contractual adjustment.",
      "remarks": [],
      "claim_adjustments": [
        {
          "group": "CO",
          "code": "45",
          "amount": 1400
        },
        {
          "group": "PR",
          "code": "2",
          "amount": 240
        }
      ],
      "lines": [
        {
          "index": 0,
          "procedure_code": "E0486",
          "procedure_qualifier": "HC",
          "modifiers": [],
          "billed": 2900,
          "paid": 1260,
          "allowed": 1500,
          "units_paid": null,
          "service_date": null,
          "service_date_end": null,
          "line_control_number": "",
          "adjustments": [],
          "remarks": []
        }
      ]
    },
    {
      "reference": "PW-1002",
      "payer_claim_number": "PAYER-CN-2",
      "status_code": "4",
      "status": "denied",
      "service_date": "20261002",
      "billed": 350,
      "paid": 0,
      "allowed": null,
      "patient_responsibility": 0,
      "amounts": {
        "billed": 350,
        "paid": 0,
        "allowed": null,
        "allowed_basis": null,
        "patient_responsibility": 0,
        "patient_basis": "stated",
        "adjustment": 350,
        "adjustment_basis": "stated",
        "write_off": 0,
        "below_allowed": 0,
        "not_paid": 350,
        "shortfall": null
      },
      "adjustments": [
        {
          "group": "CO",
          "code": "50",
          "amount": 350,
          "label": "Non-covered: not deemed a medical necessity",
          "category": "Medical Necessity",
          "known": true,
          "label_source": "paraphrase",
          "patient_billable": false
        }
      ],
      "patient_adjustments": [],
      "remark_codes": [
        "N115"
      ],
      "primary_reason": {
        "code": "50",
        "category": "Medical Necessity",
        "words": "50, Non-covered: not deemed a medical necessity"
      },
      "crossover_carrier": "",
      "service_lines": [
        {
          "procedure_code": "95800",
          "modifiers": [],
          "billed": 350,
          "paid": 0,
          "allowed": null
        }
      ],
      "check_number": "EFT-20261018-01",
      "index": 1,
      "claim_filing_indicator": "12",
      "verdict": "denied",
      "verdict_words": "Refused: the payer paid nothing. The refusing adjustment is CO-50 (Non-covered: not deemed a medical necessity).",
      "remarks": [
        {
          "code": "N115",
          "words": "The decision was based on a Local Coverage Determination (LCD).",
          "label_source": "paraphrase"
        }
      ],
      "claim_adjustments": [
        {
          "group": "CO",
          "code": "50",
          "amount": 350
        }
      ],
      "lines": [
        {
          "index": 0,
          "procedure_code": "95800",
          "procedure_qualifier": "HC",
          "modifiers": [],
          "billed": 350,
          "paid": 0,
          "allowed": null,
          "units_paid": null,
          "service_date": null,
          "service_date_end": null,
          "line_control_number": "",
          "adjustments": [],
          "remarks": [
            {
              "code": "N115",
              "words": "The decision was based on a Local Coverage Determination (LCD).",
              "label_source": "paraphrase"
            }
          ]
        }
      ]
    }
  ],
  "provider_adjustments": [],
  "groups": {
    "CO": {
      "name": "Contractual obligation",
      "patient_billable": false,
      "words": "An adjustment your agreement with the payer, or a regulation, requires. It is generally a write-off for you and is not billed to the patient."
    },
    "OA": {
      "name": "Other adjustment",
      "patient_billable": "depends",
      "words": "Used when no other group applies, such as the effect of an earlier payer's payment. Whether the patient may be billed depends on the reason code beside it and on your agreement with the plan."
    },
    "PI": {
      "name": "Payer-initiated reduction",
      "patient_billable": false,
      "words": "A reduction the payer made itself. It is not a patient responsibility amount, so it is not billed to the patient."
    },
    "PR": {
      "name": "Patient responsibility",
      "patient_billable": true,
      "words": "An amount that may be billed to the patient, such as the deductible, coinsurance or copay."
    }
  }
}
Field, Type, What it is
FieldTypeWhat it is
checkCheck
checkslist of CheckOne per check: an 835 pays each payee by its own.
claimslist of RemittanceClaim
provider_adjustmentslist of object
groupsGroupsEach adjustment group code the answer names (CO, OA, PI, PR), said once: its name, whether the patient may be billed, and its words. An adjustment carries its group code only.

POST/v1/denials/next-step

The next step on a denial

An 835, or the claims as JSON: for each claim and each adjustment, what the payer did, whether the patient may be billed, the next step, the corrected claim fields to send, what to attach, and every deadline with where it comes from: a Medicare regulation with its section, the limits you send, or no date at all.

Request

curl -sS -X POST "$PAYERWORKS_BASE_URL/v1/denials/next-step" \
  -H "Authorization: Bearer $PAYERWORKS_API_KEY" \
  -H "Content-Type: application/json" \
  -d @request.json
request.jsonJSON
{
  "x12": "ISA*00*          *00*          *ZZ*SAMPLEPAYER    *ZZ*SAMPLEBILLER   *261018*0900*^*00501*000000093*0*T*:~\nGS*HP*SAMPLEPAYER*SAMPLEBILLER*20261018*0900*93*X*005010X221A1~\nST*835*0001~\nBPR*I*80*C*ACH*CCP*01*999999999*DA*123456*1234567890**01*999999999*DA*654321*20261018~\nTRN*1*EFT-20261018-02*1234567890~\nN1*PR*SAMPLE HEALTH PLAN*PI*99999~\nN1*PE*SAMPLE FAMILY MEDICINE*XX*1234567893~\nLX*1~\nCLP*PW-2003*1*215*0**12*PAYER-CN-23*11~\nNM1*QC*1*PATIENT*SAMPLE****MI*W123456789~\nDTM*232*20261001~\nSVC*HC:99213*150*0~\nDTM*472*20261001~\nCAS*CO*16*150~\nLQ*HE*N290~\nSVC*HC:87880*65*0~\nDTM*472*20261001~\nCAS*CO*16*65~\nLQ*HE*N290~\nCLP*PW-2004*1*350*0**MB*PAYER-CN-24*11~\nNM1*QC*1*PATIENT*SECOND****MI*1EG4TE5MK73~\nDTM*232*20261002~\nSVC*HC:99214*350*0~\nDTM*472*20261002~\nCAS*CO*50*350~\nLQ*HE*N115~\nCLP*PW-2005*1*240*80*100*12*PAYER-CN-25*11~\nNM1*QC*1*PATIENT*THIRD****MI*W555555555~\nDTM*232*20261003~\nSVC*HC:99213*240*80~\nDTM*472*20261003~\nCAS*CO*45*60~\nCAS*PR*1*100~\nAMT*B6*180~\nCLP*PW-2006*1*150*0**12*PAYER-CN-26*11~\nNM1*QC*1*PATIENT*FOURTH****MI*W666666666~\nDTM*232*20260101~\nSVC*HC:99213*150*0~\nDTM*472*20260101~\nCAS*CO*29*150~\nSE*39*0001~\nGE*1*93~\nIEA*1*000000093~"
}
The answer (200)JSON
{
  "source": "x12",
  "remittance_date": "2026-10-18",
  "today": "2026-10-19",
  "claims": [
    {
      "index": 0,
      "reference": "PW-2003",
      "payer_claim_number": "PAYER-CN-23",
      "status_code": "1",
      "status": "processed as primary",
      "claim_filing_indicator": "12",
      "medicare": null,
      "service_date": "2026-10-01",
      "remittance_date": "2026-10-18",
      "notice_date": "2026-10-18",
      "notice_date_source": "bpr_16",
      "billed": 215,
      "paid": 0,
      "allowed": null,
      "patient_responsibility": null,
      "verdict": "denied",
      "verdict_words": "Refused: the payer paid nothing. The refusing adjustment is CO-16 (Claim lacks information or has a submission/billing error). The claim status code says processed as primary, but the adjustments refused the money.",
      "patient": {
        "may_bill": 0,
        "words": "Nothing on this remittance is the patient's to pay. The $215.00 under group CO (contractual) may not be billed to the patient."
      },
      "adjustments": [
        {
          "group": "CO",
          "code": "16",
          "amount": 150,
          "label": "Claim lacks information or has a submission/billing error",
          "category": "Missing Information",
          "known": true,
          "label_source": "paraphrase",
          "patient_billable": false,
          "line": 0,
          "remedy": {
            "key": "correct",
            "action": "correct",
            "label": "Correct the claim and send a replacement",
            "words": "The payer says something on the claim was missing or wrong. Fix it and send a replacement claim (frequency code 7) that carries the payer's claim number. An appeal is not the route for this.",
            "is_letter": false,
            "letter_kind": null
          }
        },
        {
          "group": "CO",
          "code": "16",
          "amount": 65,
          "label": "Claim lacks information or has a submission/billing error",
          "category": "Missing Information",
          "known": true,
          "label_source": "paraphrase",
          "patient_billable": false,
          "line": 1,
          "remedy": {
            "key": "correct",
            "action": "correct",
            "label": "Correct the claim and send a replacement",
            "words": "The payer says something on the claim was missing or wrong. Fix it and send a replacement claim (frequency code 7) that carries the payer's claim number. An appeal is not the route for this.",
            "is_letter": false,
            "letter_kind": null
          }
        }
      ],
      "remarks": [
        {
          "code": "N290",
          "words": "The rendering provider's primary identifier is missing, incomplete or invalid.",
          "label_source": "paraphrase"
        },
        {
          "code": "N290",
          "words": "The rendering provider's primary identifier is missing, incomplete or invalid.",
          "label_source": "paraphrase"
        }
      ],
      "next_step": {
        "key": "correct",
        "action": "correct",
        "label": "Correct the claim and send a replacement",
        "words": "The payer says something on the claim was missing or wrong. Fix it and send a replacement claim (frequency code 7) that carries the payer's claim number. An appeal is not the route for this.",
        "is_letter": false,
        "letter_kind": null
      },
      "corrected_claim": {
        "frequency_code": "7",
        "void_frequency_code": "8",
        "claim_control_number": "PAYER-CN-23",
        "fields": {
          "claimInformation.claimFrequencyCode": "7",
          "claimInformation.claimSupplementalInformation.claimControlNumber": "PAYER-CN-23"
        },
        "words": "Send a replacement claim through POST /v1/claims/837p with claimInformation.claimFrequencyCode \"7\" and claimInformation.claimSupplementalInformation.claimControlNumber \"PAYER-CN-23\" (the payer's claim number); it is written as CLM05-3 7 and…"
      },
      "send": [],
      "deadlines": [
        {
          "kind": "timely_filing",
          "date": null,
          "date_us": null,
          "days_left": null,
          "window": null,
          "counted_from": "the date of service",
          "source": {
            "kind": "none"
          },
          "words": "The payer's filing limit is stated in its contract or provider manual. Send facts.filing_limit_days to have the date computed."
        }
      ]
    },
    {
      "index": 1,
      "reference": "PW-2004",
      "payer_claim_number": "PAYER-CN-24",
      "status_code": "1",
      "status": "processed as primary",
      "claim_filing_indicator": "MB",
      "medicare": "fee_for_service",
      "service_date": "2026-10-02",
      "remittance_date": "2026-10-18",
      "notice_date": "2026-10-18",
      "notice_date_source": "bpr_16",
      "billed": 350,
      "paid": 0,
      "allowed": null,
      "patient_responsibility": null,
      "verdict": "denied",
      "verdict_words": "Refused: the payer paid nothing. The refusing adjustment is CO-50 (Non-covered: not deemed a medical necessity). The claim status code says processed as primary, but the adjustments refused the money.",
      "patient": {
        "may_bill": 0,
        "words": "Nothing on this remittance is the patient's to pay. The $350.00 under group CO (contractual) may not be billed to the patient."
      },
      "adjustments": [
        {
          "group": "CO",
          "code": "50",
          "amount": 350,
          "label": "Non-covered: not deemed a medical necessity",
          "category": "Medical Necessity",
          "known": true,
          "label_source": "paraphrase",
          "patient_billable": false,
          "line": 0,
          "remedy": {
            "key": "necessity",
            "action": "appeal",
            "label": "Appeal with the clinical records",
            "words": "The payer says the service was not medically necessary. Appeal with the clinical records that support it, the ones the payer's coverage policy asks for.",
            "is_letter": true,
            "letter_kind": "medical_necessity"
          }
        }
      ],
      "remarks": [
        {
          "code": "N115",
          "words": "The decision was based on a Local Coverage Determination (LCD).",
          "label_source": "paraphrase"
        }
      ],
      "next_step": {
        "key": "necessity",
        "action": "appeal",
        "label": "Appeal with the clinical records",
        "words": "The payer says the service was not medically necessary. Appeal with the clinical records that support it, the ones the payer's coverage policy asks for.",
        "is_letter": true,
        "letter_kind": "medical_necessity",
        "letter_facts": {
          "payer_name": "SAMPLE HEALTH PLAN",
          "patient_name": "SECOND PATIENT",
          "payer_claim_number": "PAYER-CN-24",
          "patient_control_number": "PW-2004",
          "service_date": "2026-10-02",
          "billed_amount": 350,
          "remittance_date": "2026-10-18",
          "adjustment_codes": [
            "CO-50"
          ],
          "remark_codes": [
            "N115"
          ],
          "claim_filing_indicator": "MB"
        },
        "letter_facts_missing": [
          "member_id",
          "provider_name"
        ]
      },
      "corrected_claim": null,
      "send": [],
      "deadlines": [
        {
          "kind": "redetermination",
          "date": "2027-02-20",
          "date_us": "02/20/2027",
          "days_left": 124,
          "window": {
            "days": 120,
            "presumed_receipt_days": 5
          },
          "counted_from": "receipt of the initial determination",
          "counted_from_date": "2026-10-18",
          "counted_from_date_source": "bpr_16",
          "source": {
            "kind": "regulation",
            "citation": "42 CFR 405.942(a)",
            "url": "https://www.ecfr.gov/current/title-42/section-405.942",
            "verified_on": "10/19/2026",
            "presumed_receipt_citation": "42 CFR 405.942(a)(1)"
          },
          "words": "A redetermination (the first level of appeal) is due within 120 days of receiving the initial determination, and receipt is presumed 5 days after the notice's date: 02/20/2027, counted from the payment date (BPR16), as the remittance advice…"
        },
        {
          "kind": "reconsideration",
          "date": null,
          "date_us": null,
          "days_left": null,
          "window": {
            "days": 180,
            "presumed_receipt_days": 5
          },
          "counted_from": "receipt of the redetermination decision",
          "source": {
            "kind": "regulation",
            "citation": "42 CFR 405.962(a)",
            "url": "https://www.ecfr.gov/current/title-42/section-405.962",
            "verified_on": "10/19/2026",
            "presumed_receipt_citation": "42 CFR 405.962(a)(1)"
          },
          "words": "A later level: 180 days from receipt of the redetermination decision, receipt presumed 5 days after that decision's date (42 CFR 405.962(a); 42 CFR 405.962(a)(1)). Its date is known once that decision is."
        }
      ]
    }
  ],
  "groups": {
    "CO": {
      "name": "Contractual obligation",
      "patient_billable": false,
      "words": "An adjustment your agreement with the payer, or a regulation, requires. It is generally a write-off for you and is not billed to the patient."
    },
    "OA": {
      "name": "Other adjustment",
      "patient_billable": "depends",
      "words": "Used when no other group applies, such as the effect of an earlier payer's payment. Whether the patient may be billed depends on the reason code beside it and on your agreement with the plan."
    },
    "PI": {
      "name": "Payer-initiated reduction",
      "patient_billable": false,
      "words": "A reduction the payer made itself. It is not a patient responsibility amount, so it is not billed to the patient."
    },
    "PR": {
      "name": "Patient responsibility",
      "patient_billable": true,
      "words": "An amount that may be billed to the patient, such as the deductible, coinsurance or copay."
    }
  },
  "deadline_rule": "A deadline is computed only from a regulation it cites (Medicare fee-for-service, by its filing indicator MA or MB), or from the limits you send as facts; otherwise its date is null and its words say the payer's contract or provider manual …"
}

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
sourceone of "x12", "claims"
remittance_datestring or null
todaystring
claimslist of NextStepClaim
groupsGroupsEach adjustment group code the answer names (CO, OA, PI, PR), said once: its name, whether the patient may be billed, and its words. An adjustment carries its group code only.
deadline_rulestring

POST/v1/appeals/letter

Write an appeal letter

An appeal letter written from the facts you send, by a fixed template for its kind. It never adds a code, an amount or a date you did not give. A fact the kind needs and you left out is named, and nothing is written.

Request

curl -sS -X POST "$PAYERWORKS_BASE_URL/v1/appeals/letter" \
  -H "Authorization: Bearer $PAYERWORKS_API_KEY" \
  -H "Content-Type: application/json" \
  -d @request.json
request.jsonJSON
{
  "kind": "timely_filing",
  "facts": {
    "payer_name": "Sample Health Plan",
    "patient_name": "Sample Patient",
    "member_id": "W666666666",
    "payer_claim_number": "PAYER-CN-26",
    "service_date": "2026-01-01",
    "provider_name": "Sample Family Medicine",
    "provider_npi": "1234567893",
    "signer_name": "Sam Sample",
    "original_filing_date": "2026-01-15",
    "proof_reference": "the clearinghouse acceptance report dated 01/16/2026",
    "filing_limit_days": 90
  }
}
The answer (200)JSON
{
  "kind": "timely_filing",
  "subject": "Request for reconsideration: timely filing denial",
  "letter": "10/19/2026\n\nSample Health Plan\n\nRe: Request for reconsideration: timely filing denial\nPatient: Sample Patient\nMember ID: W666666666\nClaim number: PAYER-CN-26\nDate of service: 01/01/2026\n\nTo the appeals department:\n\nThis claim was denied as …",
  "facts_used": [
    {
      "field": "payer_name",
      "label": "Payer",
      "value": "Sample Health Plan"
    },
    {
      "field": "patient_name",
      "label": "Patient",
      "value": "Sample Patient"
    }
  ],
  "enclosures": [],
  "guard": {
    "passed": true
  },
  "transmitted": false
}

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
kindstring
subjectstring
letterstringThe letter, as plain text.
facts_usedlist of FactUsed
enclosureslist of string
guardLetterGuard
transmittedthe value falsePayerworks wrote the letter and sent it nowhere.

POST/v1/appeals/letter/check

Check an edited letter

A letter you edited, held to the facts by the same rule: every code, amount and date it states, however it is written (a dollar sign or the word dollars, a written or numeric date, CO-50 or CARC 50, N115 or N 115), must be one the facts hold, and a placeholder left in is found.

Request

curl -sS -X POST "$PAYERWORKS_BASE_URL/v1/appeals/letter/check" \
  -H "Authorization: Bearer $PAYERWORKS_API_KEY" \
  -H "Content-Type: application/json" \
  -d @request.json
request.jsonJSON
{
  "letter": "We ask that you reverse the denial of the claim for Sample Patient (CO-29), billed at $150.00.",
  "facts": {
    "patient_name": "Sample Patient",
    "adjustment_codes": [
      "CO-29"
    ]
  }
}
The answer (200)JSON
{
  "guard": {
    "passed": false,
    "reason": "unknown_amount",
    "value": "$150.00",
    "words": "The letter states $150.00, which no fact holds. Add the amount to the facts, or take it out of the letter.",
    "findings": [
      {
        "reason": "unknown_amount",
        "value": "$150.00",
        "words": "The letter states $150.00, which no fact holds. Add the amount to the facts, or take it out of the letter."
      }
    ]
  },
  "facts_used": [
    {
      "field": "patient_name",
      "label": "Patient",
      "value": "Sample Patient"
    },
    {
      "field": "adjustment_codes",
      "label": "Adjustment codes",
      "value": "CO-29"
    }
  ]
}
Field, Type, What it is
FieldTypeWhat it is
guardLetterGuard
facts_usedlist of FactUsed

GET/v1/codes/carc/{code}

An adjustment reason code

A claim adjustment reason code in words, with its category, sent bare (45) or with its group (CO-45). A remark code sent here is named as one.

Request

curl -sS -X GET "$PAYERWORKS_BASE_URL/v1/codes/carc/CO-16" \
  -H "Authorization: Bearer $PAYERWORKS_API_KEY"
The answer (200)JSON
{
  "code": "16",
  "label": "Claim lacks information or has a submission/billing error",
  "category": "Missing Information",
  "known": true,
  "label_source": "paraphrase",
  "stopped_on": null,
  "group": {
    "code": "CO",
    "known": true,
    "name": "Contractual obligation",
    "words": "An adjustment your agreement with the payer, or a regulation, requires. It is generally a write-off for you and is not billed to the patient.",
    "patient_billable": false
  },
  "source": {
    "list": "X12 claim adjustment reason codes",
    "url": "https://x12.org/codes/claim-adjustment-reason-codes",
    "read_on": "10/19/2026"
  }
}
Field, Type, What it is
FieldTypeWhat it is
codestring
labelstring
categorystring
knownboolean
label_sourcethe value "paraphrase"
stopped_onstring or null
groupobject or null
sourceobject

GET/v1/codes/group/{code}

An adjustment group code

A claim adjustment group code (CO, PR, OA, PI or CR) in words, and whether the patient may be billed an amount under it.

Request

curl -sS -X GET "$PAYERWORKS_BASE_URL/v1/codes/group/PR" \
  -H "Authorization: Bearer $PAYERWORKS_API_KEY"
The answer (200)JSON
{
  "code": "PR",
  "known": true,
  "name": "Patient responsibility",
  "words": "An amount that may be billed to the patient, such as the deductible, coinsurance or copay.",
  "patient_billable": true,
  "patient_billable_words": "The patient may be billed this amount.",
  "label_source": "paraphrase",
  "source": {
    "list": "X12 claim adjustment group codes",
    "url": "https://x12.org/codes/claim-adjustment-group-codes",
    "read_on": "10/19/2026"
  }
}
Field, Type, What it is
FieldTypeWhat it is
codestring
knownboolean
namestring
wordsstring
patient_billableboolean or string or nulltrue, false, "depends" or null.
patient_billable_wordsstring
label_sourcethe value "paraphrase"
sourceobject
valid_codeslist of string

POST/v1/remittances/duplicates

Find duplicate remittances

Send several 835s and get back every check that is one payment sent more than once: the same trace number (TRN02) from the same originator (TRN03), never the trace alone. Each duplicate says whether the copies are the same remittance or differ in content, and a check with no trace is listed apart. Nothing is stored.

Request

curl -sS -X POST "$PAYERWORKS_BASE_URL/v1/remittances/duplicates" \
  -H "Authorization: Bearer $PAYERWORKS_API_KEY" \
  -H "Content-Type: application/json" \
  -d @request.json
request.jsonJSON
{
  "remittances": [
    "ISA*00*          *00*          *ZZ*SAMPLEPAYER    *ZZ*SAMPLEBILLER   *261018*0900*^*00501*000000001*0*T*:~\nGS*HP*SAMPLEPAYER*SAMPLEBILLER*20261018*0900*1*X*005010X221A1~\nST*835*0001~\nBPR*I*1260*C*ACH*CCP*01*999999999*DA*123456*1234567890**01*999999999*DA*654321*20261018~\nTRN*1*EFT-20261018-01*1234567890~\nN1*PR*SAMPLE HEALTH PLAN*PI*99999~\nN1*PE*SAMPLE SLEEP DENTISTRY*XX*1234567893~\nLX*1~\nCLP*PW-1001*1*2900*1260*240*12*PAYER-CN-1*11~\nCAS*CO*45*1400~\nCAS*PR*2*240~\nNM1*QC*1*PATIENT*SAMPLE~\nDTM*472*20261001~\nSVC*HC:E0486*2900*1260~\nAMT*B6*1500~\nCLP*PW-1002*4*350*0*0*12*PAYER-CN-2*11~\nCAS*CO*50*350~\nNM1*QC*1*PATIENT*SECOND~\nDTM*472*20261002~\nSVC*HC:95800*350*0~\nLQ*HE*N115~\nSE*20*0001~\nGE*1*1~\nIEA*1*000000001~",
    "ISA*00*          *00*          *ZZ*SAMPLEPAYER    *ZZ*SAMPLEBILLER   *261018*0900*^*00501*000000001*0*T*:~\nGS*HP*SAMPLEPAYER*SAMPLEBILLER*20261018*0900*1*X*005010X221A1~\nST*835*0001~\nBPR*I*1260*C*ACH*CCP*01*999999999*DA*123456*1234567890**01*999999999*DA*654321*20261018~\nTRN*1*EFT-20261018-01*1234567890~\nN1*PR*SAMPLE HEALTH PLAN*PI*99999~\nN1*PE*SAMPLE SLEEP DENTISTRY*XX*1234567893~\nLX*1~\nCLP*PW-1001*1*2900*1260*240*12*PAYER-CN-1*11~\nCAS*CO*45*1400~\nCAS*PR*2*240~\nNM1*QC*1*PATIENT*SAMPLE~\nDTM*472*20261001~\nSVC*HC:E0486*2900*1260~\nAMT*B6*1500~\nCLP*PW-1002*4*350*0*0*12*PAYER-CN-2*11~\nCAS*CO*50*350~\nNM1*QC*1*PATIENT*SECOND~\nDTM*472*20261002~\nSVC*HC:95800*350*0~\nLQ*HE*N115~\nSE*20*0001~\nGE*1*1~\nIEA*1*000000001~"
  ]
}
The answer (200)JSON
{
  "files": 2,
  "checks": [
    {
      "file": 0,
      "check": 0,
      "trace": "EFT-20261018-01",
      "originator": "1234567890",
      "amount": 1260,
      "date": "2026-10-18",
      "method": "ACH",
      "payer": "SAMPLE HEALTH PLAN",
      "claims": 2,
      "duplicate_of": null
    },
    {
      "file": 1,
      "check": 0,
      "trace": "EFT-20261018-01",
      "originator": "1234567890",
      "amount": 1260,
      "date": "2026-10-18",
      "method": "ACH",
      "payer": "SAMPLE HEALTH PLAN",
      "claims": 2,
      "duplicate_of": {
        "file": 0,
        "check": 0,
        "trace": "EFT-20261018-01",
        "originator": "1234567890",
        "amount": 1260,
        "date": "2026-10-18",
        "method": "ACH",
        "payer": "SAMPLE HEALTH PLAN",
        "claims": 2
      }
    }
  ],
  "duplicates": [
    {
      "trace": "EFT-20261018-01",
      "originator": "1234567890",
      "matched_on": [
        "TRN02",
        "TRN03"
      ],
      "identical": true,
      "copies": [
        {
          "file": 0,
          "check": 0,
          "trace": "EFT-20261018-01",
          "originator": "1234567890",
          "amount": 1260,
          "date": "2026-10-18",
          "method": "ACH",
          "payer": "SAMPLE HEALTH PLAN",
          "claims": 2
        },
        {
          "file": 1,
          "check": 0,
          "trace": "EFT-20261018-01",
          "originator": "1234567890",
          "amount": 1260,
          "date": "2026-10-18",
          "method": "ACH",
          "payer": "SAMPLE HEALTH PLAN",
          "claims": 2
        }
      ],
      "words": "2 checks carry the same trace (TRN02 EFT-20261018-01) from the same originator (TRN03 1234567890), and their content is the same: one remittance sent twice. Post it once."
    }
  ],
  "no_trace": [],
  "words": "1 payment is in these files more than once, matched by trace (TRN02) and originator (TRN03).",
  "reads": "Only the files sent in this call: nothing is stored, and no payer or bank is asked."
}
Field, Type, What it is
FieldTypeWhat it is
filesinteger
checkslist of RemitCheckEach check, with duplicate_of naming the first copy.
duplicateslist of object
no_tracelist of object
wordsstring
readsstring

POST/v1/remittances/reassociate

Match deposits to remittances

Send 835s and the deposits from your bank (the amount and effective date, and the trace number or description when your bank gives them). Each deposit is matched to one check by its trace number first, then by a trace in the description, then by amount and date only when exactly one check and one deposit fit, and every match says what agreed and what did not. Unmatched deposits and checks are listed. No bank description is repeated back.

Request

curl -sS -X POST "$PAYERWORKS_BASE_URL/v1/remittances/reassociate" \
  -H "Authorization: Bearer $PAYERWORKS_API_KEY" \
  -H "Content-Type: application/json" \
  -d @request.json
request.jsonJSON
{
  "remittances": [
    "ISA*00*          *00*          *ZZ*SAMPLEPAYER    *ZZ*SAMPLEBILLER   *261018*0900*^*00501*000000001*0*T*:~\nGS*HP*SAMPLEPAYER*SAMPLEBILLER*20261018*0900*1*X*005010X221A1~\nST*835*0001~\nBPR*I*1260*C*ACH*CCP*01*999999999*DA*123456*1234567890**01*999999999*DA*654321*20261018~\nTRN*1*EFT-20261018-01*1234567890~\nN1*PR*SAMPLE HEALTH PLAN*PI*99999~\nN1*PE*SAMPLE SLEEP DENTISTRY*XX*1234567893~\nLX*1~\nCLP*PW-1001*1*2900*1260*240*12*PAYER-CN-1*11~\nCAS*CO*45*1400~\nCAS*PR*2*240~\nNM1*QC*1*PATIENT*SAMPLE~\nDTM*472*20261001~\nSVC*HC:E0486*2900*1260~\nAMT*B6*1500~\nCLP*PW-1002*4*350*0*0*12*PAYER-CN-2*11~\nCAS*CO*50*350~\nNM1*QC*1*PATIENT*SECOND~\nDTM*472*20261002~\nSVC*HC:95800*350*0~\nLQ*HE*N115~\nSE*20*0001~\nGE*1*1~\nIEA*1*000000001~",
    "ISA*00*          *00*          *ZZ*SAMPLEPAYER    *ZZ*SAMPLEBILLER   *261018*0900*^*00501*000000093*0*T*:~\nGS*HP*SAMPLEPAYER*SAMPLEBILLER*20261018*0900*93*X*005010X221A1~\nST*835*0001~\nBPR*I*80*C*ACH*CCP*01*999999999*DA*123456*1234567890**01*999999999*DA*654321*20261018~\nTRN*1*EFT-20261018-02*1234567890~\nN1*PR*SAMPLE HEALTH PLAN*PI*99999~\nN1*PE*SAMPLE FAMILY MEDICINE*XX*1234567893~\nLX*1~\nCLP*PW-2003*1*215*0**12*PAYER-CN-23*11~\nNM1*QC*1*PATIENT*SAMPLE****MI*W123456789~\nDTM*232*20261001~\nSVC*HC:99213*150*0~\nDTM*472*20261001~\nCAS*CO*16*150~\nLQ*HE*N290~\nSVC*HC:87880*65*0~\nDTM*472*20261001~\nCAS*CO*16*65~\nLQ*HE*N290~\nCLP*PW-2004*1*350*0**MB*PAYER-CN-24*11~\nNM1*QC*1*PATIENT*SECOND****MI*1EG4TE5MK73~\nDTM*232*20261002~\nSVC*HC:99214*350*0~\nDTM*472*20261002~\nCAS*CO*50*350~\nLQ*HE*N115~\nCLP*PW-2005*1*240*80*100*12*PAYER-CN-25*11~\nNM1*QC*1*PATIENT*THIRD****MI*W555555555~\nDTM*232*20261003~\nSVC*HC:99213*240*80~\nDTM*472*20261003~\nCAS*CO*45*60~\nCAS*PR*1*100~\nAMT*B6*180~\nCLP*PW-2006*1*150*0**12*PAYER-CN-26*11~\nNM1*QC*1*PATIENT*FOURTH****MI*W666666666~\nDTM*232*20260101~\nSVC*HC:99213*150*0~\nDTM*472*20260101~\nCAS*CO*29*150~\nSE*39*0001~\nGE*1*93~\nIEA*1*000000093~"
  ],
  "deposits": [
    {
      "id": "bank-1",
      "amount": 1260,
      "effective_date": "2026-10-19",
      "trace_number": "EFT-20261018-01",
      "originator": "1234567890"
    },
    {
      "id": "bank-2",
      "amount": 80,
      "effective_date": "2026-10-19",
      "description": "SAMPLE HEALTH PLAN HCCLAIMPMT EFT-20261018-02"
    }
  ]
}
The answer (200)JSON
{
  "matches": [
    {
      "deposit": {
        "index": 0,
        "id": "bank-1",
        "amount": 1260,
        "effective_date": "2026-10-19"
      },
      "check": {
        "file": 0,
        "check": 0,
        "trace": "EFT-20261018-01",
        "originator": "1234567890",
        "amount": 1260,
        "date": "2026-10-18",
        "method": "ACH",
        "payer": "SAMPLE HEALTH PLAN",
        "claims": 2
      },
      "matched_by": "trace",
      "matched_on": [
        "TRN02",
        "TRN03"
      ],
      "agrees": {
        "amount": true,
        "date": false,
        "originator": true,
        "weekdays_from_payment_date": 1
      },
      "words": "Matched by the trace number (TRN02): check EFT-20261018-01 of 10/18/2026 (file 1), agreeing on TRN02, TRN03, BPR02. But the date differs: the deposit settled 10/19/2026 and the check's payment date (BPR16) is 10/18/2026, 1 weekday apart."
    }
  ],
  "unmatched_deposits": [
    {
      "deposit": {
        "index": 1,
        "id": "bank-2",
        "amount": 80,
        "effective_date": "2026-10-19"
      },
      "words": "Not matched: the deposit carries no trace number, its description names none of the checks' traces, and no single check has its amount on its date."
    }
  ],
  "unmatched_checks": [
    {
      "check": {
        "file": 1,
        "check": 0,
        "trace": "EFT-20261018-02",
        "originator": "1234567890",
        "amount": 80,
        "date": "2026-10-18",
        "method": "ACH",
        "payer": "SAMPLE HEALTH PLAN",
        "claims": 4
      },
      "words": "Unmatched: no deposit among those sent matches this check. CAQH CORE 370 has the plan release the 835 within 3 business days of the EFT's effective entry date either way, so the money may not have settled yet."
    }
  ],
  "counts": {
    "checks": 2,
    "deposits": 2,
    "matched": 1
  },
  "words": "1 of 2 deposits matched to a check; 1 deposit and 1 check unmatched.",
  "how": "Matched by trace number first (TRN02, with TRN03 when the deposit names its originator), then by a trace printed in the bank's description (at least 6 characters, as a whole word), then by amount and date only where neither carries a trace …",
  "sources": [
    {
      "name": "CMS, EFT and ERA: Payment Remittance Reassociation Basics (June 2022)",
      "url": "https://www.cms.gov/files/document/eft-and-era-payment-remittance-reassociation-basics.pdf",
      "read_on": "10/19/2026"
    },
    {
      "name": "CAQH CORE, EFT and ERA Operating Rules Overview",
      "url": "https://www.caqh.org/sites/default/files/core/phase-iii/policy-rules/EFT-ERA_Rules_Overview.pdf",
      "read_on": "10/19/2026"
    }
  ],
  "reads": "Only the files and deposits sent in this call: nothing is stored, no bank description is repeated back, and no payer or bank is asked."
}

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
matcheslist of object
unmatched_depositslist of object
unmatched_checkslist of object
countsobject
wordsstring
howstring
sourceslist of object
readsstring

POST/v1/remittances/split

Split an 835 by payee or rendering provider

Send an 835 paid to one tax ID and get one file per payee (the provider the payer grouped the claims under) or per rendering NPI. Each file’s payment total is recomputed from its own claims and provider-level adjustments and read back to check it balances, the parts add up to the original check, and each keeps its trace. An adjustment that names no single group gets a file of its own, never a guessed one, and a value holding a delimiter is refused, never rewritten. Send the interchange control number you track for the first file (each further file takes the next): the original’s own number is never reused. The files are yours to load; nothing is sent.

Request

curl -sS -X POST "$PAYERWORKS_BASE_URL/v1/remittances/split" \
  -H "Authorization: Bearer $PAYERWORKS_API_KEY" \
  -H "Content-Type: application/json" \
  -d @request.json
request.jsonJSON
{
  "x12": "ISA*00*          *00*          *ZZ*SAMPLEPAYER    *ZZ*SAMPLEBILLER   *261018*0900*^*00501*000000094*0*T*:~\nGS*HP*SAMPLEPAYER*SAMPLEBILLER*20261018*0900*94*X*005010X221A1~\nST*835*0001~\nBPR*I*330*C*ACH*CCP*01*999999999*DA*123456*1234567890**01*999999999*DA*654321*20261018~\nTRN*1*EFT-20261018-03*1234567890~\nDTM*405*20261018~\nN1*PR*SAMPLE HEALTH PLAN*PI*99999~\nN1*PE*SAMPLE FAMILY MEDICINE*FI*123456789~\nLX*1~\nTS3*1234567893*11*20261231*1*240~\nCLP*PW-2101*1*240*180*60*12*PAYER-CN-31*11~\nCAS*PR*2*60~\nNM1*QC*1*PATIENT*SAMPLE****MI*W123456789~\nNM1*82*1*SAMPLE*SAM****XX*1234567893~\nSVC*HC:99213*240*180~\nDTM*472*20261001~\nLX*2~\nTS3*1999999992*11*20261231*1*200~\nCLP*PW-2102*1*200*170*30*12*PAYER-CN-32*11~\nCAS*PR*2*30~\nNM1*QC*1*PATIENT*SECOND****MI*W987654321~\nNM1*82*1*SAMPLE*SARA****XX*1999999992~\nSVC*HC:99214*200*170~\nDTM*472*20261002~\nPLB*123456789*20261231*WO:PAYER-CN-32 PW-2102*20~\nSE*24*0001~\nGE*1*94~\nIEA*1*000000094~",
  "by": "payee",
  "control_number": 1
}
The answer (200)JSON
{
  "by": "payee",
  "transmitted": false,
  "files": [
    {
      "group": {
        "by": "payee",
        "key": "1234567893",
        "stated": true
      },
      "claims": 1,
      "checks": [
        {
          "trace": "EFT-20261018-03",
          "original_amount": 330,
          "amount": 180,
          "claims_paid": 180,
          "provider_adjustments": 0
        }
      ],
      "ties": true,
      "isa_control": "000000001",
      "x12": "ISA*00*          *00*          *ZZ*SAMPLEPAYER    *ZZ*SAMPLEBILLER   *261019*1500*^*00501*000000001*0*T*:~GS*HP*SAMPLEPAYER*SAMPLEBILLER*20261019*1500*1*X*005010X221A1~ST*835*0001~BPR*I*180*C*ACH*CCP*01*999999999*DA*123456*1234567890**01*99…",
      "words": "The claims the payer grouped under provider 1234567893."
    },
    {
      "group": {
        "by": "payee",
        "key": "1999999992",
        "stated": true
      },
      "claims": 1,
      "checks": [
        {
          "trace": "EFT-20261018-03",
          "original_amount": 330,
          "amount": 150,
          "claims_paid": 170,
          "provider_adjustments": 20
        }
      ],
      "ties": true,
      "isa_control": "000000002",
      "x12": "ISA*00*          *00*          *ZZ*SAMPLEPAYER    *ZZ*SAMPLEBILLER   *261019*1500*^*00501*000000002*0*T*:~GS*HP*SAMPLEPAYER*SAMPLEBILLER*20261019*1500*2*X*005010X221A1~ST*835*0001~BPR*I*150*C*ACH*CCP*01*999999999*DA*123456*1234567890**01*99…",
      "words": "The claims the payer grouped under provider 1999999992."
    }
  ],
  "checks": [
    {
      "trace": "EFT-20261018-03",
      "original_amount": 330,
      "parts_total": 330,
      "parts_add_up": true,
      "original_ties": true,
      "claims_kept": true,
      "provider_adjustments": [
        {
          "code": "WO",
          "reference": "PAYER-CN-32 PW-2102",
          "amount": 20,
          "provider": "123456789",
          "group": "1999999992",
          "assigned_by": "its reference (PLB03-2) names a claim in this group"
        }
      ]
    }
  ],
  "balanced": true,
  "how": "In each file, each check's BPR02 is recomputed as its claims' payments (CLP04) less its provider-level adjustments (PLB), BPR03 C, or D with the amount unsigned when that is negative. The LX numbers are renumbered, a TS3 whose loop is cut s…",
  "notes": [],
  "words": "Split into 2 files by payee; every file ties and the parts add up to the original."
}

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
byone of "payee", "rendering_npi"
transmittedthe value falsePayerworks wrote the files and sent them nowhere.
fileslist of object
checkslist of object
balancedboolean
howstring
noteslist of string
wordsstring

POST/v1/remittances/recoupments

Match recoupments to the claims they take back

Send a set of 835s. Every provider-level adjustment is named, and each takeback is matched to the paid claim its reference names in the files you sent: by payer claim number, then patient control number, then amount when only one earlier payment at the same payer fits. Unmatched takebacks are listed, with what each payer took back and what the files show still carried forward. It says what was taken and from which claim, never whether it should have been.

Request

curl -sS -X POST "$PAYERWORKS_BASE_URL/v1/remittances/recoupments" \
  -H "Authorization: Bearer $PAYERWORKS_API_KEY" \
  -H "Content-Type: application/json" \
  -d @request.json
request.jsonJSON
{
  "remittances": [
    "ISA*00*          *00*          *ZZ*SAMPLEPAYER    *ZZ*SAMPLEBILLER   *261018*0900*^*00501*000000001*0*T*:~\nGS*HP*SAMPLEPAYER*SAMPLEBILLER*20261018*0900*1*X*005010X221A1~\nST*835*0001~\nBPR*I*1260*C*ACH*CCP*01*999999999*DA*123456*1234567890**01*999999999*DA*654321*20261018~\nTRN*1*EFT-20261018-01*1234567890~\nN1*PR*SAMPLE HEALTH PLAN*PI*99999~\nN1*PE*SAMPLE SLEEP DENTISTRY*XX*1234567893~\nLX*1~\nCLP*PW-1001*1*2900*1260*240*12*PAYER-CN-1*11~\nCAS*CO*45*1400~\nCAS*PR*2*240~\nNM1*QC*1*PATIENT*SAMPLE~\nDTM*472*20261001~\nSVC*HC:E0486*2900*1260~\nAMT*B6*1500~\nCLP*PW-1002*4*350*0*0*12*PAYER-CN-2*11~\nCAS*CO*50*350~\nNM1*QC*1*PATIENT*SECOND~\nDTM*472*20261002~\nSVC*HC:95800*350*0~\nLQ*HE*N115~\nSE*20*0001~\nGE*1*1~\nIEA*1*000000001~",
    "ISA*00*          *00*          *ZZ*SAMPLEPAYER    *ZZ*SAMPLEBILLER   *261018*0900*^*00501*000000095*0*T*:~\nGS*HP*SAMPLEPAYER*SAMPLEBILLER*20261018*0900*95*X*005010X221A1~\nST*835*0001~\nBPR*I*50*C*ACH*CCP*01*999999999*DA*123456*1234567890**01*999999999*DA*654321*20261102~\nTRN*1*EFT-20261102-01*1234567890~\nDTM*405*20261102~\nN1*PR*SAMPLE HEALTH PLAN*PI*99999~\nN1*PE*SAMPLE SLEEP DENTISTRY*XX*1234567893~\nLX*1~\nCLP*PW-1006*1*150*150*0*12*PAYER-CN-6*11~\nNM1*QC*1*PATIENT*FIFTH****MI*W777777777~\nSVC*HC:99213*150*150~\nDTM*472*20261020~\nPLB*1234567893*20261231*WO:PAYER-CN-1 PW-1001*100~\nSE*13*0001~\nGE*1*95~\nIEA*1*000000095~"
  ]
}
The answer (200)JSON
{
  "adjustments": [
    {
      "check": {
        "file": 1,
        "check": 0,
        "trace": "EFT-20261102-01",
        "originator": "1234567890",
        "amount": 50,
        "date": "2026-11-02",
        "method": "ACH",
        "payer": "SAMPLE HEALTH PLAN",
        "claims": 1
      },
      "provider_identifier": "1234567893",
      "code": "WO",
      "label": "Overpayment recovery",
      "kind": "claim_recoupment",
      "known": true,
      "label_source": "paraphrase",
      "amount": 100,
      "effect": "withheld",
      "reference": "PAYER-CN-1 PW-1001",
      "takeback": true,
      "match": {
        "matched_by": "payer_claim_number",
        "matched_on": "CLP07",
        "token": "PAYER-CN-1",
        "claim": {
          "reference": "PW-1001",
          "payer_claim_number": "PAYER-CN-1",
          "status_code": "1",
          "paid": 1260,
          "billed": 2900,
          "service_date": "2026-10-01",
          "check": {
            "file": 0,
            "check": 0,
            "trace": "EFT-20261018-01",
            "originator": "1234567890",
            "amount": 1260,
            "date": "2026-10-18",
            "method": "ACH",
            "payer": "SAMPLE HEALTH PLAN",
            "claims": 2
          }
        },
        "reversed_in_files": null
      },
      "matched": true,
      "ambiguous": false,
      "words": "WO (overpayment recovery): $100.00 withheld from check EFT-20261102-01 of 11/02/2026 (file 2), matched to claim PW-1001 paid $1,260.00 on check EFT-20261018-01 of 10/18/2026 (file 1), by the payer claim number PAYER-CN-1 (CLP07) in its refe…"
    }
  ],
  "reversals": [],
  "payers": [
    {
      "payer": "SAMPLE HEALTH PLAN",
      "originator": "1234567890",
      "checks": 2,
      "adjustments": 1,
      "taken_back": 100,
      "matched_taken_back": 100,
      "unmatched_taken_back": 0,
      "returned": 0,
      "reversed_on_claims": 0,
      "other_withheld": 0,
      "other_added": 0,
      "forwarding_balance_net": 0,
      "open_balance": 0,
      "words": "SAMPLE HEALTH PLAN: $100.00 taken back from claims by provider-level adjustment, $100.00 of it matched to a claim in these files and $0.00 not."
    }
  ],
  "counts": {
    "checks": 2,
    "adjustments": 1,
    "takebacks": 1,
    "matched": 1,
    "unmatched": 0,
    "reversals": 0
  },
  "words": "1 takeback by provider-level adjustment, 1 matched to a claim in these files; 0 claim reversals.",
  "how": "Each provider-level adjustment is named by X12's list of PLB reason codes and matched to the one claim payment its reference (PLB03-2) names at the same payer: the payer claim control number (CLP07) first, then the patient control number (C…",
  "source": {
    "list": "X12 provider adjustment reason codes (code list 967)",
    "url": "https://x12.org/codes/provider-adjustment-reason-codes",
    "read_on": "10/19/2026"
  },
  "reads": "Only the files sent in this call: nothing is stored, and no payer is asked."
}

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
adjustmentslist of object
reversalslist of object
payerslist of object
countsobject
wordsstring
howstring
sourceobject
readsstring

GET/v1/filing-limits

Published claim filing windows

The claim filing window each payer in Payerworks’ table publishes, read on its own pages on 09/10/2026, and Medicare fee-for-service’s from 42 CFR 424.44. Search with q, and add date_of_service to count the last day where the payer states one figure; a payer whose pages leave the window to its agreement says so, with no day. Your agreement with the payer governs over a published window, and nothing here is a payer’s answer about a claim.

Request

curl -sS -X GET "$PAYERWORKS_BASE_URL/v1/filing-limits?q=select&date_of_service=2026-03-15" \
  -H "Authorization: Bearer $PAYERWORKS_API_KEY"
The answer (200)JSON
{
  "total": 1,
  "data": [
    {
      "slug": "select-health",
      "payer": "Select Health",
      "applies_to": null,
      "answer": "window",
      "answer_words": "A published window",
      "words": "1 year from the date of service.",
      "window": {
        "years": 1
      },
      "date_of_service": "2026-03-15",
      "last_day": "2027-03-15",
      "last_day_words": "File by 03/15/2027.",
      "source": {
        "url": null,
        "read_on": "09/10/2026",
        "words": "Read on the payer's own pages on 09/10/2026; the page's address was not kept."
      }
    }
  ],
  "note": "A payer's own agreement with you, or the plan's document, governs over a published window; a secondary claim's window may differ. Nothing here is a payer's answer about a claim."
}
Field, Type, What it is
FieldTypeWhat it is
totalinteger
datalist of FilingLimit
notestring

GET/v1/filing-limits/{payer}

One payer’s filing window

One payer by its slug from GET /v1/filing-limits, or by its name, with every plan line it publishes a window for; add date_of_service to count the last day. A payer with no window on record is 404 no_filing_limit_on_record, never a window.

Request

curl -sS -X GET "$PAYERWORKS_BASE_URL/v1/filing-limits/select-health?date_of_service=2026-03-15" \
  -H "Authorization: Bearer $PAYERWORKS_API_KEY"
The answer (200)JSON
{
  "payer": "Select Health",
  "data": [
    {
      "slug": "select-health",
      "payer": "Select Health",
      "applies_to": null,
      "answer": "window",
      "answer_words": "A published window",
      "words": "1 year from the date of service.",
      "window": {
        "years": 1
      },
      "date_of_service": "2026-03-15",
      "last_day": "2027-03-15",
      "last_day_words": "File by 03/15/2027.",
      "source": {
        "url": null,
        "read_on": "09/10/2026",
        "words": "Read on the payer's own pages on 09/10/2026; the page's address was not kept."
      }
    }
  ],
  "note": "A payer's own agreement with you, or the plan's document, governs over a published window; a secondary claim's window may differ. Nothing here is a payer's answer about a claim."
}
Field, Type, What it is
FieldTypeWhat it is
payerstring
datalist of FilingLimit
notestring

Reading the answer

  • A claim’s verdict comes from the money and the refusing codes, never from CLP02 alone: a refusal often arrives as CLP02 1 with nothing paid.
  • primary_reason is null when nothing refused money. A contractual write-off (CO-45) on a paid claim is not why a claim was refused.
  • A deadline cites its source or has no date: Medicare’s own windows from the regulation for Medicare claims, else the limits you send, else null.
  • A file with several checks says each check apart, and no single number or total for the file.

Troubleshooting

  • not_an_835 (422): The file is not an 835. A 277CA or a 999 goes to POST /v1/acknowledgments/explain.
  • is_a_remark_code (400): N115 and other remark codes (RARCs) are not adjustment reason codes; the CARC lookup refuses them and says so.
  • missing_facts (422): An appeal letter needs facts that were not sent; the answer lists them, and nothing is written.
  • letter_refused (422): A fact held a placeholder in brackets, which the letter guard refuses.
  • no_filing_limit_on_record (404): No published filing window is on record for that payer: ask the payer or read your agreement. A window is never guessed.

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
deposits_required400Send the bank's deposits as deposits: a list of { amount, effective_date, trace_number?, originator?, description?, id? }.
invalid_code400An adjustment reason code is one to four digits, or a letter and digits (such as 45, A1 or B13), optionally after its group.
invalid_date_of_service400date_of_service is a day, YYYY-MM-DD.
invalid_group_code400A claim adjustment group code is two letters, such as CO or PR.
invalid_letter400Send the letter's text as letter, at most 20000 characters.
invalid_payer400Name the payer by its slug from GET /v1/filing-limits, or by its name.
invalid_split_by400by is "payee" (the 2000 loop's provider, TS301) or "rendering_npi" (each claim's rendering provider, NM1*82).
is_a_remark_code400This is a remittance advice remark code (RARC), not a claim adjustment reason code (CARC).
no_remittance400Send an 835 as x12, or the claims as a list in claims.
no_remittances400Send the 835s as remittances: a list of X12 files, each the file's text.
no_x12400Send the file's text as x12.
too_many_claims400At most 100 claims a call.
two_inputs400Send either x12 (an 835) or claims (a list), not both.
unknown_letter_kind400kind is one of the letter kinds the answer lists, with the facts each requires.
no_filing_limit_on_record404No published filing window is on record for this payer. Ask the payer, or read your agreement with it; GET /v1/filing-limits lists every payer that has one.
too_many_remittances413More was sent than one call reads across its files (at most 50 files, 1000 checks, 5000 claims, 5000 provider-level adjustments and 2000 deposits): the error names the unit and the limit. Send fewer in each call.
invalid_claim_facts422One or more claims or facts are not usable; nothing was decided. Each problem is listed with its field.
invalid_deposits422One or more deposits are not usable; nothing was matched. Each problem is listed with its field.
invalid_letter_facts422One or more facts are not usable; nothing was written. Each is listed with its field.
letter_refused422The letter was not written: a fact holds a placeholder in brackets, which the guard refuses.
missing_facts422The letter needs facts that were not sent; the answer lists them.
mixed_functional_groups422This interchange holds functional groups of different kinds: send each kind in its own interchange, so no part of it goes unread.
not_an_835422This is not an 835 remittance.
value_holds_a_delimiter422A value in the file holds one of the characters Payerworks writes as a delimiter (* : ^ ~), so it cannot be copied unchanged; nothing was written.

Code lists

Any one code in words: GET /v1/codes/carc/{code}, GET /v1/codes/group/{code}.

A remittance claim’s verdict

paid, partially_paid, denied, applied_to_patient, nothing_payable, reversal, reversal_and_repaid, forwarded, pending

The next steps on a denial

Step, What to do, In words
StepWhat to doIn words
correctCorrect the claim and send a replacementThe payer says something on the claim was missing or wrong. Fix it and send a replacement claim (frequency code 7) that carries the payer's claim number. An appeal is not the route for this.
attachSend what the payer asked forThe remark codes say what the payer is missing. Send it, on a replacement claim with a PWK segment naming the attachment, or enclosed with an appeal, as the payer's instructions say.
disputeCheck the payment against your contractThe payer allowed less than your charge. That is normal under a contract; it is an underpayment only if the allowed amount is below your contracted rate for this service. If it is, ask the payer to reprocess the claim at the contracted amount.
timelyAppeal with proof of timely filingThe payer says the claim was filed after its limit. If you filed in time, appeal with your proof of filing, such as the acceptance acknowledgment (999 or 277CA) for the original claim and its date. A replacement claim cannot cure a filing limit.
duplicateFind the original claim before sending anythingThe payer already holds a claim for this service. Find the original claim and its payment first: sending again makes more duplicates. Appeal only if this is a different service, and say what makes it different.
discoveryFind the coverage active on the date of serviceThe payer says the patient was not covered on the date of service. Check eligibility for that date, find the plan that was active, and file the claim to it.
cobBill the payers in the right orderThe payer says another plan pays first. Confirm the order of benefits with the patient and the plans, file to the primary, then file to this payer as secondary with the primary's payment. If the patient has no other coverage, tell the payer so it can correct its record. Payerworks does not write a secondary claim yet.
authAppeal with the authorizationThe payer says an authorization was missing or did not cover the service. If you had one, appeal with its number. If you did not, ask the payer whether it grants one after the service.
necessityAppeal with the clinical recordsThe payer says the service was not medically necessary. Appeal with the clinical records that support it, the ones the payer's coverage policy asks for.
non_coveredCheck the benefit, then appeal or bill the patientThe payer calls the service not covered. Check the patient's benefits for it: if the plan covers it, appeal with that evidence. If it does not, whether the patient may be billed depends on the group code (PR yes, CO no) and on any notice the patient signed in advance.
recoupmentReview the takebackThe payer took back money it had paid on this claim. Read the reason it gives; if you disagree, dispute the recoupment in writing and ask for the payment to be reinstated.
contract_cutRead the remittance before decidingThe payer reduced the charge to its contracted amount and paid nothing more. That can be the deductible, a coverage denial or an underpayment, and only the remittance's patient responsibility, group codes and remarks say which. Read them, then bill the patient, appeal, or dispute the allowed amount.
decideRead the denial and decideThe code alone does not decide the remedy. Read the remark codes and the payer's notes, then correct the claim, appeal it, or write it off.
post_paymentPost the paymentThe payer paid the claim. Post the payment and the contractual write-off; bill the patient only the patient responsibility.
bill_patientBill the patientThe payer processed the claim and put the allowed amount on the patient (deductible, coinsurance or copay). Nothing was refused, so there is nothing to appeal: bill the patient.
post_correctionPost the reversal, then the new paymentThe payer reversed its earlier payment and paid the claim again. Post the reversal against the original payment, then post the new payment.
await_new_decisionWait for the new decisionThe payer withdrew an earlier decision that paid nothing. No money moves; a new decision usually follows on a later remittance.
forwardedWait for the next payerThe payer processed the claim and sent it on to the next payer itself. Do not file it to that payer by hand; wait for its own remittance.
waitWait, or ask the payerThe payer has not finished this claim. Wait for its decision, or ask the payer where it stands (a claim status request, a 276).
new_claimSend a new claimThe payer says the claim could not be processed (remark MA130), so it has no appeal rights. Send a NEW claim (frequency code 1) with the information completed or corrected.
resendFix the rejection and send it againThe claim was rejected at the payer's front end and never entered adjudication. Fix what the rejection names and send it again as a new claim (frequency code 1).
post_no_paymentPost the adjudication: nothing is payableThe payer finished the claim and nothing is payable: the contractual or prior-payer adjustments account for the whole charge. Post it with its write-off. Check the allowed amount against your contract only if you believe it is wrong.
paid_shortAsk the payer to pay its own allowed amountThe payer paid less than its own allowed amount less the patient's share, and gave no reason beyond the contractual adjustment. Ask it to pay the rest, or to say why it did not. The underpayment letter states it from allowed_amount, paid_amount and patient_responsibility_amount; no contracted rate is needed.
necessity_patientAppeal, or bill the patientThe payer refused the service as not medically necessary and put it on the patient (group PR), which a payer does when the patient signed a notice in advance that the plan might not pay. Two doors are open: appeal with the clinical records if the service was necessary, or bill the patient under that notice.
timely_medicareAsk for an exception to the time limitMedicare does not treat a finding that a claim was filed late as an initial determination, so it cannot be appealed (42 CFR 405.926(n)). The only route is an exception to the filing limit under 42 CFR 424.44(b), such as a late filing caused by an error of CMS or its contractor, asked of your Medicare contractor with the evidence. If the claim was in fact filed in time, ask the contractor to correct its error.
duplicate_medicareAsk for a reopening, not an appealMedicare processes a denial of a claim as a duplicate as a clerical error, by reopening rather than by redetermination (42 CFR 405.980(a)(3)). Find the original claim first; if this is a different service, ask your Medicare contractor to reopen the claim and say what makes it different.

The appeal letter kinds

Kind, Subject, Facts it needs
KindSubjectFacts it needs
timely_filingRequest for reconsideration: timely filing denialpayer_name, patient_name, member_id, payer_claim_number, service_date, provider_name, signer_name, original_filing_date
authorization_on_fileRequest for reconsideration: authorization on filepayer_name, patient_name, member_id, payer_claim_number, service_date, provider_name, signer_name, authorization_number
records_enclosedRecords enclosed for review of this claimpayer_name, patient_name, member_id, payer_claim_number, service_date, provider_name, signer_name, enclosures
underpaymentRequest for reconsideration: payment below the amount duepayer_name, patient_name, member_id, payer_claim_number, service_date, provider_name, signer_name, allowed_amount, paid_amount
not_a_duplicateRequest for reconsideration: not a duplicate claimpayer_name, patient_name, member_id, payer_claim_number, service_date, provider_name, signer_name, distinguishing_facts
other_coverageRequest for reconsideration: coordination of benefitspayer_name, patient_name, member_id, payer_claim_number, service_date, provider_name, signer_name, other_coverage_status
medical_necessityRequest for reconsideration: medical necessitypayer_name, patient_name, member_id, payer_claim_number, service_date, provider_name, signer_name, clinical_summary, enclosures
recoupmentDispute of a recoupmentpayer_name, patient_name, member_id, payer_claim_number, service_date, provider_name, signer_name, recoupment_amount, recoupment_date
reconsiderationRequest for reconsideration of the appeal decisionpayer_name, patient_name, member_id, payer_claim_number, service_date, provider_name, signer_name, prior_appeal_date, reconsideration_reason

Example

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

remittances.mjsJavaScript
// Payerworks example: remittances and denials, explained claim by claim. Docs: https://payerworks.com/docs/remittances
//
// 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 remittances.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. A paid claim and a denied one (a member ID ending in DENY), answered by the sandbox payer with an 835.
  const sandbox = await pw.postSandboxClaims({ sender_id: SENDER_ID, claims: [claimEndingIn(''), claimEndingIn('DENY')] });
  const the835 = sandbox.files.remittance_835;

  // 2. The 835 claim by claim: paid, allowed, the patient's share and the verdict in words.
  const explained = await pw.postRemittancesExplain({ x12: the835 });

  // 3. Each denial as the next step, with every deadline and its source.
  const next = await pw.postDenialsNextStep({ x12: the835 });

  // 4. One adjustment reason code in words.
  const carc = await pw.getCodesCarcByCode('50');

  // 5. The failure path: N115 is a remark code, not an adjustment reason, and the lookup says so.
  const refused = await refusalOf(() => pw.getCodesCarcByCode('N115'), { PayerworksError });

  return {
    verdicts: Object.fromEntries(explained.claims.map((c) => [c.reference, c.verdict])),
    denied_claims: next.claims.filter((c) => c.reference === 'EX-DENY').length,
    carc_50: carc.label,
    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
{
  "verdicts": {
    "EX-PAID": "paid",
    "EX-DENY": "denied"
  },
  "denied_claims": 1,
  "carc_50": "Non-covered: not deemed a medical necessity",
  "refused": {
    "status": 400,
    "code": "is_a_remark_code",
    "request_id": "req_5"
  }
}

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.