Create Billing Profile Payer
Adds a payer to a billing profile, creating the shared payer record if it doesn't already exist.
Endpoint
POST /v2/billing-profiles/{billing_profile_id}/payers
Path Parameters
| Parameter |
Type |
Required |
Description |
billing_profile_id |
string |
Yes |
The billing profile this record belongs to. |
Request Body
| Parameter |
Type |
Required |
Description |
client_payer_name |
string |
Conditional |
Payer name as your organisation knows it. Required to add a payer; not accepted on a plan override. |
client_payer_id |
string |
No |
Your own identifier for this payer. Free text, not used for matching. |
payer_id |
string |
No |
ClaimMD payer id — the payer_code from List Payers, not its id. Matched against the clearing-house master; an unknown value creates the payer as UNVERIFIED. |
payer_type |
string |
No |
Payer category for this relationship — the new name of plan_type. Arrives with the payer-credentialing release; until then send plan_type. One of COMMERCIAL, MEDICARE, MEDICAID, BCBS, WORKERS_COMP, CHAMPUS, SELF_PAY, OTHER. |
plan_type |
string |
No |
Payer category for this relationship — the same value as payer_type, and the field to send until the payer-credentialing release; it stays accepted after it as a deprecated alias. Sending both with different values returns 400. One of COMMERCIAL, MEDICARE, MEDICAID, BCBS, WORKERS_COMP, CHAMPUS, SELF_PAY, OTHER. |
plan |
string |
Conditional |
Omit (or DEFAULT) to add the payer. A card plan type creates that plan's override of a payer already on the profile instead — billing-profiles organisations only — and then default_payer_id is required and only the override's own fields (network_status, accept_assignment, credentialed_by, routed_payer_id) are accepted. |
enrollment_seeds |
object |
No |
See Enrollment Seeds. |
default_payer_id |
string |
Conditional |
Plan override only, and required there: the id of the payer's DEFAULT row on this billing profile, which the override is copied from. |
network_status |
string or null |
No |
Plan override only. Written to the clinic (GROUP) credentialing row of the payer's plan. null = not set. One of IN_NETWORK, OUT_OF_NETWORK. |
accept_assignment |
boolean or null |
No |
Plan override only. Whether the provider accepts the payer's allowed amount as full payment. null = not set. |
credentialed_by |
string or null |
No |
Plan override only. Who the payer credentials for this plan: EACH_THERAPIST, CLINIC_ONLY (the clinic's contract covers its therapists; provider rows are optional) or NONE. Unset reads EACH_THERAPIST. null = not set. One of EACH_THERAPIST, CLINIC_ONLY, NONE. |
routed_payer_id |
string or null |
No |
Plan override only. Another payer on this billing profile whose contract this plan's claims are sent under — that payer's DEFAULT row id; it must not route anywhere itself. null = not set. |
Enrollment Seeds
| Parameter |
Type |
Required |
Description |
claims |
boolean |
No |
Whether to seed the claims channel into enrollment tracking (enrollment.claims) instead of leaving it NOT_APPLICABLE. |
eligibility |
boolean |
No |
Whether to seed the eligibility channel into enrollment tracking (enrollment.eligibility) instead of leaving it NOT_APPLICABLE. |
era |
boolean |
No |
Whether to seed the ERA channel into enrollment tracking (enrollment.era) instead of leaving it NOT_APPLICABLE. |
Request
Add a payer:
curl --location '{base_url}/v2/billing-profiles/b7e4c1a2-6f3d-4e9b-9a51-2c8d0f7e3a14/payers' \
--header 'Authorization: Bearer JWT_TOKEN' \
--header 'Content-Type: application/json' \
--data '{
"client_payer_name": "Cascade Health Plan",
"client_payer_id": "AET-01",
"payer_id": "CHP204",
"plan_type": "COMMERCIAL",
"enrollment_seeds": {
"claims": true,
"eligibility": true,
"era": true
}
}'
Or create a plan override of a payer already on the profile (billing-profiles organisations):
curl --location '{base_url}/v2/billing-profiles/b7e4c1a2-6f3d-4e9b-9a51-2c8d0f7e3a14/payers' \
--header 'Authorization: Bearer JWT_TOKEN' \
--header 'Content-Type: application/json' \
--data '{
"plan": "MEDICARE_HMO",
"default_payer_id": "9f1c8a2e-4b31-4d0a-9c77-2f5ab8e10c44",
"credentialed_by": "EACH_THERAPIST"
}'
Response
Success Response
Code: 201 Created
{
"id": "9f1c8a2e-4b31-4d0a-9c77-2f5ab8e10c44",
"billing_profile_id": "b7e4c1a2-6f3d-4e9b-9a51-2c8d0f7e3a14",
"payer_sec_id": null,
"client_payer_name": "Cascade Health Plan",
"client_payer_id": "AET-01",
"payer_id": "CHP204",
"master_name": "Cascade Health Plan",
"state": "VERIFIED",
"plan_type": "COMMERCIAL",
"payer_type": "COMMERCIAL",
"network_status": "IN_NETWORK",
"accept_assignment": true,
"fee_schedule_ref": null,
"effective_from": "2026-01-01",
"effective_to": null,
"enrollment": {
"claims": {
"status": "NOT_STARTED",
"branch": "FIXED",
"exceptions": {}
},
"eligibility": {
"status": "NOT_STARTED",
"branch": "FIXED",
"exceptions": {}
},
"era": {
"status": "NOT_STARTED",
"branch": "FIXED",
"exceptions": {}
}
},
"issues": [
{
"code": "PAYER_ID_NOT_IN_MASTER",
"severity": "error",
"message": "Payer id not found in the clearing-house master list."
}
],
"clearing_house": "CLAIM_MD",
"rollup_statuses": {
"claims": "IN_PROGRESS",
"eligibility": "COMPLETE",
"era": "NOT_APPLICABLE"
},
"display_labels": null,
"profile_payer_contract_id": null,
"plan": "DEFAULT",
"credentialed_by": "EACH_THERAPIST"
}
The Location header carries the URL of the created resource.
Response Fields
| Field |
Type |
Description |
id |
string |
This payer row's own id. |
billing_profile_id |
string |
The billing profile this record belongs to. |
payer_sec_id |
string or null |
Id of the underlying payer record, shared across every billing profile that uses it. |
client_payer_name |
string or null |
Payer name as your organisation knows it. |
client_payer_id |
string or null |
Your own identifier for this payer. Free text, not used for matching. |
payer_id |
string or null |
ClaimMD payer id — the payer_code from List Payers, not its id. Matched against the clearing-house master; an unknown value creates the payer as UNVERIFIED. |
master_name |
string or null |
The payer's name in the clearing-house master list, once resolved. |
state |
string |
Whether this payer mapping is confirmed against the clearing-house master. One of VERIFIED, UNVERIFIED, PAPER_ONLY, ARCHIVED. |
plan_type |
string or null |
Payer category for this relationship — the same value as payer_type, and the field to send until the payer-credentialing release; it stays accepted after it as a deprecated alias. Sending both with different values returns 400. One of COMMERCIAL, MEDICARE, MEDICAID, BCBS, WORKERS_COMP, CHAMPUS, SELF_PAY, OTHER. |
payer_type |
string or null |
Payer category for this relationship — the new name of plan_type. Arrives with the payer-credentialing release; until then send plan_type. One of COMMERCIAL, MEDICARE, MEDICAID, BCBS, WORKERS_COMP, CHAMPUS, SELF_PAY, OTHER. |
network_status |
string or null |
Whether the relationship is in-network or out-of-network. On a billing-profiles organisation it's derived from the clinic (GROUP) credentialing row of this payer and plan — IN_NETWORK when that row is in network on its dates — and writing it updates that row: IN_NETWORK keeps or creates it, OUT_OF_NETWORK ends a row that covered past dates today, otherwise clears its dates. One of IN_NETWORK, OUT_OF_NETWORK. |
accept_assignment |
boolean or null |
Whether the provider accepts the payer's allowed amount as full payment. |
fee_schedule_ref |
string or null |
Fee schedule this payer relationship bills against. |
effective_from |
string or null |
First day of the payer contract, YYYY-MM-DD. On a billing-profiles organisation it's the date of the clinic (GROUP) credentialing row for this payer and plan, and writing it writes that row. |
effective_to |
string or null |
Last day of the payer contract, YYYY-MM-DD; null while open-ended. On a billing-profiles organisation it's the date of the clinic (GROUP) credentialing row for this payer and plan, and writing it writes that row. |
enrollment |
object |
Enrollment status per channel — claims, eligibility and era — each with a per-dimension status (NOT_STARTED, REQUIREMENT_GATHERING, APPLICATION_SUBMITTED, COMPLETE, NOT_APPLICABLE), a branch (FIXED, MANUAL, NA), and per-provider exceptions mapping a provider id to its own status. See Enrollment. |
issues |
array of object |
Problems found while resolving this payer — for example an unrecognised payer id. See Issues. |
clearing_house |
string or null |
One of CLAIM_MD, AVAILITY, OFFICE_ALLY, OTHER. |
rollup_statuses |
object |
Aggregated enrollment status per channel: NOT_STARTED, IN_PROGRESS, COMPLETE, NOT_APPLICABLE. IN_PROGRESS is rollup-only — it never appears in enrollment.*.status. |
display_labels |
any |
Precomputed label strings for the dashboard's payer list. |
profile_payer_contract_id |
integer or null |
A stable id in the downstream billing system, once published. null before publish. |
plan |
string |
DEFAULT (every plan) or the card plan type this row overrides. Billing-profiles organisations only; absent elsewhere. |
credentialed_by |
string |
Who the payer credentials: EACH_THERAPIST, CLINIC_ONLY (the clinic's contract covers its therapists; provider rows are optional) or NONE. A row that never set it reads EACH_THERAPIST. Billing-profiles organisations only. One of EACH_THERAPIST, CLINIC_ONLY, NONE. |
routed_payer_id |
string or null |
Another payer on this billing profile whose contract this payer's claims are sent under — for a payer that hands its claims to another company. The other payer's row id (its DEFAULT row); it must not route anywhere itself. null clears. Billing-profiles organisations only; left out of responses when unset. |
Enrollment
| Field |
Type |
Description |
claims |
object |
Whether to seed the claims channel into enrollment tracking (enrollment.claims) instead of leaving it NOT_APPLICABLE. See Claims. |
eligibility |
object |
Whether to seed the eligibility channel into enrollment tracking (enrollment.eligibility) instead of leaving it NOT_APPLICABLE. See Eligibility. |
era |
object |
Whether to seed the ERA channel into enrollment tracking (enrollment.era) instead of leaving it NOT_APPLICABLE. See Era. |
Claims
| Field |
Type |
Description |
status |
string |
Lifecycle state of the record. One of NOT_STARTED, REQUIREMENT_GATHERING, APPLICATION_SUBMITTED, COMPLETE, NOT_APPLICABLE. |
branch |
string |
One of FIXED, MANUAL, NA. |
exceptions |
object |
|
Eligibility
| Field |
Type |
Description |
status |
string |
Lifecycle state of the record. One of NOT_STARTED, REQUIREMENT_GATHERING, APPLICATION_SUBMITTED, COMPLETE, NOT_APPLICABLE. |
branch |
string |
One of FIXED, MANUAL, NA. |
exceptions |
object |
|
Era
| Field |
Type |
Description |
status |
string |
Lifecycle state of the record. One of NOT_STARTED, REQUIREMENT_GATHERING, APPLICATION_SUBMITTED, COMPLETE, NOT_APPLICABLE. |
branch |
string |
One of FIXED, MANUAL, NA. |
exceptions |
object |
|
Issues
| Field |
Type |
Description |
code |
string |
Machine-readable issue code. |
severity |
string |
Whether this issue blocks resolution or is informational. |
message |
string |
Human-readable detail for this issue. |
Error Response
Code: 400 Bad Request
{
"code": "bad_request",
"message": "Validation failed",
"errors": [
{
"field": "patient_id",
"message": "must be a string"
}
]
}
Every error has the same shape — a machine-readable code, a message, and an errors[] array that's empty when there's nothing field-specific to report. The HTTP status is authoritative.
| Status |
code |
Meaning |
400 Bad Request |
bad_request |
The request body or parameters failed validation. errors[] names the offending fields. |
401 Unauthorized |
unauthorized |
The access token is missing, malformed or expired. |
403 Forbidden |
forbidden |
The request references a resource outside the token's organisation or clinic scope. |
404 Not Found |
not_found |
No such resource, or it's outside your scope. |
409 Conflict |
conflict |
The record conflicts with existing state — see the endpoint's notes. |
412 Precondition Failed |
precondition_failed |
If-Match is stale. Re-read the resource and retry. |
423 Locked |
locked |
The organisation has a publish in progress. Retry once it finishes. |
428 Precondition Required |
precondition_required |
If-Match is required on this write. |
429 Too Many Requests |
rate_limited |
Rate limit exceeded. Back off and retry. |
500 Internal Server Error |
internal_error |
Unexpected server error. |
502 Bad Gateway |
upstream_error |
Upstream service failed or timed out. |
Notes
payer_id is the ClaimMD payer id — payer_code on List Payers, not its id. Leave it blank and the payer is created UNVERIFIED until matched.
- The body takes one of two shapes. Without
plan (or with DEFAULT) it adds a payer: client_payer_name and optionally client_payer_id, payer_id, plan_type / payer_type, enrollment_seeds. With plan set to a card plan type it creates that plan's override of a payer already on the profile (billing-profiles organisations only; elsewhere 400 BILLING_PROFILES_ONLY): default_payer_id is required, and only network_status, accept_assignment, credentialed_by and routed_payer_id may be sent — null for any of them is the same as leaving it out. The override starts as a copy of the DEFAULT row; payer type, fee schedule, enrollment and dates stay on the DEFAULT row. A mistake is reported against the shape the body has: plan present and not DEFAULT means a plan override.
payer_type replaces plan_type, which stays accepted as a deprecated alias.
payer_type, plan, include_plan_overrides, the plan override and the payer policy fields (credentialed_by, routed_payer_id) arrive with the payer-credentialing release. Until it reaches your environment they are absent from responses and refused on writes (400); send the payer type as plan_type, which keeps working after it.
- When onboarding refuses a write, each
errors[] entry carries a code naming the rule that failed, and field names the field in snake_case, as this API spells it (an empty field means the whole row, or the whole create, not one field). A 400 for a body that fails this API's own schema check (an unknown field, a wrong type, a value outside the listed ones) has no code; its field is the JSON pointer of the offending value (/effective_from) or the name of the missing field. Codes from this endpoint: DUPLICATE_PLAN_ROW (409, the override exists), PAYER_ID_HELD_BY_HISTORY (409, on payer_id: a history credentialing row on a billing profile that carries this payer already uses that ClaimMD payer id, and this payer has its own row for the same provider; remove that row, let the removal publish, then retry), PAYER_ENTRY_UNKNOWN (default_payer_id or routed_payer_id isn't a row of this profile), PLAN_OVERRIDE_NEEDS_DEFAULT, PLAN_INVALID, ROUTED_PAYER_NOT_ATTACHED, ROUTED_PAYER_SELF, ROUTED_PAYER_NO_PAYER_ID (the routed payer has no ClaimMD payer_id), ROUTED_PAYER_CHAIN (the routed payer routes elsewhere itself), BILLING_PROFILES_ONLY.