Skip to main content

HomeCareBilling API changelog

Changes to the HomeCareBilling REST API, newest first. Each heading is the API version, as hcb-api-version and the OpenAPI document's info.version state it. Additive changes within a version are listed under it; a breaking change starts a new version under a new path. A deprecation is listed here with its sunset date at least six months before the operation stops answering.

1

Published September 24, 2026, at /api/v1. Deprecations: none.

Added October 24, 2026 (US-74.8, DCW Workforce Report):

  • GET /api/v1/reports/workforce (from, to, at most a year apart; limit, offset): each Direct Care Worker's hours, lowest wage, four-week average hours, members served and counties per primary service, for HCPF's Base Wage Attestation and Workforce Reporting. The MCP tool get_workforce_report answers the same function.

Changed October 24, 2026 (#2997, file answers that survive a cut):

  • MCP file answers carry base64 beside the download_url only up to 4 KB (was 16 KB). The answer holds the base64 twice, so a 12 KB 837 answered 33.9 KB, past a gateway that cuts near 20 KB, with the link after the cut point. delivery: "inline" is unchanged.
  • Company document and export files carry a charset only on text types (a PDF went out as application/pdf; charset=utf-8), and their file name in RFC 6266's encoded form (filename*=UTF-8''...).

Changed October 24, 2026 (#2997, print parameters by their names):

  • GET /api/v1/print/{form}, GET /api/v1/print/{form}/{id}.pdf and the get_print_document tool refuse a parameter the form does not read, naming the ones it does (400 bad_request; a tool error over MCP). It used to be ignored, so a client that sent date_from for a communication report's from got the default range with no sign of it. The operations' descriptions and the tool's params list what each form reads.
  • A print's PDF is served inline rather than attachment, so a person who opens an assistant's download_url sees it in the browser, ready to print.

Changed October 24, 2026 (#2997, file answers any AI client can open):

  • Every MCP file answer now carries a download_url that opens WITHOUT the Authorization header for 10 minutes: a signed link for that one file, on that one AI connection, so an assistant whose model cannot attach the connection's token, or the person it hands the link to, can open or print it. Each fetch re-checks the connection, the agency's consent and the member, as a token would; revoking the connection closes its links. The answer is private, no-store and sends no Referer. The token still works. The link is never the access token, which is still never read from a URL.
  • base64 now rides along only for a small file (4 KB since the entry above) (it encodes before the link, so a gateway that cuts a long answer would cut the link off too). delivery: "inline" sends base64 up to 1 MiB beside the link, for a client that must pass the bytes on.

Changed October 24, 2026 (#2997, an MCP client that cuts tool results short):

  • Every MCP tool that answers a file (get_print_document, print_client_work_orders, export_shift_plan, get_batch_837, get_person_document_file, get_company_document_file, get_data_export_file, get_client_note_attachment, get_caregiver_note_attachment) takes an optional delivery: auto, the default, answers as before (base64 up to 1 MiB, else a download_url); url answers only the /mcp/files download_url, whatever the size, without making the file. The fetch makes it, checks the record and writes the audit row, so a record that does not exist is reported there.

Changed October 23, 2026 (Epic 109, US-109.7, one status for many caregivers):

  • PATCH /api/v1/caregivers/status (caregiver_ids, at most 200, and status): sets each caregiver to the status, saving each one on its own so a refused save leaves the others saved. The answer lists updated and failed, each failure with the caregiver's id, name (null for an id that is not this agency's caregiver) and the reason in words. An archived caregiver is a failure, not a change. A caregiver already at the status counts as updated and writes no audit row; each one that changed writes one. One caregiver sent twice, in either letter case, is set and counted once. An unknown status or one that is not a string, no ids, more than 200, or an id that is not a string is 422 validation_failed, and nothing is written.
  • The MCP tool update_caregiver_statuses answers the same function. Its PHI access row names the agency's caregivers the call found, never an id it did not find.

Changed October 23, 2026 (Epic 109, US-109.3, the attention queue):

  • GET /api/v1/attention (kind, limit, offset): everything about a client or caregiver that needs doing, overdue first (oldest first, undated last among them), then soonest due. Each row carries kind (due_today, overdue, compliance, oig, supervisory_visit, recertification, authorization_ending, follow_up), subject_type (client, caregiver, or agency for a reminder with no client), subject_id, subject_name ("Last, First"), due_on, action_label ("Renew by Nov 3") and path, the app page that does it. limit defaults to 20 and is at most 100; total is the true count. An unknown kind is 422 invalid_kind.
  • The MCP tool needs_attention answers the same function.

Changed October 22, 2026 (Epic 108, US-108.9, the dollars unused on a PAR):

  • GET /api/v1/authorizations and GET /api/v1/authorizations/{id} carry unused_value: roughly what the authorized units no claim has billed yet are worth, in whole US dollars as a string ("2496"), at HCPF's published rate on the authorization's end date for its code and modifiers (HX dropped, as a PAR never carries it). Null unless the authorization is active, or when no published rate prices it. The MCP tools find_authorizations and get_authorization carry the same field.

Changed October 22, 2026 (Epic 108, US-108.3, underpaid claims):

  • GET /api/v1/underpayments (paid_from, paid_to, include_dismissed, limit, offset): paid claims HCPF paid less than its published rate for the dates of service, after the adjustments that lawfully explain short pay, the largest gap first. Each row carries claim_id, client_id, the service and paid dates, procedure_code, modifiers, units, published_rate, tenant_rate, expected, paid, gap, carcs (each with its description), and the kind and fingerprint to dismiss it with. The page adds total_gap, truncated (more than 5,000 paid claims in the period, so only the newest-paid were judged), paid_from and paid_to. Paid dates default to the last 90 days; a range over 366 days is 400. Dismissed rows are left out unless include_dismissed is true. Dismissing is POST /api/v1/revenue-warnings/dismissals with kind underpayment.
  • The MCP tool list_underpayments answers the same function.

Changed October 22, 2026 (Epic 108, US-108.5, resubmission deadlines):

  • GET /api/v1/resubmission-deadlines (within_days, include_dismissed, limit, offset): denied and unpaid claims, the soonest resubmit-by date first (id and claim_id, both the claim's id, batch_id, client_id, service_date_from, service_date_to, procedure_code, status, icn, resubmit_by, basis, days_left, kind, fingerprint, dismissed). A dismissed line is left out unless include_dismissed=true; dismiss one with POST /api/v1/revenue-warnings/dismissals, kind resubmission_deadline.
  • The MCP tool list_resubmission_deadlines answers the same function.

Changed October 22, 2026 (Epic 108, US-108.1, dismissible revenue warnings):

  • GET /api/v1/batches/{id}/revenue-warnings: every revenue warning on the batch's claims, in row order (claim_id, row_number, kind, fingerprint, message, dismissed), paged. A warning blocks nothing. Another agency's batch answers 404.
  • POST /api/v1/revenue-warnings/dismissals (kind, subject_id, fingerprint) dismisses one until its figures change, 201 with the dismissal; dismissing one already dismissed answers the existing dismissal. DELETE /api/v1/revenue-warnings/dismissals with the same body shows it again, 204. An id naming no claim of the agency answers 404 before the rest of the body is judged; a kind no warning has is 422 unknown_kind.
  • The MCP tools list_batch_revenue_warnings, dismiss_revenue_warning and restore_revenue_warning answer the same functions.

Changed October 22, 2026 (Epic 108, US-108.8, Medicaid revalidation dates):

  • GET /api/v1/provider-revalidations, POST /api/v1/provider-revalidations, PATCH /api/v1/provider-revalidations/{id} and DELETE /api/v1/provider-revalidations/{id}: the revalidation due date for each NPI the agency bills under (npi, location_name, revalidation_due_on, notes), nearest first. Writes need an admin credential (403 forbidden otherwise); a changed date clears last_alerted_threshold, so it is reminded again at 90, 60 and 30 days.
  • The MCP tools list_provider_revalidations, save_provider_revalidation (adds, or changes one given provider_revalidation_id) and delete_provider_revalidation answer the same functions.

Changed October 22, 2026 (Epic 107, US-107.11, a client's month printed as one document):

  • GET /api/v1/print/{form} takes the form client_work_orders with client_id and month (YYYY-MM): every live Work Order of the client in force in that month, one sheet each, Personal Care before Homemaker, then by shift and WO #, footed "Page N of M" across the document; format=pdf, or /api/v1/print/client_work_orders/{client_id}.pdf, answers it as a PDF. Another agency's client, or a deleted one, answers 404.
  • The MCP tool print_client_work_orders (client_id, month) answers that PDF as the other print tools do.

Changed October 21, 2026 (Epic 107, US-107.10, one way to make a client's Work Orders):

  • GET /api/v1/clients/{id}/shift-plan and get_shift_plan carry other_work_orders, the client's live Work Orders made outside the Shift Plan that are in force this month or later (id, number, service, caregiver, effective_date, closing_date; at most 50), and hma, the client's HMA calculator week (plan_id, weekly_minutes) or null.
  • POST /api/v1/plans-of-care/{id}/work-orders/distribute and distribute_plan_work_orders carry shift_plan_work_orders, the Work Orders the client's Shift Plan made that are in force in the month, each with its shift_id; empty when the client has no Shift Plan. The Work Orders are made regardless.

Changed October 21, 2026 (Epic 107, US-107.14, the card's task columns):

  • GET /api/v1/clients/{id}/shift-plan and get_shift_plan: each card row gains min_task (a decimal string, the row's week over its visits as the printed Work Order writes it: 40 + 35 is "37.5"), times (its marks on the shift) and week (its day minutes added); all three null on a row with no marks on that shift.

Changed October 21, 2026 (Epic 107, US-107.6, one plan PDF):

  • GET /api/v1/print/{form} and the MCP tool get_print_document take the form shift_plan with client_id: the client's Shift Plan as one document, a Letter portrait sheet per shift, Personal Care's then Homemaker's, footed "Page N of M" across the plan; format=pdf answers it as a PDF. Another agency's client, or a deleted one, answers 404.

Changed October 21, 2026 (Epic 107, US-107.8, the Shift Plan in her words):

  • PUT /api/v1/clients/{id}/shift-plan/care-instructions/{shift_id} and the MCP tool set_shift_plan_care_instructions: one card's Care Instructions, as the card's box keeps them. They are that shift's Work Order notes: Generate writes them, and a change rewrites the notes of a Work Order already generated for the shift, audited as a relayed setting. Blank or null removes them; a text longer than a Work Order's notes hold answers 422 too_long, a shift id no plan has 404.
  • GET /api/v1/clients/{id}/shift-plan: settings.care_instructions; each card's after, care_instructions and caregiver_week (the shift's caregiver's week across the agency's clients, null with no active caregiver); each day's by_day, true when the shift starts at a time of its own that day (set through shift_settings by_day in PATCH); each service's off_tasks; each task row's split. A split task is no longer among warnings, and a caregiver who also works for another client at an overlapping or too-close time is named there, one line per day and visit.
  • A client's first Shift Plan takes the days, shifts a day, each shift's start and "after", the gap, the split and the marks of the agency's most recently changed one, instead of the fixed defaults; with no plan yet, the defaults.

Changed October 21, 2026 (Epic 107, US-107.3, a caregiver is optional and picks are saved):

  • PUT /api/v1/clients/{id}/shift-plan/caregivers/{shift_id} and the MCP tool set_shift_plan_caregiver: save the caregiver picked for a shift, or let go of it with caregiver_id: null, before Generate or after. A caregiver the agency has none of on file (another agency's, a deleted one) answers 404 and nothing is saved; an inactive one is saved and comes back as a warning.
  • GET /api/v1/clients/{id}/shift-plan and get_shift_plan carry caregivers, shift id => the caregiver picked for it.
  • POST /api/v1/clients/{id}/shift-plan/generate and generate_shift_plan_work_orders: a shift left out of caregivers takes its saved pick, no longer its Work Order's caregiver; each caregiver sent is saved as the shift's pick. A shift with no pick is skipped as no_caregiver and keeps the Work Order it has.

Changed October 21, 2026 (Epic 107, US-107.7, the task table as on her page):

  • POST /api/v1/clients/{id}/shift-plan/tasks/add and the MCP tool add_shift_plan_task: the task table's Add task. A task of the state form goes into the table on the Shift Plan, never on the Plan of Care, at 15 min × 1 = 15 min a week, or with the calculator's figures when it was taken out earlier. A task already in the table changes nothing; a name the form does not list for the service answers 422 unknown_task.
  • DELETE /api/v1/clients/{id}/shift-plan/tasks/{service}/{task} and the MCP tool remove_shift_plan_task: the task table's ×. The task leaves the table, the layout and the changed cells of its row; a task the table does not hold answers 404.
  • GET /api/v1/clients/{id}/shift-plan: task_table lists each service's tasks in the state form's order, under the form's names ("Meal Prep/Menu Planning", "Bladder Care"); each row gains norm, max and over_max (the state's weekly maximum, a warning only). New task_totals (each service's Min / week and CFC hours) and addable (the form's tasks Add task offers).

Changed October 21, 2026 (US-107.9):

  • POST /api/v1/cfc-calculator and the MCP tool create_client_from_cfc_calculator: a new client from a CFC calculator. The card read from it (last_name and first_name required; medicaid_id, address and phone when the calculator has them) makes the client, and the calculator's import job starts for it, as POST /api/v1/clients/{id}/cfc-calculator starts one. The answer's outcome is created, existing (the Medicaid ID, or with none the name, is on file for the same person: no client is made and the import is for that client) or conflict (the Medicaid ID is on file under another name: 200, import null, nothing written). A card the client form refuses answers 422 validation_failed, and nothing is made.
  • A calculator row whose Min / week is not its Min / task times its Times / week is imported with its days spread over that Min / week, so they add up to the week the task keeps.

Changed October 21, 2026 (Epic 107, US-107.1, a Shift Plan keeps the office's own cells):

  • POST /api/v1/clients/{id}/shift-plan/cells and set_shift_plan_cell take no lock_version and never answer 409: a cell is kept on the Shift Plan as the office's own value, on any shift, generated or not, and every later change lays the week out again under it. The count the automatic layout gives that cell lets go of the change. A shift the plan does not have, or a row on no Work Order task of the plan, answers 404. A lock_version still sent is ignored.
  • POST /api/v1/clients/{id}/shift-plan/undo and undo_shift_plan_edits let go of every cell change, then return each generated Work Order to the layout; they no longer answer 409.
  • GET /api/v1/clients/{id}/shift-plan: every card's day cells are the layout with the office's cells over it, a generated card's too, never its Work Order's stored lines; a cell's edited is true exactly where the office set it.

Changed October 21, 2026 (Epic 104, the Shift Plan):

  • GET /api/v1/clients/{id}/shift-plan and the MCP tool get_shift_plan: the client's Shift Plan as the Shift Plan screen shows it (made with the agency's defaults on the first read): its settings, each service's week against its calculator, one card per shift with its generated Work Order, day columns and rows of day cells, the task table, warnings and print_problems. Days are the plan's own, 0 Saturday to 6 Friday. Each read is audited against the plan and its client.
  • PATCH /api/v1/clients/{id}/shift-plan and update_shift_plan_settings: the settings sent, as the screen saves them; a malformed value answers 422 naming its field.
  • POST /api/v1/clients/{id}/shift-plan/cells and set_shift_plan_cell: one day cell, against the card's lock_version; a Work Order written since answers 409 stale_record and nothing is saved.
  • POST /api/v1/clients/{id}/shift-plan/undo and undo_shift_plan_edits: the screen's Undo my changes, answering undone_shifts.
  • POST /api/v1/clients/{id}/shift-plan/tasks and update_shift_plan_task: one task-table figure (times, min_task or min_week); a value not above 0 answers 422 invalid_figure, one past a week 422 too_large.
  • POST /api/v1/clients/{id}/shift-plan/generate and generate_shift_plan_work_orders: the screen's Generate, with optional caregivers per shift, answering generated (the Work Orders written, replaced, archived and skipped, and the warnings). Nothing is refused for the layout.
  • GET /api/v1/clients/{id}/shift-plan/export and export_shift_plan: the screen's Download Excel, audited as an export before it is sent.
  • Every write answers the Shift Plan as the screen shows it next, in data. Another agency's client answers 404.

Changed October 18, 2026 (#2567):

  • POST /api/v1/broadcasts and the MCP tool send_broadcast take recipient_scope pick, implied by either new field: caregiver_ids, the agency's caregivers to send to whatever their status (former ones included, at most 1000), and tag, every caregiver carrying it (any case), active ones only unless include_former is true. An id that is not one of the agency's caregivers answers 422 validation_failed. A caregiver opted out of SMS is never texted, on both too.
  • Broadcast gains reply_count and yes_count.
  • GET /api/v1/broadcasts and the MCP tool list_broadcasts: the agency's broadcasts, newest first, paged, each with message, reply_count and yes_count.
  • GET /api/v1/broadcasts/{id}/replies and the MCP tool list_broadcast_replies: the caregivers who texted back to a broadcast, latest first, each with the reply, yes and replied_at; another agency's broadcast answers 404. Each read is audited against the caregivers it returned.

Changed October 17, 2026 (US-102.37):

  • GET /api/v1/payroll-summary and the MCP tool get_payroll_summary: the Payroll Summary of a month (year, month, both required) or one of its pay periods (period, an index into pay_periods), computed as the Payroll Summary page computes it. Each caregiver's row carries the regular, overtime, daily overtime, travel and attendant hours, the rates applied, total_pay, the cash advance this payroll deducts and the timesheets the hours came from; rows are sorted by name and paged with limit and offset, and totals are over every row. A cash advance another payroll file holds is listed in cash_advance_held, worded as the page words it ("$50.00 on the Oct 01 - Oct 15, 2026 file"), and is in neither cash_advance nor the totals. Each read is audited against the caregivers it returned.
  • GET /api/v1/cash-advances and the MCP tool list_cash_advances: the agency's cash advances, newest first, filtered by status, search and deduct_in_month (YYYY-MM), paged, with totals of amount and remaining_balance over every advance the filters match.
  • CashAdvance gains reason, in every answer, and caregiver_name, in the list.
  • GET /api/v1/payroll/w4-changes and the MCP tool list_w4_changes: the caregivers whose W-4 changed since payroll was last sent it, longest waiting first, with the ADP file number, filing status, dependents and when it changed, as the Payroll Summary's W-4 panel lists them. Paginated with limit and offset; each read is audited against the caregivers it returned.
  • GET /api/v1/supervisory-visits/due and supervisory_visits_due take planned_for (YYYY-MM): only the clients whose planned supervisory visit falls in that month, by planned day, as the roster's month list shows them. Each row carries planned_day, the day capped to the month's last, null when no day is set. Any other form of planned_for is 400.

Changed October 17, 2026 (US-102.34):

  • GET /api/v1/clients/{id}/other-services, POST /api/v1/clients/{id}/other-services, PATCH /api/v1/client-other-services/{id} and DELETE /api/v1/client-other-services/{id}, and the MCP tools list_client_other_services, add_client_other_service, update_client_other_service and delete_client_other_service: a client's other services, the outside providers serving it (kind adult_day, cna, rn, pt or other; company, phone, address, description; days, any of su mo tu we th fr sa, kept in week order; and times, an optional time per chosen day). Each write is audited against the credential, as the client page's are. No kind, an unknown day or a field past its length answers 422 naming the field. Over MCP the typed fields, each time among them, answer as {"untrusted_text": ...}.
  • A client carries agency_services_only (the client has no outside providers, Access's MHS ONLY), on GET /api/v1/clients/{id}, the list and the MCP tool get_client. POST /api/v1/clients/{id}/agency-services-only and the MCP tool set_agency_services_only set it, with value and the lock_version the client was read with; a client changed since answers 409 stale_record. PATCH /api/v1/clients/{id} does not take it.
  • The agency profile carries work_order_print_certification: whether a printed Work Order carries the notice, certification and signature lines, true unless the agency turns it off (GET/PATCH /api/v1/agency, and the MCP tools get_agency_profile and update_agency_profile, admins only on write).

Changed October 16, 2026 (US-102.35):

  • POST /api/v1/clients/{id}/supervisory-plan and the MCP tool set_supervisory_plan: a client's planned supervisory visit slot, the month of each quarter (planned_supervisory_offset, 1 to 3) and the day of it (planned_supervisory_day, 1 to 31), as the client page sets them. Both null clears it, a day without a month is 422 validation_failed, and a lock_version read before another write is 409 stale_record. The client read (GET /api/v1/clients/{id}, get_client) carries both fields; the client PATCH does not write them.
  • POST /api/v1/work-orders/{id}/duplicate and duplicate_work_order take an optional mode (keep_both, close_previous, temporary) with effective_date, closing_date, temporary_from, temporary_to, client_id, caregiver_id and lock_version: a new standing Work Order with the next WO #, as the page's Duplicate makes it, answered as its first month with warnings. An admin or office manager only (403 duplicate_not_permitted). close_previous needs the lock_version the Work Order was read with (409 stale_record when it changed since); a choice the page refuses, a missing Effective Date included, is 422 duplicate_refused in its words, a close of an archived Work Order 422 work_order_archived. A field another mode takes, or these fields mixed with month and year, is 400. A body without mode copies one month, as before.
  • POST /api/v1/caregivers/{id}/w4-sent-to-payroll and the MCP tool mark_w4_sent_to_payroll: records that the payroll processor was sent a caregiver's W-4 change and clears it, as the Payroll Summary does. An optional w4_changed_at clears only the change read at that time (409 stale_record otherwise); a caregiver with none waiting is 422 no_w4_change. The W-4 values are never returned.

Changed October 11, 2026:

  • POST /api/v1/settings/sandata/certification/cases/{case} and the MCP tool send_sandata_certification_case: sends one Sandata certification test case, admin only and in the certification tenant only. The certification page read carries cases, each with its id, round, applied (null in round 1), why it is blocked, and state, how many of its records are accepted, waiting, refused (they go again on a send), parked (refused too often to go again until they change), held_back (they cannot be sent as they are) and to_send. 404 not_found for an unknown case, 409 not_ready while Sandata has not accepted what the case needs (the message names the cases to send first, and says which of them send a record refused too often), 422 no_records with no sample records, 409 nothing_to_send when every record of it is accepted, waiting, parked or held back, 500 case_incomplete when its change failed and changed nothing.
  • PATCH /api/v1/settings/sandata/certification/dry-run and the MCP tool set_sandata_dry_run: the certification tenant's dry-run switch. On, a test case writes the records it would send to the server log, keeps nothing and sends nothing, also while Sandata is paused. The certification page read carries dry_run, which is on until someone turns it off.
  • POST /api/v1/settings/sandata/certification/send and the MCP tool send_sandata_sample_records send the Employees and then the Clients test case, each on its own, and answer dry_run and each case's result beside queued, which is false in a dry run. A case refused while the other went carries refused, the code and message the case's own send would answer. POST /api/v1/settings/sandata/certification/send-visits and the MCP tool send_sandata_sample_visits send the next visit test case whose visits Sandata does not hold yet, one per call, and answer its case beside queued_visits; 409 not_ready is now about that case's clients and employees alone.
  • The certification page creates 8 sample clients and 8 employees (it created 5 of each), still with 20 visits.

Changed October 10, 2026:

  • A caregiver carries position: the job title the agency gives them, free text up to 200 characters (code points) (GET/PATCH /api/v1/caregivers/{id}, the list, POST /api/v1/caregivers, and the MCP tools update_caregiver and create_caregiver). Null until set. Over MCP it answers as {"untrusted_text": ...}, as text someone typed.

  • The MCP tools update_caregiver and update_client answer a card's address and city (a client's second address line and ACP address too) as {"untrusted_text": ...}, and a date of birth that is not an ISO date the same way, as get_caregiver and get_client already did. update_client answers the language preference that way too.

  • A client's or caregiver's date of birth that can no longer be read answers null, on /api/v1 and over MCP, rather than the text error; a caregiver's SSN that can no longer be read answers ssn_masked null rather than failing the request.

  • Over MCP, a date of birth an import stored as MMDDYYYY or M/D/YYYY answers as the YYYY-MM-DD date it is, as the rest of the app reads it; other text still answers as {"untrusted_text": ...}.

  • A PUT to a company-document upload slot that another PUT is still storing answers 409 upload_slot_in_progress; read it again shortly. A used slot's 409 upload_slot_used always names the document, and a slot whose store died before saving one may be used again after ten minutes.

  • A Work Order read (GET /api/v1/work-orders/{id}, the list, and the MCP tool get_work_order) answers seen_by_date: each date of its month to an opaque value (US-95.99). Send a date's value as seen to PUT /api/v1/work-orders/{id}/days/{date} or set_work_order_day, and a date changed since that read is refused (409 stale_record) with nothing written. The value is a hash; its format is not a contract.

  • A file an MCP tool answers with a download_url (one too large to carry inline: a note attachment, a company or person document, an export, an 837, a printed form) is fetched under /mcp/files/, with the AI connection's own token (US-95.98). Its /api/v1 twin refused that token, which is valid for /mcp only, so such a URL could not be fetched at all. The /api/v1 file routes are unchanged and still take an agency key.

  • Every error status an operation's description names is now in its responses, in the shared Error envelope, with the codes the description gives (US-95.54). The resources' list, get, create and update operations declare 400 bad_request, 404 not_found, 409 stale_record and 422 validation_failed where each applies. Nothing about the answers themselves changed; a client generated from the document now handles them.

  • A save that lost a race with another write while the request ran answers 409 stale_record on every operation, and an MCP tool says the record changed since it was read. Nothing is saved, so read it again and retry. Before, only the supervisory visit lifecycle answered this way; a calendar event's restore, a visit exception's resolve or assignment, and any other write whose record moved answered 422 validation_failed.

  • The null rule of October 8 (US-95.62) now runs on every write with a body (US-95.89), among them the timesheet, Work Order content, generation and lifecycle, assignment lifecycle, visit exception, settings list, payroll, claim, report template, PAR lifecycle and caregiver app writes. A null or a blank on a field the body's schema does not declare nullable is 422 null_not_allowed naming it, and a body of one value (a direction, a status, a reason) refuses its null or blank by name. A nullable field's null empties it on a change, and on an action means the same as leaving it out (a sign date is today, a status change has no reason). The MCP tool for each write takes the same body, the integration settings writes, a person document's upload and metadata update and a restore's lock_version among them (US-95.100): a null or blank Sandata Account or provider id is refused by name, a null or blank username, password, Account SID or Auth Token keeps the saved one, and a JSON upload declares its body beside the multipart one.

  • A company document up to the page's limit through JSON (US-95.56): POST /api/v1/company-documents/uploads checks the document's details and answers a single-use upload_url, bound to the credential and the agency, and PUT /api/v1/company-documents/uploads/{token} takes the file's bytes as the body, with the same credential, and answers the stored document. The MCP tool upload_company_document answers such a slot, under /mcp, when it is called without file_base64 or with a file larger than it carries.

  • A record id is a UUID's 36-character text form, in either case, wherever one is sent (US-95.69): a path id, a body field, a query filter. Sixteen arbitrary characters were read as a raw UUID at some operations; they now name no record, so a path id answers 404 and an id among the /api/v1/visits/bulk-verify and /api/v1/visit-exceptions/resolve ids answers 422 validation_failed at both.

  • The rest of the Settings page is on the API (US-95.47), admin credentials only: GET /api/v1/settings/security and PUT /api/v1/settings/security (the two-factor requirement and the session timeout, saved together), POST /api/v1/users/{id}/two-factor/reset, GET /api/v1/settings/notifications, PATCH /api/v1/settings/notifications, GET /api/v1/settings/adp, PATCH /api/v1/settings/adp, GET /api/v1/settings/csv-mapping, PUT /api/v1/settings/csv-mapping, GET /api/v1/settings/tpid-authorized, PUT /api/v1/settings/tpid-authorized, and GET /api/v1/consents/{purpose}, POST /api/v1/consents/{purpose} and DELETE /api/v1/consents/{purpose} for external_ai_clients and api_access. GET /api/v1/me/reminder-preferences and PUT /api/v1/me/reminder-preferences read and set the caller's own reminder preferences, for any member. Each change writes an audit row naming the key.

  • Added POST /api/v1/work-orders/{id}/verify-for-billing and the MCP tool verify_work_order_for_billing, the timesheet page's Verify hours (US-95.44): the hours a Work Order's days carry become its verified hours, and one in progress is completed, writing or finding its caregiver report. It takes the lock_version the Work Order was read with and answers the Work Order, timesheet (what happened to the report) and completion (completed_now or already_complete). Added POST /api/v1/work-orders/{id}/timesheet/overwrite and the MCP tool overwrite_timesheet, the Work Order page's Overwrite: a completed Work Order's report is written again from its days and tasks, answering 201 with the new report. A report with a claim on a live batch answers 409 has_claims, its details giving total, by_status and timesheet_ids, and nothing changes; one with entries typed from the card answers 409 entries_typed.

Changed October 9, 2026:

  • Every printed form the web has is readable over the API (US-95.40): GET /api/v1/print/{form} answers the print page's own HTML, with its print layout, for the route's path and query parameters sent as query parameters by their names on the route, and format=pdf answers that page as a PDF; GET /api/v1/print/{form}/{id}, {id} being the record id then .pdf, is the PDF of one record's form. The forms, and the ids each takes, are listed in the operation's description. A record of another agency answers 404. Each print writes the audit row the web print writes, naming the credential. The MCP tool get_print_document answers the PDF.
  • The agency profile update refuses a null or blank name as null_not_allowed, naming it, before the save is tried (US-95.73); it was refused as validation_failed from the save. The service authorization, agency profile, certification, satisfaction survey, supervisory visit, monthly report and PAR check MCP tools now declare their parameters from these bodies, so a field the API lets you empty takes null over MCP too.
  • A supervisory visit or monthly report write now treats a field sent as a change: null or blank visit_date, supervisor_name or comments empties it, and a field left out is kept (US-95.87). Null used to be dropped as if the field had not been sent. Text is trimmed on both surfaces, and the nothing_to_change and invalid_answers refusals read the same over /api/v1 and MCP.
  • A request whose data store was busy or did not answer (a lost connection, a lock or statement timeout, a deadlock) before it saved anything now answers 503 temporarily_unavailable with Retry-After, and frees its Idempotency-Key, so a retry under the same key runs again (US-95.94). It used to answer an unmarked 500 that a retry under the key replayed. A request that had already saved part of its work still answers 500.
  • POST /api/v1/batches/from-timesheets answers 409 stale_record when the client, assignment, work order or service authorization a claim took its billing values from changed between the read and the export, as it already did for the timesheet itself (US-95.74). The batch it makes bills the claims it validated, from one pricing pass (US-95.68).
  • A write whose path names a record the agency does not have answers 404 not_found whatever its body holds (US-95.86). Some writes used to judge the body first and answer 400 or 422 for an id that named nothing. The order is now the same on every write with a path id: the id, then the body, then the lock_version (400 for a missing or malformed one, 409 for a stale one). The MCP write tools answer in the same order.
  • A plan of care's authorization_id takes null to unlink its PAR. An id that is not a PAR of the plan's own client, not deleted, now answers 422 naming authorization_id on a create or update, over REST and MCP alike; it used to save the plan unlinked, or ignore the id on an update. The link a plan already carries is kept when sent back, even once its PAR is deleted (US-95.85).

Added October 9, 2026:

  • GET /api/v1/settings/sandata, PATCH /api/v1/settings/sandata, POST /api/v1/settings/sandata/test, GET /api/v1/settings/telephony, PATCH /api/v1/settings/telephony, DELETE /api/v1/settings/telephony, POST /api/v1/settings/telephony/test and GET /api/v1/settings/{tab}/secrets/{key} (US-95.46): the Sandata and Telephony settings tabs, admin only. A read says whether each credential is saved; the secrets operation returns one with the tab's audit row. A telephony PATCH that changes credentials tests them with Twilio first.
  • GET /api/v1/settings/sandata/certification, PATCH /api/v1/settings/sandata/certification/steps/{key}, POST /api/v1/settings/sandata/certification/sample-records, DELETE /api/v1/settings/sandata/certification/sample-records, POST /api/v1/settings/sandata/certification/validate, POST /api/v1/settings/sandata/certification/send and POST /api/v1/settings/sandata/certification/send-visits (US-95.46): the Sandata certification page, admin only; the sample records are created, sent and removed only in the certification tenant.
  • POST /api/v1/claims/{id}/prepare-resubmission and POST /api/v1/batches/{id}/prepare-resubmissions (US-95.49): an admin releases a refused claim's timesheet, or a whole batch's, to be billed again, as the batch page's Release does.
  • POST /api/v1/claims/{id}/evv-override and POST /api/v1/claims/{id}/follow-up (US-95.49): override a claim's EVV warning with a reason, and open a denial follow-up.
  • GET /api/v1/clients/{id}/documents, POST /api/v1/clients/{id}/documents, GET /api/v1/caregivers/{id}/documents, POST /api/v1/caregivers/{id}/documents, GET /api/v1/documents/{id}, PATCH /api/v1/documents/{id}, DELETE /api/v1/documents/{id} and GET /api/v1/documents/{id}/file (US-95.48): the documents on a client's or caregiver's file, as the Documents tab keeps them. A file downloads only once its virus scan is clean (404 not_scanned_clean before).
  • GET /api/v1/meeting-minutes, POST /api/v1/meeting-minutes, GET /api/v1/meeting-minutes/{id}, PATCH /api/v1/meeting-minutes/{id}, DELETE /api/v1/meeting-minutes/{id} and POST /api/v1/meeting-minutes/{id}/finalize (US-95.43): the Compliance meeting minutes pages, from draft to finalized. Finalized minutes refuse any change (422 not_draft).
  • GET /api/v1/oig-attestations, POST /api/v1/oig-attestations and GET /api/v1/oig-attestations/{id} (US-95.43): the monthly OIG exclusion attestation; its report is named by a company document of the agency.
  • GET /api/v1/denials (US-95.50): the claims the remittance did not pay, newest payment first, filtered by payment_date_from/payment_date_to and member, each CARC and RARC with its plain-English meaning.
  • POST /api/v1/query (US-95.41): the aggregate counts the AI assistant answers (a count, a per-status breakdown, a date-range count, or the records missing data). Stores nothing, so it takes no Idempotency-Key and a read-only account may ask it.
  • POST /api/v1/timesheets/{id}/export and POST /api/v1/timesheet-entries/{id}/pull-evv (US-95.45): the returned timesheet bar's Export and the entries page's Pull EVV. A timesheet entry now also carries evv_clock_in, evv_clock_out and visit_id.

Added October 9, 2026 (US-95.42): what the client, caregiver and batch pages show of SSN, medical information and the 837 file.

  • Clients and caregivers carry ssn_masked (***-**- and the last four digits), and their POST and PATCH take a full ssn, which is never returned. An ssn in a body used to be ignored.
  • GET /api/v1/clients/{id}/medical and PATCH /api/v1/clients/{id}/medical read and write the client page's Medical tab.
  • GET /api/v1/batches/{id}/837 downloads a batch's 837 file as Batch Detail does.

Changed October 8, 2026 (US-95.62): one null rule for the record writes, read from the request body's schema. It runs on the POST and PATCH of assignments, authorizations, caregivers and their trainings, evaluations and vaccinations, clients, client certifications, satisfaction surveys, client and caregiver notes, complaints, critical incidents, plans of care, prospects, service rates, supervisory visits, support tickets, task set templates, visits and work orders, and now also on PATCH /api/v1/agency, POST /api/v1/satisfaction-surveys/{id}/complete and the monthly report save (POST /api/v1/work-orders/{id}/monthly-report), which did not refuse a null before. Every other write reads its body as it did.

On those writes a field left out is unchanged, and no value the server accepts is changed on the way in:

  • A null or a blank ("" or whitespace) on a field the schema does NOT declare nullable is 422 null_not_allowed naming the field. A null there was already refused; a blank used to reset the field to its default (status: "" on a client, visit_type: "" on a visit) or was refused with another code (validation_failed for a blank first_name or claim default, field_required for a blank support ticket subject).
  • These fields are now declared not nullable, since the record requires them: a service rate's procedure_code, rate_per_unit and effective_date; an assignment's billing_code and effective_date; a plan of care's effective_date; a prospect's first_name, last_name and phone; a task set template's name; a note's note_date and note_text; a training's completed. A null on one was validation_failed, and on a plan's effective_date a 200 that changed nothing; it is now null_not_allowed.
  • A null or a blank on a field the schema declares nullable reaches the write as before. On a PATCH it empties the field, or, on a field the record still requires (an authorization's authorized_units, a complaint's complaint_date), is 422 naming it. Three writes do otherwise, and keep doing so: a supervisory visit write and a monthly report save keep the field on a null (a blank empties it), and a completed training's expiry_date is set to a year after its completion.
  • A list holding a null element is refused naming the list, where it could store the null (a plan's tasks holding a null was a 400 and is now this 422).

MCP's create and update tools for visits, assignments, Work Orders, plans of care, service rates, prospects and task set templates take the same schemas and answer the same calls alike. MCP's other write tools still refuse a null on a property they do not declare nullable, even where this API takes it. Changed October 8, 2026 (US-95.79): a failure that is not the caller's is answered by what a retry can achieve, the same on every operation that stores or reads a file (the ten that document it). A file store that did not answer, or an upload whose temporary file could not be read for a reason that clears by itself, is 503 (storage_unavailable for the file store, temporarily_unavailable for the upload) with Retry-After: 30. A file store that refused the request, a virus scan that could not be queued or an upload that could not be read for any other reason is 500 internal_error. A record whose file is gone is 410 file_missing, its message saying to generate or upload the file again; only the five operations that read a stored file document or answer it. The answers that changed:

  • GET /api/v1/payroll-exports/{id}/file: file_missing where it said no_file.
  • GET /api/v1/company-documents/{id}/file: 410 or 500 where it said 503 retrieve_failed.
  • GET /api/v1/note-attachments/{id}: 503, 500 or 410 where it said 404.
  • GET /api/v1/exports/{id}/file: 503 or 500 where an unreadable file said 410, and 409 export_failed, its message the export's own reason, where a failed export said 409 not_ready.
  • POST /api/v1/provider-care-plans/{id}/reconciliation/preview: 503, 500 or 410 where a PCSP the store could not read said 422 unreadable_document.
  • POST /api/v1/company-documents and POST /api/v1/clients/{id}/pcsp-documents: 503 or 500 where a store, scan-queue or upload failure said 422 validation_failed.
  • POST /api/v1/client-notes/{id}/attachments and POST /api/v1/caregiver-notes/{id}/attachments: 503 or 500 where a virus scan that could not be queued, or an upload that could not be read, said 422 not_saved or file_required, and 500 internal_error where a refused audit record said 422 not_saved.
  • POST /api/v1/payroll-exports/{id}/generate: 503 or 500 where a store failure said a 500 that kept the Idempotency-Key, and 500 internal_error that frees it where a refused audit record failed the request. A refused generation leaves the export and its earlier file as they were.
  • GET /api/v1/exports/{id}: an export whose file the store did not answer for stays processing, its error_message saying it is retried automatically, until the last attempt marks it failed, saying to start a new export; one whose file the store refused is failed at once, where both used to read failed between attempts. A completed export's error_message is null.

A store answer is transient when it is an HTTP 408, 429, 500, 502, 503 or 504, S3's 400 RequestTimeout, or a transport or protocol error, and permanent otherwise (a 501 or 505 included). None of these changed anything. An answer that persisted nothing now leaves the Idempotency-Key free whatever its status (these, and a 500 for an audit record that could not be written), so a retry under the same key runs again instead of replaying the failure; a retry while the first request still runs is 409 idempotency_in_progress, as before. A slow file store answers within about 67 seconds. MCP tools say the same sentence. Changed October 8, 2026 (US-95.82): request body limits are stated in the pages' MB, 2^20 bytes, and KB, 2^10 bytes, so each rises slightly: any body takes 1 MB (1,048,576 bytes, was 1,000,000), a JSON-RPC body to /mcp 3,248,128 bytes (was 3,100,000), the CFC calculator tools a file of 1 MB (was 1,000,000 bytes), validate_claims_csv a sheet of 1 MB (1,048,576 bytes, was 1,000,000), and a signature image (POST /api/v1/work-orders/{id}/signatures, sign_work_order, the caregiver app's signatures) 50 KB (51,200 bytes, was 50,000). A voice recording to the in-app assistant takes the upload routes' 10 MB (10,485,760 bytes, was 8,000,000). A file sent base64 to an MCP tool fits the /mcp body up to 1.7 MB (1,887,435 bytes; the CFC calculator tools take 1 MB), and every tool that takes one says so, refuses a larger file, and names the REST route that takes it: create_batch and store_pcsp, which said 10 MB, refuse naming POST /api/v1/batches or POST /api/v1/clients/{id}/pcsp-documents, and add_client_note_attachment, add_caregiver_note_attachment and upload_company_document refuse naming their multipart routes. validate_claims_csv and POST /api/v1/clients/{id}/pcsp-documents state their limits, and POST /api/v1/company-documents states that a JSON body takes at most 1 MB. Every 413 for a body too large names the limit that refused it, by the route and the body's content type: a multipart body on a route that takes files names the file it may carry (a CFC calculator's, 5 MB), any other body the most its parser reads (1 MB, and 3 MB for JSON to /mcp, whose 413 points to the tool's description for where a larger file goes).

Added October 7, 2026 (US-95.30): the files on notes. GET /api/v1/client-notes/{id}/attachments and GET /api/v1/caregiver-notes/{id}/attachments list a note's attachments with their virus-scan status; POST /api/v1/client-notes/{id}/attachments and POST /api/v1/caregiver-notes/{id}/attachments attach a file (multipart field file, up to 10 MB; a file breaking the note page's rules is 422 naming the rule); GET /api/v1/note-attachments/{id} downloads one once its scan is clean (404 before); DELETE /api/v1/note-attachments/{id} removes one, for its uploader or an agency admin (404 for anyone else). MCP gains the matching tools, one per kind of note.

Added October 7, 2026 (US-95.32): OIG checks, PINs and the bulk compliance updates. GET /api/v1/caregivers/{id}/oig-checks and POST /api/v1/caregivers/{id}/oig-checks list and record a caregiver's OIG exclusion checks, and POST /api/v1/oig-checks/bulk records a clear check for every active caregiver (admin credentials only). POST /api/v1/caregivers/{id}/telephony-pin and POST /api/v1/telephony-pins/bulk generate telephony PINs, PUT /api/v1/caregivers/{id}/app-pin sets and DELETE /api/v1/caregivers/{id}/app-pin resets an app PIN; none of them returns a PIN (PRD 5.8). POST /api/v1/trainings/bulk-annual-completion (admin credentials only) and POST /api/v1/vaccinations/bulk make the compliance dashboard's bulk updates. MCP gains the matching tools.

Added October 7, 2026 (US-95.32): a caregiver's compliance record, pay rates and Employee File checklist. GET /api/v1/caregivers/{id}/compliance-items, POST /api/v1/caregivers/{id}/compliance-items (one per caregiver: 422 already_recorded naming it) and PATCH /api/v1/caregivers/{id}/compliance-items (409 stale_record) keep the compliance record and its custom items. GET /api/v1/caregivers/{id}/pay-rates and POST /api/v1/caregivers/{id}/pay-rates list and add pay rates, a new one ending the current rate of its type. GET /api/v1/caregivers/{id}/file-checklist, PATCH /api/v1/caregivers/{id}/file-checklist (several items, all or none; 422 hidden_item or unknown_item) and POST /api/v1/caregivers/{id}/file-checklist/review read, set and review the Employee File checklist. MCP gains the matching tools.

Added October 7, 2026 (US-95.36): the agency's own records. GET /api/v1/company-documents, GET /api/v1/company-documents/{id}, POST /api/v1/company-documents (multipart file, or file_base64 with file_name), PATCH /api/v1/company-documents/{id} and DELETE /api/v1/company-documents/{id} (each with the lock_version read: 400 without it, 409 stale_record when it changed since; 422 retained for an OIG attestation's report) and GET /api/v1/company-documents/{id}/file (once scanned clean; 409 scan_pending, 410 scan_infected). POST /api/v1/exports starts a report page's CSV export, GET /api/v1/exports/{id} reads its status and GET /api/v1/exports/{id}/file its file. GET /api/v1/import-configurations, GET /api/v1/import-configurations/{id}, POST /api/v1/import-configurations, PATCH /api/v1/import-configurations/{id} and DELETE /api/v1/import-configurations/{id} (each with the lock_version read: 400 without it, 409 stale_record when it changed since). GET /api/v1/saved-reports, POST /api/v1/saved-reports, PATCH /api/v1/saved-reports/{id} and DELETE /api/v1/saved-reports/{id}, by kind (client or caregiver); a saved report's filters are accepted and never returned. Eighteen MCP tools do the same.

Added October 7, 2026 (US-95.35): payroll writes. DELETE /api/v1/service-rates/{id}, POST /api/v1/service-rates/{id}/transition (close a rate and open its successor from effective_date) and POST /api/v1/service-rates/import (a CSV as csv or csv_base64, with preview to check it and write nothing) manage the agency's own rates, and PUT /api/v1/service-rates/schedule-source sets use_system_fee_schedule. POST /api/v1/cash-advances, POST /api/v1/cash-advances/{id}/repayments and POST /api/v1/cash-advances/{id}/write-off are Cash advances. POST /api/v1/payroll-exports starts an export for a pay period, POST /api/v1/payroll-exports/{id}/generate builds its ADP file (format adp or adp_run, with warnings), GET /api/v1/payroll-exports/{id}/file returns the CSV, and POST /api/v1/payroll-exports/{id}/mark-exported marks it sent. MCP's delete_service_rate, transition_service_rate, import_service_rates, set_fee_schedule_source, create_cash_advance, record_cash_advance_repayment, write_off_cash_advance, create_payroll_export, generate_payroll_csv, get_payroll_export_file and mark_payroll_export_exported do the same.

Added October 7, 2026 (US-95.33): provider care plans. GET /api/v1/provider-care-plans (client_id), POST /api/v1/provider-care-plans, GET /api/v1/provider-care-plans/{id} and PATCH /api/v1/provider-care-plans/{id} save and read a plan and its revisions, the certification period decided as the form decides it (422 certification_disagreement naming both periods unless certification_choice is sent). POST /api/v1/provider-care-plans/{id}/mark-current, POST /api/v1/provider-care-plans/{id}/reconciliation and POST /api/v1/clients/{id}/pcsp-documents (multipart file) mark a plan current, record a reconciliation and store a PCSP. POST /api/v1/provider-care-plans/{id}/reconciliation/preview proposes a PCSP's authorisations and answers a single-use token good for an hour, and POST /api/v1/provider-care-plans/{id}/reconciliation/apply applies exactly that preview with the caller's decisions (409 already_applied, expired). MCP gains the matching tools.

Added October 7, 2026 (US-95.31): the client page's actions. POST /api/v1/clients/{id}/calendar-events adds a custom event to a client's calendar and POST /api/v1/calendar-events/{id}/restore undoes a change to one (upcoming or overdue only). POST /api/v1/clients/{id}/next-action-snoozes and DELETE /api/v1/clients/{id}/next-action-snoozes snooze and bring back a Next Actions suggestion for the caller. GET /api/v1/clients/{id}/health-summary, POST /api/v1/clients/{id}/health-summary (422 no_conditions, 503 ai_unavailable), PATCH /api/v1/clients/{id}/health-summary (409 stale_record) and DELETE /api/v1/clients/{id}/health-summary read, write, edit and delete the AI health summary. GET /api/v1/clients/{id}/par-check and PATCH /api/v1/clients/{id}/par-check read and save the PAR unit check, all services or none (422 not_on_par for a service the PAR has no plan for). MCP gains the matching tools.

Added October 7, 2026 (US-95.31): client records. GET /api/v1/clients/{id}/certifications, POST /api/v1/clients/{id}/certifications, PATCH /api/v1/client-certifications/{id} and DELETE /api/v1/client-certifications/{id} keep a client's certification periods (an overlap answers 422). GET /api/v1/clients/{id}/satisfaction-surveys, POST /api/v1/clients/{id}/satisfaction-surveys, PATCH /api/v1/satisfaction-surveys/{id} (409 stale_record) and POST /api/v1/satisfaction-surveys/{id}/complete (every required question answered) keep its surveys. GET /api/v1/clients/{id}/emergency-info, POST /api/v1/clients/{id}/emergency-info and DELETE /api/v1/emergency-info/{id} keep its emergency information revisions, and PATCH /api/v1/clients/{id}/information-sheet writes the information sheet's fields (a blank SSN keeps it; the SSN is never returned). MCP gains the matching tools.

Added October 7, 2026 (US-95.33): a supervisory visit's lifecycle. POST /api/v1/supervisory-visits/{id}/complete completes it and schedules the next one (admin credentials only, 403 forbidden otherwise), POST /api/v1/supervisory-visits/{id}/reopen clears its signatures for correction (422 already_draft), POST /api/v1/supervisory-visits/{id}/date sets or clears its date, and POST /api/v1/supervisory-visits/{id}/signatures signs one line (supervisor, client, caregiver or pcp; 422 already_signed). A visit another request changed while one of these ran answers 409 stale_record (send it again), and a later completion step that failed (the next visit, the completing user's reminder cadence) 500 internal_error, nothing saved. MCP's complete_supervisory_visit, reopen_supervisory_visit, set_supervisory_visit_date and sign_supervisory_visit call the same functions.

Changed October 7, 2026 (US-95.52): an agency whose account is read-only may now make, over /api/v1, every write its MCP twin allows at that level (notes, incidents, complaints, trainings, support tickets, reminders and the like), as MCP and the web already let it; the level an operation allows is read from the MCP tool naming it. Batch writes and every write whose twin excludes the read-only level are still refused with 403 read_only, and a credential without hcb.write with 403 insufficient_scope.

Added October 7, 2026 (US-95.51): POST /api/v1/batches/from-timesheets bills the approved timesheets among timesheet_ids as one batch, as Billing > Generate batch does (201 with the batch, left_out naming every timesheet not in it and why, and warnings; 422 critical_issues when the selection breaks a rule that blocks a batch, 422 nothing_billable, 409 timesheets_already_exported or stale_record). MCP's create_batch_from_timesheets does the same.

Added October 7, 2026 (US-95.38): the Settings list tabs, admin credentials only (403 forbidden otherwise). Checklists: GET /api/v1/checklists/{checklist}/items, POST /api/v1/checklists/{checklist}/items, PATCH /api/v1/checklist-items/{id}, POST /api/v1/checklist-items/{id}/deactivate (422 last_active), POST /api/v1/checklist-items/{id}/reactivate and POST /api/v1/checklist-items/{id}/move. CFC programs: GET /api/v1/cfc-programs, PATCH /api/v1/cfc-programs/{category} (422 last_active_category), POST /api/v1/cfc-programs/{category}/tasks, PATCH /api/v1/cfc-tasks/{id}, POST /api/v1/cfc-tasks/{id}/deactivate (422 last_active_task), POST /api/v1/cfc-tasks/{id}/reactivate and POST /api/v1/cfc-tasks/{id}/move. Report templates: GET /api/v1/report-templates/{report_type}, POST /api/v1/report-templates/{report_type}/questions, PATCH /api/v1/report-questions/{id}, POST /api/v1/report-questions/{id}/deactivate, POST /api/v1/report-questions/{id}/reactivate, POST /api/v1/report-questions/{id}/move, POST /api/v1/report-questions/{id}/flag (sets a flag to the value sent), POST /api/v1/report-templates/{report_type}/apply-preset (422 unknown_preset) and PATCH /api/v1/report-templates/{report_type}/form; a change the page confirms first answers 409 confirmation_required unless confirm is true. A question's add and edit bodies are typed: options is an array of codes, option_labels an object of captions keyed by code (a code it names must be in the options, or be one the same write removes, whose caption goes with it), multiline a boolean and print_region top_list or table, which the supervisory sheet's own band questions do not take. A setting a question does not take is refused by name (422), and a null inside options or option_labels is refused. EVV rules: GET /api/v1/evv-rules, PATCH /api/v1/evv-rules/{id}, POST /api/v1/evv-rules/{id}/toggle and POST /api/v1/evv-rules/reset. Every audit row written during an /api/v1 or MCP request now names the API key or AI connection. MCP gains the matching tools.

Added October 7, 2026 (US-95.37): agency administration, admin credentials only (403 forbidden otherwise) except connected apps. GET /api/v1/users, PATCH /api/v1/users/{id} (name, role; 422 cannot_change_own_role, last_admin), DELETE /api/v1/users/{id} (deactivates and revokes the member's keys, connections and webhook endpoints; 422 cannot_deactivate_self) and POST /api/v1/users/{id}/reactivate. GET /api/v1/invitations, POST /api/v1/invitations (201; 422 already_member, pending_invitation) and DELETE /api/v1/invitations/{id} (422 not_pending). GET /api/v1/api-keys and GET /api/v1/webhook-endpoints list without secrets; GET /api/v1/webhook-endpoints/{id}/deliveries reads the delivery log and POST /api/v1/webhook-deliveries/{id}/resend sends one again (409 in_flight). POST /api/v1/api-keys, DELETE /api/v1/api-keys/{id}, POST /api/v1/webhook-endpoints, PATCH /api/v1/webhook-endpoints/{id} and DELETE /api/v1/webhook-endpoints/{id} answer 403 web_only: a credential is created or changed by an admin signed in to Settings. GET /api/v1/connected-apps and DELETE /api/v1/connected-apps/{id} list and revoke AI app connections as Connected apps does: an admin credential the agency's, a staff one its own member's. Another agency's record is 404. MCP's find_users, update_user, deactivate_user, reactivate_user, find_invitations, invite_user, revoke_invitation, find_api_keys, create_api_key, revoke_api_key, find_webhook_endpoints, create_webhook_endpoint, update_webhook_endpoint, delete_webhook_endpoint, find_webhook_deliveries, resend_webhook_delivery, find_connected_apps and revoke_connected_app call the same functions.

Added October 7, 2026 (US-95.39): the pipeline, caregiver broadcasts and notifications, open to every credential. GET /api/v1/prospects, POST /api/v1/prospects, GET /api/v1/prospects/{id}, PATCH /api/v1/prospects/{id} (409 stale_record) and DELETE /api/v1/prospects/{id} (422 cannot_delete_converted) keep the pipeline, and POST /api/v1/prospects/{id}/convert makes the client or caregiver (422 invalid_status_for_conversion unless at onboarding). POST /api/v1/broadcasts sends a message to active caregivers by email, SMS or both, to all or a compliance group, skipping and counting those without the contact method or opted out of SMS (422 no_recipients, 409 duplicate, 429 rate_limited). GET /api/v1/notifications lists the credential's member's notifications (read=read|unread); POST /api/v1/notifications/{id}/read, POST /api/v1/notifications/read-all and POST /api/v1/notifications/{id}/resolve act on them. Another agency's record, or another member's notification, is 404. MCP's find_prospects, get_prospect, create_prospect, update_prospect, delete_prospect, convert_prospect, send_broadcast, list_notifications, mark_notification_read, mark_all_notifications_read and resolve_notification call the same functions.

Added October 7, 2026 (US-95.34): batch and claim writes. POST /api/v1/batches now takes column_mapping and save_mapping (keep the mapping the file was read with as the agency's saved one). DELETE /api/v1/batches/{id} deletes a batch not yet sent (422 already_submitted, submission_in_progress, not_eligible), returning its timesheets to approved. PATCH /api/v1/claims/{id} corrects an uploaded claim and POST /api/v1/claims/{id}/replacement creates a replacement claim in its own batch, each with a reason and for admin credentials only (403 forbidden). POST /api/v1/claims/{id}/reconcile, POST /api/v1/claims/{id}/unreconcile and POST /api/v1/checks/{number}/reconcile are the payment report's reconciliation, and PATCH /api/v1/claims/{id}/investigation sets a denial's investigation_status and resolution_notes. A Claim now carries reconciled_at, investigation_status and resolution_notes. MCP's create_batch, delete_batch, update_claim, create_replacement_claim, reconcile_claim, unreconcile_claim, reconcile_check and update_claim_investigation do the same.

Added October 7, 2026 (US-95.28): timesheet writes. POST /api/v1/assignments/{id}/timesheets creates a month's timesheet from an assignment (201; 409 work_order_timesheet_exists, 422 period_outside_assignment). POST /api/v1/timesheets/{id}/entries, PATCH /api/v1/timesheet-entries/{id}, POST /api/v1/timesheets/{id}/tasks and PATCH /api/v1/timesheet-tasks/{id} edit a draft's entries and tasks (422 not_editable once it is not a draft). POST /api/v1/timesheets/{id}/submit (422 signatures_required unless acknowledge_missing_signatures), POST /api/v1/timesheets/{id}/approve (with warnings for stored hours that differ from the entries), POST /api/v1/timesheets/{id}/reject (a reason), POST /api/v1/timesheets/{id}/reopen (422 no_release unless a denied claim sent it back) and POST /api/v1/timesheets/{id}/signatures run the returned timesheet's workflow. DELETE /api/v1/timesheets/{id} deletes a draft (422 not_draft otherwise), and GET /api/v1/timesheets/{id}/billing-data returns the claim lines an approved timesheet bills, writing nothing (422 billing_refusal). A timesheet changed since it was read is 409 stale_record. MCP's create_timesheet, add_timesheet_entry, update_timesheet_entry, add_timesheet_task, update_timesheet_task, submit_timesheet, approve_timesheet, reject_timesheet, reopen_timesheet, sign_timesheet, delete_timesheet and generate_billing_data do the same.

Added October 7, 2026 (US-95.29): DELETE /api/v1/clients/{id} and DELETE /api/v1/caregivers/{id} (the lock_version read, in the query) soft-delete as the web's lists do; POST /api/v1/clients/{id}/restore and POST /api/v1/caregivers/{id}/restore (the lock_version read, in the body) restore them; a DELETE's answer carries the lock_version the record was left at, the one its restore takes, and a second restore of the same read is 409 stale_record. A deleted client or caregiver leaves the default list and is listed with include_deleted=true. A restored caregiver's response carries meta.pin_resolution and, when a new telephony PIN was issued, meta.new_pin, in that response only. DELETE /api/v1/client-notes/{id} and DELETE /api/v1/caregiver-notes/{id} soft-delete a note and its attachments. DELETE /api/v1/supervisory-visits/{id} deletes a draft for any key and a finalized visit for an admin key only (422 not_draft otherwise), and DELETE /api/v1/satisfaction-surveys/{id} deletes a survey, answering its id and deleted_at. DELETE /api/v1/trainings/{id} and DELETE /api/v1/evaluations/{id} delete a caregiver's training record or evaluation, as the caregiver's tabs do. Refusals are 422 already_deleted, not_deleted, has_active_references and has_active_assignments. MCP gains the matching delete and restore tools.

Added October 7, 2026 (US-94.24): POST /api/v1/visits/bulk-verify and POST /api/v1/visits/bulk-cancel move up to 100 of the agency's visits, each on its own, as the visit list's bulk actions do; the answer lists succeeded_ids and each visit failed with its reason (not_found, invalid_transition, exception_not_dismissed, error). POST /api/v1/visit-exceptions/{id}/assignment assigns an exception to a user of the agency, or unassigns it with assigned_to_id null (422 assignee_not_found for anyone else). A visit exception gains assigned_to_id. MCP gains create_visit, bulk_verify_visits, bulk_cancel_visits, bulk_resolve_visit_exceptions and assign_visit_exception on the same operations.

Added October 6, 2026 (US-95.26): a Work Order's content. GET /api/v1/work-orders/{id}/plan reads the weekly plan in force today (each weekday's visits, each task line with its minutes and per-weekday counts, and its lock_version), and PATCH /api/v1/work-orders/{id}/plan writes weekdays, lines and drop_lines into it as the Work Order page saves its grid (409 stale_record for a plan changed since, unless it already holds what is sent; 422 unknown_task_definition). PUT /api/v1/work-orders/{id}/days/{date} marks a date worked or not (422 recorded_work without confirm, 422 frozen). PUT /api/v1/work-orders/{id}/tasks/{task_definition_id}/days/{date} marks a task done, not done or untouched, and POST /api/v1/work-orders/{id}/unplanned-tasks records a task the plan did not hold. PATCH /api/v1/provider-type-templates/{id}/certification saves a provider type's certification with the certification_version read (admin only; 409 stale_record; 422 not_agency_template). GET /api/v1/provider-type-modifiers now also returns each provider type's id, agency_owned and certification. MCP's get_work_order_plan, update_work_order_plan, set_work_order_day, toggle_work_order_task, add_unplanned_task and update_provider_type_certification do the same.

Added October 6, 2026 (US-95.14): supervisory visits and monthly client reports. GET /api/v1/supervisory-visits lists the agency's visits (filtered by status, client_id, caregiver_id and visit_date_from / visit_date_to) and GET /api/v1/supervisory-visits/{id} returns one, each with its checklist questions and answers and never a signature or print-form field; POST /api/v1/supervisory-visits records a draft conducted by the API key's user (a telehealth visit needs an agency admin and the agency's acknowledgment, else 422 visit_type_not_allowed); PATCH /api/v1/supervisory-visits/{id} edits a draft with its lock_version (422 not_editable for a completed or signed visit, or a draft already carrying a signature); GET /api/v1/supervisory-visits/due lists the clients a visit is due for. GET /api/v1/monthly-client-reports lists a client's reports (client_id required) and POST /api/v1/work-orders/{id}/monthly-report saves the one report a Work Order month holds: 201 when it creates it, 200 when it updates it, 422 client_signed once the client has signed. Another agency's visit, client or Work Order is 404.

Added October 6, 2026 (US-95.17): compliance reads and the OIG roster screen, each returning what its MCP tool returns. GET /api/v1/caregivers/{id}/compliance returns a caregiver's training, vaccinations, evaluation and credential dates; GET /api/v1/clients/{id}/file-completeness and GET /api/v1/caregivers/{id}/file-completeness return a person's file items; GET /api/v1/audit-readiness returns the summary's counts and a page of the people with a gap; GET /api/v1/compliance-alerts lists the active caregivers with one kind of problem (alert_type required, 400 otherwise); GET /api/v1/oig-screens lists the agency's OIG screens with their still-open review counts (include_single adds new-hire and single-caregiver screens); POST /api/v1/oig-screens queues a roster screen and answers 202 with status queued or already_queued (422 demo_agency for a demo agency); GET /api/v1/oig-screening-status lists each caregiver's latest OIG check. Another agency's client or caregiver is 404.

Added October 6, 2026 (US-95.18): support tickets, today's agenda and its reminders. POST /api/v1/support-tickets opens a support ticket (subject, description of at least 20 characters, category and priority, all required); a screenshot or any other field in the body is ignored, never stored. A missing, over-long or unknown value is 422 naming the field (field_required, field_not_text, field_too_long, invalid_choice, description_too_short), and past the in-app assistant's shared ceiling the answer is 429 support_ticket_limit. GET /api/v1/support-tickets lists, in the page envelope and newest first, the tickets the API key's user raised, filtered by status and priority, and GET /api/v1/support-tickets/{id} returns one of them, each with its reference, status, priority, category, SLA status and resolution notes, never its description; a ticket another member raised, or another agency's, is 404. GET /api/v1/agenda/today returns the reminders due today and those overdue (each capped, with total, truncated, limit and its own offset, due_today_offset and overdue_offset), today's client birthdays and the billing work waiting, for Mountain time's day unless date names another. POST /api/v1/reminders/{id}/complete and POST /api/v1/reminders/{id}/dismiss close one reminder as the Today page's Done and Dismiss buttons do (completing a recurring one schedules its next, dismissing ends the series); one already closed as asked answers 200 with changed: false, one closed the other way is 422 already_closed, and another agency's reminder is 404 and nothing changes. MCP's create_support_ticket, list_support_tickets, check_ticket_status, whats_due_today and complete_reminder do the same.

Added October 6, 2026 (US-95.20): POST /api/v1/service-rates creates one of the agency's own service rates (procedure_code, modifiers, rate_per_unit, effective_date, description), and PATCH /api/v1/service-rates/{id} changes its rate_per_unit, effective_date or description. A service rate carries no lock_version, so a PATCH takes none. A platform-wide rate is never written: its id answers 404. A duplicate code, modifiers and effective date, or a rate_per_unit not greater than 0, answers 422 naming the field. MCP's create_service_rate and update_service_rate do the same.

Added October 6, 2026 (US-95.16): a caregiver's training, vaccinations and evaluations. GET /api/v1/caregivers/{id}/trainings, GET /api/v1/caregivers/{id}/vaccinations and GET /api/v1/caregivers/{id}/evaluations list the caregiver's records in the shape MCP's caregiver-record tools return (notes are written, never returned). POST /api/v1/caregivers/{id}/trainings and POST /api/v1/caregivers/{id}/evaluations record one (422 already_recorded with the existing record's id in details.training_id or details.evaluation_id), and PATCH /api/v1/trainings/{id} and PATCH /api/v1/evaluations/{id} change one (422 nothing_to_change for an empty body; these records carry no lock_version). POST /api/v1/caregivers/{id}/vaccinations records the vaccination for a year and type, 201 when none was recorded (422 status_required without a status) and 200 when it updates the one recorded; a vaccination has no PATCH. Another agency's caregiver or record is 404 and nothing is written.

Added October 6, 2026 (US-95.15): critical incidents and complaints. GET /api/v1/critical-incidents lists the agency's incidents (filtered by status, incident_type, client_id and date_from / date_to) and GET /api/v1/critical-incidents/{id} returns one, its reports, notifications and referrals in the nested shape MCP's incident tools use; POST /api/v1/critical-incidents reports a draft (reported by the API key's user) and PATCH /api/v1/critical-incidents/{id} changes the fields sent with its lock_version, reports and notifications merged over the stored legs (422 invalid_field for a malformed leg). GET /api/v1/complaints lists the agency's complaints (filtered by status, client_id, caregiver_id and date_from / date_to), GET /api/v1/complaints/{id} returns one with its answers by question key, POST /api/v1/complaints logs one at intake (422 unknown_answer_keys or invalid_answers for answers its questions cannot take) and PATCH /api/v1/complaints/{id} changes it with its lock_version. On either resource a status move the record's transitions refuse is 422 invalid_transition, an empty change is 422 nothing_to_change, and another agency's record, client or caregiver is 404. Neither resource has a delete.

Added October 6, 2026 (US-95.13): the communication log. GET /api/v1/clients/{id}/notes and GET /api/v1/caregivers/{id}/notes list a client's or caregiver's notes in the page envelope, newest first, filtered by contact_type and synced with updated_since; POST /api/v1/clients/{id}/notes and POST /api/v1/caregivers/{id}/notes file a note (manager_initials defaults to the API key's user's initials); PATCH /api/v1/client-notes/{id} and PATCH /api/v1/caregiver-notes/{id} change the fields sent (a body that changes nothing is 422 nothing_to_change; notes carry no lock_version). A person of another agency, or a deleted one, is 404. Attachments are neither returned nor accepted; attachment_count says how many there are. Over-long initials or employee names are 422 (initials_too_long, employee_names_too_long, employee_name_too_long), never cut.

Added October 6, 2026 (US-95.27): Work Order generation and the templates behind it. POST /api/v1/assignments/{id}/work-orders/generate lays out a month's Work Order from the client's Plan of Care (201 with the Work Order and warnings; 409 work_order_exists unless overwrite is true; 422 no_schedule). POST /api/v1/plans-of-care/{id}/work-orders/distribute splits a plan across caregivers with per-caregiver frequencies (201 with the Work Orders and coded warnings; 409 plan_changed for a plan task id the plan no longer carries). POST /api/v1/plans-of-care/{id}/resolve-over-authorization trims the month's Work Orders back to the authorization (200 with each change; 422 residual_over_authorization when a chosen target cannot absorb it). POST /api/v1/work-orders/{id}/timesheet writes a completed Work Order's caregiver report (201; 422 work_order_not_ready or hours_not_verified; 409 timesheet_exists). GET /api/v1/task-set-templates, POST /api/v1/task-set-templates, GET /api/v1/task-set-templates/{id}, PATCH /api/v1/task-set-templates/{id} (with lock_version) and DELETE /api/v1/task-set-templates/{id} list, get, create, change and delete task set templates, and GET /api/v1/provider-type-modifiers and PUT /api/v1/provider-type-modifiers/{code} read and set a provider type's modifiers against the set read (expected_modifiers; 409 stale_modifiers). Template and modifier writes are an admin's (403 forbidden). MCP's generate_work_orders, distribute_plan_work_orders, resolve_over_authorization, generate_timesheet, find_task_set_templates, get_task_set_template, create_task_set_template, update_task_set_template, delete_task_set_template, find_provider_type_modifiers and set_provider_type_modifiers do the same.

Added October 6, 2026 (US-95.22): a client's CFC calculator, as a job. POST /api/v1/clients/{id}/cfc-calculator starts an import of a CFC Direct Care Services Calculator (.xlsx, .pdf, .png, .jpg or .jpeg, multipart field file, at most 5 MB, optional task_names) into the client's Plans of Care, one per service on the sheet; POST /api/v1/clients/{id}/cfc-calculator/preview starts a preview of the per-day minutes an import would write. Each answers 202 with the job at once, since reading a scan can take minutes; GET /api/v1/cfc-imports/{id} reads it until it has ended, succeeded with its rows or plans and warnings, or failed with its error (unreadable_calculator, import_refused, extraction_unavailable once the extraction service has not answered through every retry). A file over 5 MB answers 422 file_too_large, and a body over the upload cap 413, both naming max_file_size; any task_names but a list of names 422 invalid_task_names.

Added October 5, 2026 (#2216): a visit exception's sandata_ack_status gains sending, an acknowledgement claimed for a send that has not been answered yet. It is not withdrawable, as submitted is not; a send that never finished is retried after 15 minutes.

Added October 5, 2026 (US-98.29): DELETE /api/v1/visits/{id}/sandata-exceptions withdraws a wrong code recorded as raised by Sandata while its acknowledgement has not been sent (200 with the exception, now status withdrawn; 422 already_sent once it has gone; 404 when the visit has no code recorded), after which the right code can be recorded. A visit exception's status gains withdrawn. MCP's withdraw_sandata_exception does the same.

Changed October 5, 2026 (US-98.37): a visit time written without its UTC offset (scheduled_start_time, scheduled_end_time, adjusted_start_time, adjusted_end_time on POST or PATCH /api/v1/visits) is refused with 422 time_offset_required instead of being read as UTC; a value that is not a time answers 422 invalid_time. MCP gains update_visit, with PATCH's rules: a null clears a nullable field and is refused (null_not_allowed) on any other, for every MCP update tool, and the answer carries the same warnings.

Added October 5, 2026 (US-98.33): POST /api/v1/visits/{id}/reassign hands a visit to another caregiver (caregiver_id, lock_version), answering the visit and its warnings (calls_superseded, caregiver_not_active, overlapping_visit, months_unfrozen); MCP's reassign_visit does the same. A deleted caregiver is 422 caregiver_not_found, and a visit deleted meanwhile is 404. A visit's calls carry superseded_at, set on the earlier caregiver's calls by a reassignment: they stay as history and no longer count as the visit's clock.

Added October 5, 2026 (US-98.36): PATCH /api/v1/me/pin changes the caregiver's PIN (current_pin, new_pin). A wrong current_pin is 422 invalid_current_pin and counts as a failed sign-in (429 rate_limited once the limit is reached); a new PIN that is not six digits, or is repeated or sequential, is 422 validation_failed naming new_pin. On success (204) the asking device stays signed in and every other device and web app session of the caregiver is signed out.

Added October 5, 2026 (US-98.40): POST /api/v1/work-orders/{id}/fill-from-evv fills an in-progress Work Order's days from the caregiver's EVV visits for its client, as the page's Fill times from EVV does, and answers the days filled, updated, unchanged, differing (typed by hand, kept) and flagged; a split shift fills one entry per visit, a visit fills only the one live Work Order of its month that serves it (one several could take is flagged), and a fill that writes moves the Work Order's lock_version. MCP's fill_work_order_from_evv does the same.

Added October 5, 2026 (US-98.32): DELETE /api/v1/visits/{id} answers meta.links, what rested on the visit and stays, read under the delete's lock: timesheet_entries whose EVV times were pulled from it, each with the work_order_number its timesheet names (the first 50, with timesheet_entries_total), and unfrozen_months, the Work Order months its signature alone froze, each with its work_order_number. MCP's delete_visit answers the same as links.

Added October 5, 2026 (US-98.17): an unmatched call carries chosen_visit_id, the visit the caregiver chose in the phone menu when that visit refused the call, and reason gains visit_closed, visit_reassigned, visit_already_clocked, no_clock_in and not_recorded for those calls.

Added October 5, 2026 (US-98.6): POST /api/v1/me/push-tokens registers the caregiver app's APNs (platform ios) or FCM (platform android) token for the signed-in device (201 the first time, 200 when it registers again or replaces the token), and DELETE /api/v1/me/push-tokens/current stops push to it; signing out does too. Reminders and alerts are queued to the app's devices beside the caregiver web app's Web Push; delivery through APNs and FCM starts once those are configured.

Added October 5, 2026 (US-98.12): the caregiver app's profile and inbox. GET /api/v1/me also returns the caregiver's phone, email and unread_notifications (as does sign-in's caregiver). GET /api/v1/me/devices lists the devices the caregiver is signed in on (current marks the one asking) and DELETE /api/v1/me/devices/{id} signs one out. GET /api/v1/me/notifications (filter by type, dismissed=true to include dismissed ones), POST /api/v1/me/notifications/{id}/read, POST /api/v1/me/notifications/{id}/dismiss and POST /api/v1/me/notifications/read-all (answering data.marked) work the caregiver's notifications; a dismissal keeps its first time when repeated. Another caregiver's device or notification is 404.

Added October 4, 2026 (US-98.8): POST /api/v1/visits schedules a visit (source api), PATCH /api/v1/visits/{id} corrects its scheduled and adjusted times and EVV attributes with the lock_version it was read with, and POST /api/v1/visits/{id}/transitions moves its status (verify, cancel, reopen and the rest), answering 422 invalid_transition with the statuses it can move to. An adjusted-time change records Colorado's reason_code and reason_memo; without a reason it is saved as OTHER. Create and update answer {data, warnings}: reason_code_missing and overlapping_visit are warnings, never refusals, as are group_identifier_dropped, assignment_not_open (an assignment the office ended), long_window (over 24 hours) and service_date_moved. A client, caregiver or assignment from another agency (or an assignment for another pair) is 422 naming the field, as is a scheduled window over 31 days. A visit's service date is its scheduled start's day in Mountain time, set from the times rather than sent, and it moves with the start; visit_type changes only while the visit is not queued for or sent to Sandata, and only a group visit keeps a group_identifier.

Added October 4, 2026 (US-98.20): DELETE /api/v1/visits/{id}, with the lock_version the visit was read with, deletes a visit as the web does: its open exceptions are dismissed and their Sandata acknowledgements queued, and a visit Sandata holds is queued to go to Sandata as cancelled. A visit changed since it was read answers 409 stale_record; a deleted or unknown one answers 404.

Changed October 4, 2026 (US-98.20): a deleted visit's exceptions are dismissed with it. GET /api/v1/visit-exceptions still lists them, now with status dismissed, resolution code other and the note "The visit was deleted."; the response shape is unchanged.

Added October 3, 2026 (US-74.1): POST /api/v1/clients/{id}/acp-protection marks a client in Colorado's Address Confidentiality Program, whose address and call locations are then withheld from Sandata, or removes the mark with a reason; a client carries acp_protected.

Added October 4, 2026 (US-98.5): POST /api/v1/me/visits/{id}/signatures keeps the client's or the caregiver's signature on one of the caregiver's visits (one per signer; replace: true replaces it), and GET /api/v1/me/visits/{id}/signatures/{signature_id}/image reads it back as an uncached PNG.

Added October 4, 2026 (US-98.10): GET /api/v1/unmatched-calls lists the telephony clock calls that matched no visit (filters status and call_date_from / call_date_to; the calling number masked to its last four), and POST /api/v1/unmatched-calls/{id}/match, POST /api/v1/unmatched-calls/{id}/dismiss and POST /api/v1/unmatched-calls/{id}/undo-dismiss resolve them as the unmatched-calls screen does.

Added October 4, 2026 (US-98.4): POST /api/v1/me/clock-events takes up to 100 clocks the caregiver app recorded offline, each recorded at its captured_at and judged on its own; it answers which synced and which failed.

Added October 4, 2026 (US-98.34): GET /api/v1/refused-clocks lists the clocks a closed visit refused and the server kept for the office, and POST /api/v1/refused-clocks/{id}/review marks one reviewed; GET /api/v1/me/refused-clocks gives the caregiver app the signed-in caregiver's own of the last 30 days.

Added October 2, 2026 (US-98.22): POST /api/v1/visits/{id}/sandata-exceptions records the ACK exception Sandata raised on a visit it took (15 Unmatched Client ID / Phone or 21 No Show Exception) as a sandata_raised visit exception and queues its acknowledgement to Sandata; one per visit.

Added October 2, 2026 (US-95.25): the Work Order lifecycle. POST /api/v1/work-orders/{id}/archive, POST /api/v1/work-orders/{id}/unarchive, POST /api/v1/work-orders/{id}/reopen, POST /api/v1/work-orders/{id}/signatures, POST /api/v1/work-orders/{id}/paper-signatures, POST /api/v1/work-orders/{id}/transition and POST /api/v1/work-orders/{id}/dismiss-warnings change a Work Order read at the lock_version sent (409 for one changed since); POST /api/v1/work-orders/{id}/duplicate copies it into the next month or the month sent; POST /api/v1/work-orders/{id}/close-document snapshots a completed one, close notes left out; and POST /api/v1/work-orders/{id}/dismiss-guidance clears the page's Getting Started notice. A status change to completed answers the caregiver report it wrote or found in timesheet; an unarchive, reopen or duplicate whose slot a live Work Order holds answers 409 slot_taken with its WO #. A Work Order now reads with its four signature dates, paper_signatures_collected and paper_signatures_collected_at.

Added October 2, 2026 (US-95.24): an assignment's status and weekly schedule. POST /api/v1/assignments/{id}/transition changes an assignment's status, with an optional reason the status history keeps and the lock_version it was read with. GET /api/v1/assignments/{id}/schedule reads its shifts and their days, and PUT /api/v1/assignments/{id}/schedule replaces one shift's days, the shift named by shift_number in the body or ?shift=, with the lock_version the assignment was read with; a save moves it and answers the new one beside the shifts. A refused day answers 422 invalid_schedule naming it. A transition's reason is at most 1000 characters.

Added October 2, 2026 (US-95.23): the PAR lifecycle. POST /api/v1/authorizations/{id}/transition changes a PAR's status and DELETE /api/v1/authorizations/{id} deletes one that is not active; both take the lock_version the PAR was read with (in the body, and in the query string for the delete) and answer 409 for a PAR changed since. POST /api/v1/authorizations/{id}/recertifications starts its renewal, POST /api/v1/recertifications/{id}/in-progress and POST /api/v1/recertifications/{id}/complete move it on, and GET /api/v1/recertifications lists the open ones of PARs still on file. A PAR has one open recertification at a time, and completing one creates the renewing PAR from the fields sent, as the web's renewal form does. POST /api/v1/eligibility-checks records a client's eligibility for a month and POST /api/v1/clients/{id}/eligibility-verified marks it verified; clients now carry eligibility_verified_at.

Added October 2, 2026 (US-95.21): Plans of Care. GET /api/v1/plans-of-care and GET /api/v1/plans-of-care/{id} return a client's plans with their tasks; POST /api/v1/plans-of-care creates one with its tasks (the client's current plan for that service becomes past) and PATCH /api/v1/plans-of-care/{id} changes one, replacing its tasks when a list is sent. A lowered task is saved with an over_authorized warning in warnings. Plans have no lock_version (the last save wins, as on the web) and no delete.

Added October 2, 2026 (US-95.19): the agency profile. GET /api/v1/agency returns the agency's name, address, phone and fax, NPI, Tax ID and claim defaults (rendering provider id, diagnosis code, place of service, week start day). PATCH /api/v1/agency sets the fields it sends; admin credentials only. The claim defaults and the week start can be changed but not cleared.

Added October 2, 2026 (US-94.20, US-94.23): GET /api/v1/claims takes member (a Medicaid ID or patient name, at most 64 characters); GET /api/v1/authorizations takes service_code, in any letter case; POST /api/v1/batches/validate takes an optional column_mapping, as a JSON part or column_mapping[field] form fields, applied over the saved mapping for that check only.

Added October 1, 2026 (Epic 98): the caregiver app. A caregiver signs in with POST /api/v1/caregiver-sessions (agency code, employee id, PIN) and gets a device token, sent as a bearer token on /api/v1/me routes only: GET /api/v1/me, and DELETE /api/v1/caregiver-sessions/current to sign out. An agency API key is refused there, and a device token everywhere else.

Added October 1, 2026 (Epic 98): EVV visits. GET /api/v1/visits and GET /api/v1/visits/{id}; one visit also carries the newest 200 of its clock calls, its changes with reason codes and who signed (never the image).

Added October 1, 2026 (US-98.2): the caregiver's own schedule. GET /api/v1/me/visits lists the signed-in caregiver's visits from date_from to date_to (today by default, at most 31 days, starting no more than 90 days back), not cancelled, with each client's name, address and geofence and never a Medicaid id. GET /api/v1/me/visits/{id} is one of them with its clock-in and clock-out; another caregiver's visit is 404, and a cancelled or deleted one is returned with its status and deleted_at.

Added October 1, 2026 (US-98.3): clocking in and out from the caregiver app. POST /api/v1/me/visits/{id}/clock-in and POST /api/v1/me/visits/{id}/clock-out record the call with the device's location and the device token's device id, and answer with the warnings it was recorded with; whatever the device sends is recorded, never refused, and a captured_at that is not a time, is ahead of now, or is before the visit existed is recorded at the server's time; one sent more than 5 minutes after the time it carries is recorded at that time with late_sync. A repeat answers 200 with the first call. A visit that is not scheduled or in progress takes no clock: 422 visit_not_clockable, nothing recorded.

Added October 1, 2026 (US-98.9): visit exceptions. GET /api/v1/visit-exceptions (filterable by status, exception_type, severity, visit, client, caregiver and detected date, and syncable) and GET /api/v1/visit-exceptions/{id}, each with the Colorado reason code its Sandata acknowledgement carries; POST /api/v1/visit-exceptions/{id}/resolve to acknowledge, correct or dismiss one, POST /api/v1/visit-exceptions/resolve for up to 100 at once, and GET /api/v1/visit-exceptions/reason-codes.

Authentication is an agency API key, sent as a bearer token. Every list is paginated and every error uses one envelope. A POST made with an API key takes an Idempotency-Key header (except POST /api/v1/batches/validate, which stores nothing). A PATCH takes no Idempotency-Key; it sets only the fields it sends.

The API is described by an OpenAPI 3 document, which needs no credential.

Operations, by resource:

  • Clients: GET /api/v1/clients, POST /api/v1/clients, GET /api/v1/clients/{id}, PATCH /api/v1/clients/{id}
  • Caregivers: GET /api/v1/caregivers, POST /api/v1/caregivers, GET /api/v1/caregivers/{id}, PATCH /api/v1/caregivers/{id}
  • Assignments: GET /api/v1/assignments, POST /api/v1/assignments, GET /api/v1/assignments/{id}, PATCH /api/v1/assignments/{id}
  • Service authorizations: GET /api/v1/authorizations, POST /api/v1/authorizations, GET /api/v1/authorizations/{id}, PATCH /api/v1/authorizations/{id}
  • Batches: GET /api/v1/batches, POST /api/v1/batches (upload a claims file), GET /api/v1/batches/{id}, POST /api/v1/batches/validate (check a file without storing it), and POST /api/v1/batches/{id}/submit (send a batch to HCPF)
  • Claims: GET /api/v1/claims, GET /api/v1/claims/{id}
  • Work orders: GET /api/v1/work-orders, POST /api/v1/work-orders, GET /api/v1/work-orders/{id}, PATCH /api/v1/work-orders/{id}
  • Timesheets: GET /api/v1/timesheets, GET /api/v1/timesheets/{id}
  • Service rates: GET /api/v1/service-rates, GET /api/v1/service-rates/{id}
  • Billing codes: GET /api/v1/billing-codes
  • Responses from the payer: GET /api/v1/responses, GET /api/v1/responses/{id}
  • Remittances: GET /api/v1/remittances, GET /api/v1/remittances/{id}
  • The OpenAPI document: GET /api/v1/openapi.json

Webhook event types, registered by an agency admin in Settings:

  • batch.accepted
  • batch.rejected
  • remittance.posted
  • claim.denied