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: code on PUT /api/v1/settings/security, sunset April 30, 2027; emergency_contact_name and emergency_contact_phone on the Client, and the MCP create_client tool's responsible_party, sunset 2027-05-31.

Added November 9, 2026 (US-122.5, open shifts):

  • GET /api/v1/service-areas, POST /api/v1/service-areas, PATCH /api/v1/service-areas/{id} and POST /api/v1/service-areas/import-starter: the agency's service areas, the starter set added once (agency_settings.manage to change; open_shifts.view to list).
  • GET /api/v1/open-shifts, GET /api/v1/open-shifts/{id}, POST /api/v1/open-shifts, PATCH /api/v1/open-shifts/{id} and POST /api/v1/open-shifts/{id}/cancel: post, read, change and cancel a shift that needs a caregiver (open_shifts.manage; open_shifts.view to read). A shift names cross streets, a ZIP and a service area, never the client's address or point. A note that names the client answers 422 client_info_found until the request repeats with acknowledged holding the finding's fingerprint. New refusals: 409 open_shifts_off, open_shift_closed, open_shift_assigned and slot_already_posted (with open_shift_id), and 422 no_shift_plan, not_a_run_day and client_info_found.
  • POST /api/v1/open-shifts/cross-streets: the cross streets nearest a client's stored point, or 422 cross_streets_not_found. Stores nothing.

The MCP tools list_service_areas, create_service_area, update_service_area, import_starter_service_areas, list_open_shifts, get_open_shift, create_open_shift, update_open_shift, cancel_open_shift and suggest_open_shift_cross_streets answer the same.

Added November 9, 2026 (US-122.11, who responded to an open shift):

  • GET /api/v1/open-shifts/{id}/responses (getOpenShiftsByIdResponses): the shift's live responses, active caregivers first, then nearest to the shift's service area, then by when they responded; limit (default 50, at most 100) and offset. Needs open_shifts.manage: a view-only credential answers 403. home_area is answered only to a holder of open_shifts.administer.
  • GET /api/v1/open-shifts and the MCP tool list_open_shifts take filter=with_responses (at least one live response) and filter=no_responses.

The MCP tool list_open_shift_responses answers the same as getOpenShiftsByIdResponses.

Added November 9, 2026 (US-122.12, assign an open shift):

  • POST /api/v1/open-shifts/{id}/assign (postOpenShiftsByIdAssign) with {"caregiver_id"}: the caregiver takes the shift, and an ongoing shift's caregiver is also picked on the client's Shift Plan slot. Answers 200 with data.open_shift, data.notes (who takes the slot from the next Generate, who keeps the current Work Order) and data.shift_plan_path. A schedule clash, a posted rate that differs from the caregiver's pay rate and a start that has passed are warnings (open_shifts.schedule_clash, open_shifts.rate_differs, open_shifts.start_passed); none refuses. Needs open_shifts.manage. A caregiver who did not respond is accepted while the agency's api_may_assign_non_responder is on. New refusals: 422 not_a_responder and caregiver_not_active; 409 open_shift_assigned, open_shift_closed and 422 no_shift_plan as on create.

The MCP tool assign_open_shift answers the same as postOpenShiftsByIdAssign.

Added November 9, 2026 (US-122.14, remove an assignment):

  • POST /api/v1/open-shifts/{id}/unassign (postOpenShiftsByIdUnassign): the shift goes back to open and what the assign made is undone. A one-time shift's scheduled Visit is cancelled and its cover Assignment closed; a Visit already in progress or completed is left and answered as a open_shifts.needs_attention warning. An ongoing shift whose start has not passed has its Shift Plan pick cleared and the standing Work Order the assign generated archived; after its start the pick stays, with the same warning. Answers 200 with data.open_shift. Needs open_shifts.manage. New refusal: 409 open_shift_not_assigned. Cancelling an assigned shift now undoes the assignment the same way.

The MCP tool unassign_open_shift answers the same as postOpenShiftsByIdUnassign.

Added November 10, 2026 (US-122.26, whether a caregiver can be texted):

  • A Caregiver gains read-only text_status and text_status_detail: the first that holds of no_cell_phone, opted_out (they replied STOP; the detail is that day), no_consent, not_verified and phone_changed (open-shift texts only, while the agency has open shifts on), last_text_failed (the newest open-shift text failed; the detail is the provider's reason), else can_text. Sent in a write, both are ignored.
  • GET /api/v1/caregivers takes text_status: one of those values, or cannot_text for every value but can_text.

The MCP tool find_caregiver takes the same text_status filter and its rows carry both fields.

Added November 10, 2026 (US-122.24, onboarding complete):

  • PATCH /api/v1/caregivers/{id} and the MCP tools update_caregiver and update_caregiver_status: a move from potential to active now answers two warnings, never a refusal. workforce.onboarding_open_items names the employee file items still open; workforce.no_employee_id says the caregiver cannot sign in with a PIN until an employee ID is set. Both are computed on every such save and cannot be dismissed. The move queues one OIG rescreen job, as it did before. The response shape is unchanged: the warnings arrive in warnings.

Added November 9, 2026 (US-122.25, the open-shifts dashboard):

  • GET /api/v1/open-shifts/dashboard (getOpenShiftsDashboard): with no section, data.counts (open, open_no_responses, assigned_upcoming, paused) and data.coverage (per service area: open and unanswered shifts and how many people have it in reach). With section one of not_responding, onboarding, pauses, activity or alerts_sent, that list's rows and total, paged by limit and offset; alerts_sent takes status (pending, sending, sent, failed, unknown, skipped). Needs open_shifts.administer. New refusals: 422 invalid_section and invalid_status.

The MCP tool open_shifts_dashboard answers the same as getOpenShiftsDashboard.

Added November 10, 2026 (US-122.15, completed, no-show, strikes and pauses):

  • POST /api/v1/open-shifts/{id}/complete (postOpenShiftsByIdComplete): an assigned shift moves to completed; its Shift Plan pick and Visit stay. Before the shift's start it is refused 409 not_started while the agency's complete_before_start is off. Answers 200 with data the shift. Needs open_shifts.manage.
  • POST /api/v1/open-shifts/{id}/no-show (postOpenShiftsByIdNoShow): once the start has passed, the assignment is undone as an unassign does it, the shift is cancelled with outcome no_show, its responders and the assignee are told, and the assignee gets one strike. Strikes in the agency's strike_window_days reaching strikes_before_pause pause the caregiver from responding to open shifts for pause_days; sign-in, clock-in and EVV are never paused. Before the start: 409 not_started. Needs open_shifts.manage.
  • POST /api/v1/caregivers/{id}/restore-open-shift-access (postCaregiversByIdRestoreOpenShiftAccess): clears the pause and voids every strike in one transaction. Answers 200 with data.caregiver_id, data.voided and data.lifted (false when there was nothing to lift). Needs open_shifts.administer.
  • New refusals, each 409: not_assigned (a shift that is not assigned, a second complete or no-show included) and not_started. A caregiver's late cancel (US-122.14c) now records a strike too. assign warns open_shifts.caregiver_paused for a paused caregiver and still assigns.

The MCP tools complete_open_shift, mark_open_shift_no_show and restore_open_shift_access answer the same as the three operations above.

Deprecated November 16, 2026 (US-118.17, one delivery record): POST /api/v1/work-orders/{id}/fill-from-evv and POST /api/v1/work-orders/{id}/fill-from-care-logs, sunset May 16, 2027, after which each answers 410. A Work Order's delivered days now come straight from its care logs, so neither operation writes anything: each answers 200 in its existing schema with filled, updated, differences and flagged empty and unchanged listing every date of the month with a delivery, and leaves lock_version as sent, so a retry at the same version answers the same. The 409 stale_record, 422 not_editable and 404 answers are unchanged, and so are the fill_work_order_from_evv and fill_work_order_from_care_logs MCP tools, which answer the same.

Changed November 8, 2026 (US-118.16, a task mark is the day's care log's):

  • PUT /api/v1/work-orders/{id}/tasks/{task_definition_id}/days/{date} (putWorkOrdersByIdTasksByTaskDefinitionIdDaysByDate) and POST /api/v1/work-orders/{id}/unplanned-tasks (postWorkOrdersByIdUnplannedTasks) write the mark on that day's care log (the Work Order's client, caregiver, service and shift), drafting one with source office when the day has none, and no longer on the Work Order. They need timesheets.manage where they needed work_orders.manage: a key without it answers 403 forbidden, even one holding work_orders.manage. A combined Work Order (service legacy) keeps its own marks and still needs work_orders.manage.
  • Both answer 409 frozen for a day a submitted, approved or exported Returned Timesheet holds, the message naming the Timesheet's month and status and details the Timesheet; it answers again once that Timesheet is back in draft. The PUT answers 409 record_locked when the day's care log is signed.
  • The answer is the care log's mark: id is its care_log_tasks id (null when completed: null met a day with no mark), completed is true for done and false for not_needed or refused, and notes is its reason. completed: false is stored as not_needed, and completed: null clears the mark. An unplanned task is stored as done with the notes as its reason. A combined Work Order answers its own row, as before.
  • The MCP tools toggle_work_order_task and add_unplanned_task need timesheets.manage too, and refuse a frozen day with the same sentence.

Changed November 8, 2026 (US-118.21, a Work Order's delivered days):

  • A Work Order's entries, on GET /api/v1/work-orders and GET /api/v1/work-orders/{id}, are the delivered days of its month: one per live care log of its client, caregiver, service and shift, ordered by date, then Time In (none last), then sequence. The item keys are unchanged. time_in and time_out are the care log's Mountain times, so a night's time_out is earlier than its time_in; hours_worked is the real length, null when a time is missing. A day typed on the Work Order with no care log is no longer an entry. The MCP find_work_orders now answers each Work Order's entries as get_work_order does.
  • A combined Work Order (service legacy) answers every row recorded on it as its entries, as before: no care log carries a combined service.

Added November 8, 2026 (US-118.27, imported Sandata visits become care logs):

  • GET /api/v1/visit-imports/{id} answers findings, once the import has ended: a list of VisitImportFinding (row, rule_id, message, care_log_id, service_date, timesheet_id, status, period), today only care_logs.imported_for_billed_day, a visit on a day a submitted, approved or exported Returned Timesheet holds, left unlinked to that day's care log. Never a name or a Medicaid ID. The MCP get_visit_import answers it too.
  • An unresolved row's reason can be no_work_order_for_code (no Work Order of the client and caregiver bills the visit's code) or delivery_failed (the visit was saved but its care log was not; import the file again).
  • care_logs.imported_for_billed_day joins the code values of a care log's warnings (CareLogWarning, CareLogDetail, MeCareLogDetail).

Changed November 8, 2026 (US-118.36, US-118.37, #3945, delivered-day warnings):

  • POST /api/v1/me/care-logs/{id}/tasks and POST /api/v1/me/care-logs/{id}/tasks/{task_id}/mark add the findings the write raised (care_logs.over_weekly_limit and the like) to the care log's warnings. Warnings, never refusals.
  • A Timesheet entry write's warnings can hold timesheets.time_out_before_time_in: the Time Out is before the Time In, so the day counts as an overnight shift.
  • POST /api/v1/paper-capture/forms/{id}/apply lists in care_log_warnings, for either card, each day whose delivery another source recorded (kind recorded): the paper's times were not written and the recorded times stand, and those fields are left out of what the apply wrote.

Changed November 8, 2026 (US-120.28, a client lead's languages):

  • POST /api/v1/prospects and PATCH /api/v1/prospects/{id} keep languages for a potential client as well as a potential employee; it was ignored on a client lead before. Converting a client lead writes its languages, joined with ", ", into the client's language_preference. The MCP tools create_prospect and update_prospect do the same.

Added November 8, 2026 (US-120.25, a contact's History):

  • GET /api/v1/clients/{client_id}/contacts/{contact_id}/history (getClientsByClientIdContactsByContactIdHistory) reads the edits of one of a client's contacts, newest first, as the People section's History does: each a ContactHistoryEntry with inserted_at, user_name ("System" when no member is recorded) and changed_fields, never an old or new value. A contact holding no relation to the client answers 404. The MCP tool get_contact_history does the same.

Added November 8, 2026 (US-120.19, a client's people):

  • GET /api/v1/clients/{id}/relations lists a client's people (responsible party, representative, emergency contacts, case manager and supervisor, CMA office, physician, pharmacy, key holder), current and ended, each with its contact, ordered by kind, rank and start date; kind narrows to one.
  • POST /api/v1/clients/{id}/relations relates a person by contact_id or a new contact, answering 201 with the relation and warnings. Replacing a responsible party, representative, case manager, supervisor or CMA office names the current relation in replaces (id, lock_version); without it, or naming one no longer current, it answers 409 stale_record.
  • POST /api/v1/clients/{id}/relations/{relation_id}/end ends a relation, today when no ends_on is sent; one already ended answers unchanged.
  • GET /api/v1/contacts finds contacts by name or organization, GET /api/v1/contacts/{id} reads one and PATCH /api/v1/contacts/{id} edits one at its lock_version. A contact is seen only through a client the caller may open.
  • The MCP tools list_client_relations, set_client_relation, end_client_relation and find_contacts do the same.
  • Deprecated: the Client's emergency_contact_name and emergency_contact_phone ("Deprecated: use /api/v1/clients/{id}/relations. Served until 2027-05-31."), now read from the client's emergency contact 1, and MCP create_client's responsible_party ("Deprecated: use set_client_relation. Served until 2027-05-31."). Writes of them still land in the client's relations until then.

Added November 8, 2026 (US-120.13, one person recorded twice):

  • POST /api/v1/contacts/{id}/merge, body {loser_ids}: the contacts loser_ids names (1 to 50) are the same person as the one in the path. Their relations move to it and they are deleted; the answer is the contact with relation_ids and client_ids. 422 invalid for an empty or oversized list, 404 not_found for a contact not this agency's or already merged, 403 without clients.manage, 409 stale when another write got there first. The MCP tool merge_contacts does the same.

Added November 8, 2026 (US-120.17, the caregiver's representative step): POST /api/v1/me/half-month-summaries and GET /api/v1/me/care-logs/{id} (and every other /api/v1/me/care-logs/{id} answer) carry representatives, a list of MeRepresentative (relation_id, name, relationship_label): the client's current representative, then its current responsible party, one entry per person, empty when the office recorded neither or the client is not one the caregiver is assigned to today. POST /api/v1/me/half-month-summaries/{id}/signatures and POST /api/v1/me/care-logs/{id}/attestation take an optional signer_relation_id on a representative's line: a listed id signs under that entry's name and relationship (signer_name ignored), an id the list does not hold answers 422 validation_failed, and with neither field the first listed entry signs, else "Representative". A signer_name alone now signs with no relationship, where before the line copied the client's responsible party's relationship and, left out, its name.

Changed November 5, 2026 (US-114.19, Work Orders take the access scope):

  • Every Work Order, monthly report, task set template and provider type operation decides on the caller's permissions rather than its role: reads need work_orders.view, writes work_orders.manage, template and list writes agency_settings.manage, and provider type modifier and procedure code writes billing.manage, each refused with 403 forbidden and details.permission. POST /api/v1/work-orders/{id}/duplicate with mode no longer answers 403 duplicate_not_permitted; a key whose member's roles grant work_orders.manage may duplicate, archive, unarchive, reopen and redraft, where an admin or office manager role was required before.

Added November 5, 2026 (US-83.6, LRP Homemaker plans): a Plan of Care (GET, POST and PATCH /api/v1/plans-of-care, and the plan-of-care MCP tools) carries lrp, true when a legally responsible person provides a Homemaker plan's care. An LRP plan is its own billing line: it stays current beside the client's regular Homemaker plan, and a new LRP plan replaces only the client's LRP plan. lrp is false when left out of a create, and a plan whose service is not Homemaker answers 422 naming lrp when it is sent true. A plan's lrp is fixed once it is created: a PATCH that changes it answers 422 naming lrp.

Changed November 4, 2026 (#3849): an assignment schedule day's hours (GET and PUT /api/v1/assignments/{id}/schedule, the get_assignment_schedule and save_assignment_schedule MCP tools) keeps two decimal places when one would lose precision: 3:00 PM to 12:15 AM next day is 9.25, not 9.3, and 9:00 to 9:20 AM is 0.33. Whole and half hours read as before (4.0, 2.5). Stored rows were recomputed to match.

Added November 4, 2026 (Change caregiver):

  • POST /api/v1/work-orders/{id}/change-caregiver and the change_work_order_caregiver MCP tool give a Work Order to another caregiver from a date, as the page's Change caregiver does. The body is a WorkOrderChangeCaregiver: caregiver_id, from (YYYY-MM-DD) and lock_version, all required. From the Effective Date or earlier, a copy for the new caregiver replaces the Work Order and the old one is archived; from a later date, the old one closes the day before. It answers 201 with the new Work Order as data and warnings. Refusals: 422 same_caregiver (already this Work Order's caregiver), 422 work_order_archived, 409 on a stale lock_version, 403 forbidden without work_orders.manage (US-114.19), 404 for a Work Order not in the agency.

Added November 4, 2026 (US-121.9, InMyTeam's weekly schedule PDF):

  • POST /api/v1/assignments/schedule-import takes InMyTeam's weekly schedule, printed to PDF, as the multipart field file (at most 10 MB) and imports it as Import Assignments does, inside the request. It answers 200 with a ScheduleImportResult: dry_run, week_start and items, each with row, client, caregiver, service, outcome (new, changed, unchanged, not_imported, not_on_schedule), days_before, days_after, reason and warnings; a real run adds imported, updated, skipped, failed (each {row, errors}), reasons and warnings. dry_run "true" writes nothing. Names resolve among the agency's own clients and caregivers only. Sending the file again imports and updates nothing; a pair another send created first is skipped as already_on_file. It needs imports.manage and scheduling.manage (403 forbidden with details.permission); 422 not_a_schedule, unreadable_pdf, file_required, file_too_large, invalid_dry_run write nothing.

Added November 3, 2026 (US-121.7, client, caregiver and PAR imports):

  • POST /api/v1/clients/import, POST /api/v1/caregivers/import and POST /api/v1/authorizations/import import a file sent as csv (text) or csv_base64, at most 5,000 rows, through the pipelines Import Clients, Import Caregivers and Import PARs run, InMyTeam's Patients, Caregivers and Authorization exports included. Each answers 200 with a RecordImportResult: dry_run, format (hcb, inmyteam_patients, inmyteam_caregivers, inmyteam_authorizations), imported, updated, skipped, failed (each {row, errors}) and reasons by code; the caregiver import adds pay_withheld, the rows whose pay was left out for a key without payroll.manage. dry_run true answers the same counts and writes nothing. A file sent twice, or twice at once, writes each record once; the second send's rows are skipped as already_on_file. They need imports.manage, and the PAR import authorizations.manage too (403 forbidden with details.permission); 422 file_required, empty_file, too_many_rows, csv_parse_error, invalid_dry_run, and for the PAR import not_an_authorization_export. MCP: import_clients, import_caregivers and import_authorizations answer the same.

Changed November 3, 2026 (US-121.11, overnight schedule rows):

  • PUT /api/v1/assignments/{id}/schedule: a day may carry an optional boolean ends_next_day (default false) for a shift that ends after midnight, such as 22:30 to 00:30. A day whose end_time is before its start_time without it answers 422 invalid_schedule: ": end_time must be after start time; turn on Ends next day for a shift that ends after midnight". The overlap check with the assignment's other shifts compares across midnight: a Monday 22:00-02:00 overnight day on shift 1 refuses a Tuesday 01:00-03:00 day on shift 2.
  • GET /api/v1/assignments/{id}/schedule, and the schedule the PUT answers: every day carries ends_next_day, and an overnight day's hours count past midnight (22:30 to 00:30 is 2.0). MCP: save_assignment_schedule and get_assignment_schedule take and return it the same way.

Added November 3, 2026 (US-121.8, EVV rollout):

  • GET /api/v1/settings/evv-collection reads the agency's EVV rollout (evv_rollout: off, pilot or all), the day collection starts (evv_collected_from, a date or null) and the number of caregivers enrolled in the pilot (enrolled_caregivers).
  • PATCH /api/v1/settings/evv-collection sets either field; a rollout outside the three, or a start day that is not a date, answers 422 validation_failed and stores nothing. Admin keys only (403 forbidden otherwise). MCP: get_evv_collection and update_evv_collection.
  • GET and PATCH /api/v1/caregivers/{id} carry evv_enrolled_on, the day a caregiver joins the EVV pilot (null when not enrolled).

Added November 3, 2026 (US-121.2 and US-121.10, a PAR's weekly allowance):

  • GET, POST and PATCH /api/v1/authorizations and /api/v1/authorizations/{id}, and every other answer carrying a ServiceAuthorization: weekly_hours and weekly_units, decimal strings derived on every read from the PAR's total and dates (inclusive days / 7, to two places). weekly_hours is null for a visits PAR, and both are null when the units, unit type or dates are missing. They are output only: the create and update schemas do not offer them. MCP: get_authorization, find_authorizations and par_units_remaining return them the same way.
  • POST /api/v1/recurring-schedules, PATCH /api/v1/recurring-schedules/{id}, POST /api/v1/recurring-schedules/{id}/lines and PATCH and DELETE /api/v1/recurring-schedules/{id}/lines/{line_id}: a RecurringLineWarning code may be over_weekly_allowance, a line on a 15-minute code whose hours a week over the run period exceed its PAR's weekly allowance. It never stops the write. Every warning carries authorization_id, the PAR an over_weekly_allowance warning was judged against, null for every other code. The MCP recurring-schedule tools answer the same.

Changed November 2, 2026 (Epic 114, access policy):

  • POST /api/v1/paper-capture/forms/{id}/apply needs, besides clients.manage, the target record's own permission: a Work Order work_orders.manage, a timesheet timesheets.manage, a Plan of Care or supervisory visit care_plans.manage; a Time and Services Card also needs timesheets.manage, since it writes the month's timesheet and care logs (on a Work Order, both). The permission is judged against the form as the apply locks it, so the paper-capture consent and the form's own refusals (404, 422 invalid_decisions, not_ready, no_target) are answered first. Without it the apply answers 403 forbidden with details.permission naming what is missing, and writes nothing. MCP: apply_paper_form refuses the same way.
  • POST /api/v1/paper-capture/applications/{id}/undo needs what applying did: besides clients.manage, the target record's permission as above. Without it the undo answers 403 forbidden with details.permission, and restores nothing. MCP: undo_paper_application refuses the same way.

Changed November 2, 2026 (#3683, remittance matching has no cap):

  • GET /api/v1/remittances/{id}: complete is false only for a remittance with no parse (null reconciliation, no lines). A parsed remittance is matched against every one of the agency's claims, so it always answers true, and a line's null claim_id means it matched none of them, never that matching stopped early. The descriptions of complete and of a line's claim_id say so.

Added November 2, 2026 (US-115.19, webhooks):

  • Webhook event type caregiver.credential_expiring, sent once when a caregiver's dated credential enters its month window (8 to 30 days left) and once when it enters its week window (7 days or fewer), found by a weekly run, whether or not the caregiver can receive texts. data is caregiver_id, credential (criminal_background_expiry, dora_expiry, caps_expiry, driver_license_expiry or main_training_expiry), expires_on and lead (month or week). A renewed credential is announced afresh.

Added November 2, 2026 (US-115.22, webhooks):

  • Webhook event type claim.denial_withdrawn, sent when an agency undoes the attribution that denied a claim, and only to an endpoint whose claim.denied for that claim was delivered. data is the denial's claim_id, batch_id, response_id and payment_status_code, plus withdrawn_event_id, the id of the claim.denied it withdraws. No order is promised between it and a later claim.denied of another claim.

Added November 2, 2026 (US-115.18):

  • Webhook event type visit.verified, sent once per visit an office user verifies (one at a time or in bulk). Its data carries visit_id, client_id, caregiver_id and status only; read the visit with an agency API key. Register it in Settings, Webhooks.

Added November 1, 2026 (US-113.17, HCB University):

  • GET /api/v1/university/videos and GET /api/v1/university/videos/{slug}: the narrated training videos in the order /university shows them, and one video with the pages it shows, its chapters, and each rendered language's video, captions and poster as storage URLs signed for 6 hours (null when one could not be signed). The same for every agency, readable by any key; 404 not_found for a slug the catalog does not list. The MCP tools list_university_videos and get_university_video answer the same.

Added November 1, 2026 (US-117.6, one store for dismissed warnings):

  • POST /api/v1/finding-dismissals dismisses any warning by its rule_id, subject_type, subject_id (and subject_date for a warning about one day), the fingerprint it was listed with, its context and, where its rule asks why, a reason of 3 to 500 characters; it answers 201 with the FindingDismissal, the same one again for a warning already dismissed at those figures. POST /api/v1/finding-dismissals/{id}/restore shows it again and answers 200 with the dismissal, kept, its restored_at set. Refusals: 409 stale_finding when the fingerprint is not the warning's current one; 422 unknown_rule, not_dismissible and reason_required; 403 for a credential that may not write; 404 for a dismissal that is not the agency's or is already shown again. The MCP tools dismiss_finding and restore_finding answer the same functions.
  • POST /api/v1/revenue-warnings/dismissals now answers 409 stale_finding when the fingerprint is not the warning's current one (its figures changed since it was listed), and writes nothing. DELETE on the same path keeps the dismissal as history rather than deleting it; its 204 is unchanged.

Added October 31, 2026 (US-112.10, recurring batches):

  • GET /api/v1/batches/{id}/recurring-proposal (Make recurring's dialog), GET /api/v1/recurring-schedules, POST /api/v1/recurring-schedules, GET /api/v1/recurring-schedules/{id}, PATCH /api/v1/recurring-schedules/{id} (settings, then status pauses, resumes or ends it), POST /api/v1/recurring-schedules/{id}/lines, PATCH /api/v1/recurring-schedules/{id}/lines/{line_id} (status pauses or resumes a line), DELETE /api/v1/recurring-schedules/{id}/lines/{line_id}, POST /api/v1/recurring-schedules/{id}/skip-next, POST /api/v1/recurring-runs/{id}/hold and POST /api/v1/recurring-runs/{id}/rerun. A write answers the record and a warnings array, which never blocks it. Every write and the proposal need hcb.submit and full access: 403 insufficient_scope, read_only or submission_blocked otherwise. Refusals use the schedule page's words: 409 run_status, period_moved (with the schedule's next_period), schedule_exists, stale_record; 422 batch_in_progress, schedule_ended, nothing_to_bill, no_submission_access, patient_limit_exceeded. The MCP tools propose_recurring_schedule, create_recurring_schedule, list_recurring_schedules, get_recurring_schedule, update_recurring_schedule, add_recurring_line, update_recurring_line, delete_recurring_line, hold_recurring_run, skip_next_recurring_run and rerun_recurring_period run the same operations.

Changed October 30, 2026 (#3389, a Plan of Care entered in error is deleted):

  • DELETE /api/v1/plans-of-care/{id} soft-deletes a draft or a voided plan, as the client's Plans of Care tab does, and answers its id and deleted_at. The plan leaves GET /api/v1/plans-of-care and every other read; the audit trail keeps it. A signed plan answers 422 plan_signed: void it first. Deleting a current plan leaves its service with no current plan. The MCP tool delete_plan_of_care does the same.

Added October 30, 2026 (#3362, a client's calendar):

  • GET /api/v1/clients/{id}/calendar-events lists a client's calendar events as the client's Calendar tab does, earliest due first, future events included; open=upcoming or open=overdue narrows it to the open ones due today or later, or past their date. Any event it lists can be closed with POST /api/v1/reminders/{id}/complete or /dismiss. The MCP tool list_client_calendar_events answers the same page.

Changed October 30, 2026 (A-4, an agency API key signs nothing):

  • Every operation that records a signature answers 403 signature_requires_person to an agency API key (hcb_key_), before the record is looked up: POST .../signatures on plans of care, supervisory visits, emergency information, consent forms, Monthly Client Reports, critical incidents, complaints, Work Orders and timesheets, POST /api/v1/signed-records/{record_type}/{id}/addenda, and POST /api/v1/care-logs/{id}/paper-on-file. The refusal spends none of the key's writes. A key used to sign as the admin who created it, whoever ran it. A member signs in the web app, or through an AI app they connected, which signs as them. Every other operation a key may call is unchanged, and the request's audit row now names the key's label as well as its id.

Changed October 30, 2026 (care-log verification fixes):

  • POST /api/v1/me/care-logs/{id}/tasks adds a task the caregiver did off the plan, as the app's "Add a task I did": body {task_definition_id, count?, reason_code?, reason_note?}, answering the care log. A mark of a task not on the log (422 task_not_on_log) now points the caregiver token at this route.
  • A care log's warnings may hold times_missing: no Visit is linked and the time in or time out is empty, so the day counts 0 hours. Its task_definition_id is null. A warning only; nothing refuses on it.
  • POST /api/v1/care-logs/{id}/paper-on-file answers 422 invalid_scan for a scan, or a document on file, that is not a PDF, JPEG or PNG by its bytes, or is over the size limit; nothing is stored or signed. A document_id whose virus scan has not finished answers 409 scan_pending, and one the scan found infected or could not scan answers 422 scan_not_clean.
  • POST /api/v1/me/care-logs/{id}/attestation-skip with an unknown reason now names the reasons that are allowed in its 422.

Changed October 30, 2026 (US-101.47, DocuSign sends the contract records):

  • POST and GET /api/v1/signed-records/{record_type}/{id}/docusign-envelopes take client_consent_form, client_emergency_info and monthly_client_report as record_type, besides plan_of_care and supervisor_visit. A Monthly Client Report taken by phone or video call and a disclosure notice the client declined have no remote signer: sending one answers 422 role_not_allowed. complaint and critical_incident stay unsupported and answer 404 not_found. The MCP tools send_record_with_docusign and list_docusign_envelopes take the same record_type values.

Added October 30, 2026 (US-101.51, the agency's own DocuSign key):

  • PUT /api/v1/settings/docusign/own-key, body {integration_key, secret_key}, stores the integration key and secret of a Private custom integration the agency made in its own DocuSign account, encrypted, and never shows either again; Connect and every token refresh then run under it instead of HomeCareBilling's app-wide key, and an active connection, which was issued under the old key, must be connected again. 422 validation_failed names the rule (a UUID; a secret of 8 to 256 characters without spaces), never the value. DELETE /api/v1/settings/docusign/own-key removes it; nothing stored answers the same body and writes nothing. Admin credentials only. MCP: set_docusign_own_key, remove_docusign_own_key.
  • GET /api/v1/settings/docusign (and get_docusign_settings) answer own_key_set and own_key_set_at.

Changed October 29, 2026 (#3319, the authenticator code kept out of logs):

  • PUT /api/v1/settings/security takes the authenticator code as otp_code. code is deprecated: it is still read when otp_code is absent, until April 30, 2027. The MCP tool update_security_settings takes the same arguments.

Changed October 29, 2026 (care-log epic area fix, half-month):

  • POST /api/v1/me/half-month-summaries/{id}/client-skip answers 409 caregiver_not_signed on a summary whose caregiver line is not signed (a draft); the skip is recorded only after the caregiver signs.

Changed October 29, 2026 (US-101.22, the care-log fill keeps the office's decisions):

  • POST /api/v1/work-orders/{id}/fill-from-care-logs lists in differences, ordered by date, each day an office-set mark or a date marked not worked kept the fill from writing; the reason of a not-worked day is "Marked not worked; the care log was not filled".

Changed October 29, 2026 (#3229, bug reports that say enough to act on):

  • POST /api/v1/support-tickets takes optional screen, record_ids, steps_to_reproduce, expected, actual and follow_up_id. A bug report missing what the server cannot work out from the user's recent activity answers 422 needs_more_info and files nothing: its details name the missing items, the questions to ask the user, and a follow_up_id. Send the request again with the answers and that follow_up_id; it files the request whatever is still missing, once however often it is sent. A follow_up_id the server did not give that user in that agency is asked again like a first call.
  • A record_ids that is not up to 10 record ids, "any" or "don't know" answers 422 invalid_record_ids; a follow_up_id that is not an id answers 422 invalid_follow_up_id.

Added October 29, 2026 (US-111.20, the SFTP drop's port):

  • PUT /api/v1/payroll/connection/sftp takes port, an integer 1 to 65535 or the empty string (the schema's oneOf); absent or null keeps the saved one, the empty string clears it, and none saved connects on 22. Another value answers 422 invalid_port. A new host or port forgets the trusted server key. MCP set_payroll_sftp takes it too.
  • The connection's settings carries sftp_port, null when unset.

Added October 29, 2026 (US-111.24, Add to ADP):

  • POST /api/v1/caregivers/{id}/adp-hire sends a caregiver with no ADP worker to RUN as a new hire, as Add to ADP on ADP workers does, once and never retried, and answers {caregiver_id, status, message}: sent (ADP named the worker; it is linked), pending_in_adp (finish the hire in RUN's New Hire Wizard) or unconfirmed (ADP did not answer). New answers: 409 hire_push_off (not RUN, or allow_hire_push off), 409 already_linked (an ADP worker or an open send), 422 hire_refused, 502 adp_unreachable. Agency-admin only, at full access (403 submission_blocked, 403 read_only). MCP: add_caregiver_to_adp.
  • DELETE /api/v1/caregivers/{id}/adp-hire is "I checked RUN: not there": it clears an unconfirmed or pending_in_adp send (409 hire_not_abandonable otherwise), at full access or while billing blocks submission (403 read_only only). MCP: add_caregiver_to_adp with not_in_run: true, at the same levels.
  • PATCH /api/v1/payroll/connection takes allow_hire_push, the Payroll tab's "Let HomeCareBilling start new hires in RUN". MCP: update_payroll_connection.

Added October 29, 2026 (US-111.23, the ADP Marketplace connect code):

  • POST /api/v1/payroll/connection/connect-code answers 201 {connect_code, expires_at}: a new single-use code to paste into the ADP Marketplace checkout form, valid 7 days, as Settings > Payroll's Connect in ADP Marketplace shows it. A new code replaces the old, the connection waits for its ADP Marketplace order, and the code is never answered again. Agency-admin only (403 forbidden otherwise); 409 payroll_integration_off while connecting through ADP Marketplace is off for the agency. Issued only where the tab offers one, changing nothing otherwise: 409 marketplace_not_offered unless the connection's ADP is RUN and HomeCareBilling's ADP Marketplace listing is set; 409 already_connected while the connection is connected through ADP Marketplace, waiting for consent, or needs attention there. MCP: create_payroll_connect_code.

Added October 29, 2026 (US-101.34, the client chart):

  • GET /api/v1/clients/{id}/chart (getClientsByIdChart) answers a page of the client's chart, newest first: every signed record, document, legacy paper scan and care log, with each record's state, signers, open signature lines, true copy, signed addenda and void. Filters types, service_type, caregiver_id, from and to; limit (default 50, at most 200) and offset. Another agency's client is 404; a filter it cannot read is 400 naming it. The MCP tool get_client_chart answers the same.

Changed October 29, 2026 (care logs meet the contract records):

  • GET /api/v1/print/care_log reads addenda_through as the other signed records' prints do, and the care log's print carries its signed addenda after its signatures. A care log addendum's true copy prints through it.
  • /api/v1/signed-records/{record_type}/{id}: the record_type description, and record_type on RecordAddendum and SignedRecordState, name every type taken: supervisor_visit, plan_of_care, monthly_client_report, complaint, critical_incident, client_consent_form, client_emergency_info, care_log and half_month_summary (which takes no addendum). An unknown record_type's 404 names them too. No type was added or removed.
  • POST /api/v1/care-logs/{id}/paper-on-file with a document_id takes a document a person uploaded to the client's file; a paper-capture scan or a document the system made (a true copy, a voice attestation) is 422 document_not_found, as another client's document is.

Added October 28, 2026 (#3226, logging a monthly follow-up):

  • POST /api/v1/clients/{id}/follow-up/log logs the client's open monthly follow-up as the Log form of Operations > Follow-Ups does: contact_type and contact_date (not in the future), and optional notes. A client with nothing open is 422 no_open_follow_up; another agency's client is 404.

Added October 28, 2026 (US-111.20, the ADP SFTP drop):

  • PUT /api/v1/payroll/connection/sftp saves the SFTP drop's host, user, folder and private_key as Settings > Payroll does; a null or absent field keeps the saved one. A key that is not an OpenSSH or PEM private key without a passphrase answers 422 invalid_private_key. MCP set_payroll_sftp does the same.
  • The connection (GET, PATCH and the new PUT) carries sftp_key_fingerprint, the SHA-256 fingerprint of the saved key's public half, and settings.sftp_host_key_fingerprint, the server key trusted at the first successful Test connection; secrets_set.sftp_private_key says whether a key is saved. The key itself is never answered.
  • POST /api/v1/payroll/connection/test tests the SFTP drop on an :sftp_drop connection: it signs in, lists the folder and answers "Connected. {folder} holds {count} files." or which step failed.
  • POST /api/v1/payroll-exports/{id}/submissions on an SFTP drop connection uploads the export's Workforce Now paydata file once; with resend: true after ADP holds the file it answers 409 not_replaceable.

Changed October 28, 2026 (US-111.12, Test connection):

  • POST /api/v1/payroll/connection/test answers 409 not_api_connection and records nothing while the agency's connection uses a method other than its own API credentials, with a sentence saying why Test connection is refused. MCP test_payroll_connection refuses with the same sentence.

Added October 28, 2026 (US-111.18, connection health):

  • GET /api/v1/payroll/connection (and PATCH's answer) carries health: status, last_success_at, last_failure_at, consecutive_failures, certificate_expires_at, status_reason (token_refused, circuit_open, certificate_expired, method_paused or Test connection's code), message (the reconnect banner's sentence) and paused_until (while HomeCareBilling has paused calls to ADP). MCP get_payroll_connection answers the same.

Added October 28, 2026 (US-111.17, Fix and resend):

  • POST /api/v1/payroll-exports/{id}/submissions takes an optional body: resend: true replaces what ADP holds as "Fix and resend" on /payroll-exports does, superseding the earlier send, and choices (per caregiver id, replace or keep) answers a 409 needs_choice, whose details.lines give HomeCareBilling's hours and ADP's for each caregiver whose hours in ADP were edited. A send or resend of hours ADP already has answers the last send with unchanged: true. New answers: 409 resend_required (the hours changed after a send ADP holds lines of), 409 awaiting_confirmation, 409 export_exported, 502 read_back_failed. MCP: send_payroll_export takes resend and choices, and answers needs_choice with the same lines.

Added October 28, 2026 (US-111.15, Send to ADP):

  • POST /api/v1/payroll-exports/{id}/submissions sends a generated export to ADP as "Send to ADP" on /payroll-exports does: it checks the export, queues one line per caregiver and answers the submission at once. An export that already has a send answers that send and posts nothing again. 422 unsendable (with the findings) when the check finds it cannot be sent, 422 not_sendable_status when it is not generated (or was regenerated or marked downloaded while the send was being built), 403 submission_blocked or read_only for an agency whose HomeCareBilling billing pauses sending, 403 insufficient_scope for a grant without hcb.submit. Any member at full access. MCP: send_payroll_export.
  • GET /api/v1/payroll-exports/{id}/submissions/{submission_id} reads the send and a page of its lines (50, at most 100): each line's status, the label the screen shows and ADP's error, never the hours or rates posted. Any member at every access level. MCP: get_payroll_submission.

Added October 28, 2026 (US-111.14, ADP's codes and pay cycles):

  • POST /api/v1/payroll/earning-mappings/sync queues a read of ADP's earning codes, rate codes and pay cycles, as "Sync from ADP" on /payroll/earnings does, and answers {queued: true}. Agency-admin only (403 forbidden otherwise); 409 payroll_integration_off while the API connection is off and 409 not_api_connection while the agency sends payroll by file or SFTP. MCP: sync_payroll_codes.
  • POST /api/v1/payroll-exports/:id/check can name seven more rules for an API connection: period_not_an_adp_pay_cycle, pay_frequency_differs, code_not_in_adp, code_worker_type_mismatch, adp_terminated, adp_on_leave and rate_differs.

Added October 28, 2026 (US-111.13, ADP workers and their caregivers):

  • GET /api/v1/payroll/workers pages the ADP workers of the agency's API connection beside their caregivers (filter all, needs_person, linked or no_adp_worker; 50 a page, at most 100), each with how it was linked and its warning. Never a rate.
  • POST /api/v1/payroll/workers/{id}/link, body {caregiver_id}, and DELETE /api/v1/payroll/workers/{id}/link link and unlink as /payroll/workers does; 409 already_linked or caregiver_already_linked when the worker or the caregiver is taken.
  • POST /api/v1/payroll/workers/sync queues a read of every ADP worker and answers {queued: true}. All four are agency-admin only (403 forbidden otherwise), answer 409 payroll_integration_off while the API connection is off and 409 not_api_connection while the agency sends payroll by file or SFTP. MCP: list_payroll_workers, link_payroll_worker, unlink_payroll_worker (argument payroll_worker_id), sync_payroll_workers.

Added October 28, 2026 (US-111.12, the ADP API Central connect flow):

  • POST /api/v1/payroll/connection/csr makes the certificate request for the agency's ADP API Central project and answers 201 {csr_pem}; HomeCareBilling keeps the private key, and a live connection keeps its current key until the certificate for the new request is saved.
  • PUT /api/v1/payroll/connection/credentials, body any of {client_id, client_secret, certificate_pem} (null or blank keeps the saved value), answers the connection as GET /api/v1/payroll/connection does. A certificate that is not one, was not signed for HomeCareBilling's request or current key, or has expired answers 422 invalid_certificate with the sentence Settings > Payroll shows, and nothing is saved.
  • POST /api/v1/payroll/connection/test makes one read at ADP and answers {connected, message}, the sentence the tab shows. All three are agency-admin only (403 forbidden otherwise) and answer 409 payroll_integration_off while sending with the agency's own API credentials is off. No answer carries a secret or a key. MCP: create_payroll_csr, set_payroll_credentials, test_payroll_connection.

Added October 28, 2026 (US-111.7, the ADP payroll connection):

  • GET /api/v1/payroll/connection answers the agency's ADP payroll connection as Settings > Payroll shows it: enabled, product, method, status, methods_offered, settings (RUN company code, Employee ID template, file version, contractors and the rest), certificate_expires_at and secrets_set, a boolean per secret and never a value. An agency with no connection gets one, sent as a file to an unknown ADP.
  • PATCH /api/v1/payroll/connection, body any of {enabled, product, method, run_company_code, employee_id_template, run_file_version, send_contractors}, applies the tab's checks: a RUN company code that is not 1 to 10 letters and numbers answers 422 naming run_company_code; a method not offered for the product stores file, and notice says so. Both are agency-admin only (403 forbidden otherwise) and answer 409 payroll_integration_off while the integration is off, except a PATCH turning enabled on when the platform and the plan allow it. MCP: get_payroll_connection, update_payroll_connection. GET/PATCH /api/v1/settings/adp are unchanged.

Added October 28, 2026 (US-111.6, ADP-format import files):

  • GET /api/v1/payroll-exports/{id}/file takes an optional format query parameter. adp_import answers the file ADP imports as it is, as Payroll exports > Download for ADP builds it: RUN's Time Sheet Import (##GENERIC## V1.0, rate codes, file Monthly-03012026-03312026.csv and the like) or the Workforce Now paydata file (PR{co}EPI.csv), built from the timesheets and cash advances the export was generated from, every line ADP would refuse left out. entry_sheet answers the RUN sheet the office types from (Entry sheet (to type from)). A format answers 409 payroll_integration_off while the ADP payroll integration is off, 422 with the check's unsendable code (product_unknown, no_company_code) when no line can be written, and 422 unknown_file_format for another value. Without format the answer is unchanged. Any member at every access level. MCP: get_payroll_export_file takes the same format.

Added October 28, 2026 (US-111.5, the pre-send payroll check):

  • POST /api/v1/payroll-exports/{id}/check answers {data: [{severity, code, caregiver_id, message, fix_path}]}, the findings Payroll exports > Check lists: every line ADP would refuse and why (unsendable, refusal, warning), sorted by severity then caregiver last name, with the page where each is fixed. code is an enum naming the rule, RUN's rate_codes_assumed and too_many_rates among them. It changes nothing, so it takes no Idempotency-Key and any member may call it at every access level, a read-only agency or key included. Another agency's export answers 404 not_found; 409 payroll_integration_off while the ADP payroll integration is off. MCP: check_payroll_export.

Added October 28, 2026 (US-111.4, ADP earning mappings):

  • GET /api/v1/payroll/earning-mappings lists the twelve ADP earning-code slots /payroll/earnings shows, every hour kind (regular, weekly_overtime, daily_overtime, travel, attendant, cash_advance) for employee then contractor: each the saved code, or HomeCareBilling's proposal with saved false. A fixed set, so not paged.
  • PUT /api/v1/payroll/earning-mappings, body {hour_kind, worker_type, earning_code, rate_code, file_column}, saves one slot as a row's Save does and answers it; a null or blank earning_code clears it back to its proposal. A refused field answers 422 validation_failed naming it.
  • Both are admin credentials only (403 forbidden) and answer 409 payroll_integration_off while the ADP payroll integration is off for the agency. MCP: list_payroll_earning_mappings, set_payroll_earning_mapping.

Added October 28, 2026 (Epic 101 contract-records walk, the signing state):

  • Every emergency information revision, intake notice, complaint, critical incident, monthly client report, Plan of Care and supervisory visit now carries its signing state, as its page shows it: signatures (the live signatures, oldest first), signed_at (null on a draft), signing_complete (true once every required line holds a signature; a signed record can be false) and missing_signers (each open line's roles and label). In GET /api/v1/clients/{id}/emergency-info, GET /api/v1/clients/{id}/consent-forms, GET /api/v1/consent-forms/{id}, GET /api/v1/complaints, GET /api/v1/complaints/{id}, GET /api/v1/critical-incidents, GET /api/v1/critical-incidents/{id}, GET /api/v1/monthly-client-reports, GET /api/v1/plans-of-care, GET /api/v1/plans-of-care/{id}, GET /api/v1/supervisory-visits and GET /api/v1/supervisory-visits/{id}, and wherever one is answered, the sign responses included. An incident signed on the office line alone lists the supervisor review in missing_signers; a Plan of Care signed by the supervisor alone lists the client or representative line; an in-person supervisory visit needs the supervisor, the client and the caregiver or PCP, a telehealth one the supervisor alone. MCP: the list, get and sign tools for each carry it too (list_supervisory_visits now lists each visit's signatures as well).
  • An emergency information revision also carries superseded: true for a draft older than a signed or amended revision of the same client, which will never be signed. It still deletes.
  • GET /api/v1/work-orders/{id}/monthly-report answers the report the Work Order month holds, with its answers and signing state; 404 for a Work Order with no report yet or of another agency. MCP: get_monthly_client_report.
  • An intake notice's signature items are now the shared RecordSignatureSummary schema (the same fields as before), and the complaint, critical incident and monthly report schemas gain the same four properties. The Plan of Care and supervisory visit schemas gain signed_at, signing_complete and missing_signers; their signatures items keep their own schemas.

Added October 28, 2026 (US-101.42, the missing-intake warning):

  • Every client now carries intake_missing in GET /api/v1/clients and GET /api/v1/clients/{id}: the intake forms the client page warns are not signed yet (agency_disclosure_notice, client_rights_acknowledgement, emergency_information), empty when the page shows no warning. It blocks nothing. MCP: get_client carries it too.
  • POST /api/v1/clients/{id}/intake-warning-dismissals, body {reason} (optional, at most 500 characters), dismisses it as the page's Dismiss does: 201 for the client's first dismissal, 200 when it replaces one. It shows again only when a form outside the stored missing_forms goes missing. MCP: dismiss_intake_warning.

Added October 28, 2026 (US-101.32, emergency information under the signed-record contract):

  • POST /api/v1/emergency-info/{id}/signatures, body {role}, records agency staff's signature (office) typed as the credential's user. The client's or authorized representative's line is drawn on the device in the app and answers 422 drawn_required here. MCP: sign_client_emergency_info.
  • Every emergency information revision now carries record_state (draft, signed, amended, voided) in GET /api/v1/clients/{id}/emergency-info and wherever a revision is answered.
  • DELETE /api/v1/emergency-info/{id} answers 409 record_locked for a signed, amended or voided revision and deletes nothing. A draft deletes as before.
  • client_emergency_info joins the record_type values the signed-record operations (addenda, void, history) accept.

Added October 28, 2026 (US-101.44, "Client can't sign" on a half-month summary):

  • With a caregiver session token: POST /api/v1/me/half-month-summaries/{id}/client-skip, body reason (one of the care log's client-skip reasons), records that the client could not sign the half. The caregiver's signed line then completes it, and its true copy is stored. 200 with HalfMonthSummary (client_skip_reason set); the same reason again answers it unchanged. 409 record_locked when the client's or a representative's line is signed or the half is already complete, 409 voided, 422 validation_failed for an unknown reason, and 404 for another caregiver's or another agency's summary. No MCP twin: MCP has no caregiver actor.

Added October 28, 2026 (US-101.29, the phone care logs left incomplete):

  • GET /api/v1/phone-care-logs/exceptions lists the live phone care logs with no task entered, a call that ended before it was finished, or no client attestation, as the Phone care logs screen does: each with its reasons and recording_document_id (the client's kept recording, if clean). Filters reason, from and to; paged by limit (default 25, at most 100) and offset. A log is listed 15 minutes after its call. MCP: list_phone_care_log_exceptions.
  • POST /api/v1/phone-care-logs/{id}/dismiss, body {reason}, takes a log off the list with why; the care log itself does not change. 201 with the dismissal, 200 with already_dismissed true when it was dismissed already, 404 for any care log that is not the agency's live phone care log. MCP: dismiss_phone_care_log_exception.

Added October 27, 2026 (Epic 101 contract-records area review):

  • GET /api/v1/print/work_order_report reads report, a monthly client report's id: it prints that report in any record state, a voided or signed one included, rather than the Work Order's live report. A report of another Work Order or another agency, or an id that is not one, answers 404. Left out, the print is unchanged.
  • A client's intake_missing counts an emergency information revision or intake notice only once every line its type requires is signed: an emergency information revision signed by the agency staff alone no longer clears it.

Added October 27, 2026 (US-101.33, the Chapter 26 intake notices):

  • GET /api/v1/clients/{id}/consent-forms lists a client's intake notices (the agency disclosure notice and the client rights acknowledgement), newest first, paged with limit (default 25) and offset. MCP: list_client_consent_forms.
  • POST /api/v1/clients/{id}/consent-forms, body {form_type}, starts a draft notice stamped with the agency's current wording and answers 201. A client has one open draft of each type: starting a second answers the open one. Every disclosure choice starts on its first option (Agency) and is listed in defaulted_keys until someone picks it. MCP: start_client_consent_form.
  • GET /api/v1/consent-forms/{id} and PATCH /api/v1/consent-forms/{id}, body {answers, lock_version}. A key sent counts as chosen and leaves defaulted_keys. A signed notice answers 409 record_locked, a stale lock_version 409 stale_record. MCP: get_client_consent_form, answer_client_consent_form.
  • POST /api/v1/consent-forms/{id}/signatures, body {role: "office"}, signs agency staff's line, typed as the calling member. It completes a rights acknowledgement; on a disclosure notice it needs declined_reason, which records that the client declined and the notice was conveyed verbally, both in one transaction. The client's and representative's lines are drawn on the device in the app and answer 422 drawn_required. MCP: sign_client_consent_form.
  • All: another agency's id answers 404 not_found before the body is judged. client_consent_form joins the record_types of /api/v1/signed-records/{record_type}/{id}/addenda, /void and /history, and the print is GET /api/v1/print/client_consent_form?id=&client_id=.
  • Under /consent-forms, not /consents: /api/v1/consents/{purpose} is the agency's data-sharing consent (US-92.2).

Added October 27, 2026 (US-92.18, paper capture, every action of the Paper inbox, its review and the upload control). Each operation but the last two answers 403 paper_capture_consent_required until an agency admin accepts the paper-forms disclosure in Settings; another agency's form, page or update answers 404.

  • POST /api/v1/paper-capture/scans uploads a photo or scan (multipart field file, up to 10 MB), from the record origin_target_kind and origin_target_id name or none, after the agency's reading credit is checked against its pages (422 insufficient_credit); 201 and the scan. MCP: upload_paper_scan.
  • POST /api/v1/paper-capture/scans/uploads answers a single-use slot, valid 30 minutes, for a file up to 25 MB. MCP: upload_paper_scan without file_base64.
  • PUT /api/v1/paper-capture/scans/uploads/{token} stores the slot's bytes once (409 upload_slot_used, 409 upload_slot_in_progress, 410 upload_slot_expired); an AI connection PUTs to /mcp/paper-capture/uploads/{token}.
  • GET /api/v1/paper-capture/forms lists the Paper inbox's forms, paged (limit default 50, at most 100), narrowed by status or by scan_id to one upload's forms, each with the actions the inbox offers, the scan it was read from and total_count. MCP: list_paper_forms.
  • GET /api/v1/paper-capture/forms/{id} answers the form as its review shows it: mode, rows, notes, the summary line, pages, candidates and draft_id. MCP: get_paper_form.
  • GET /api/v1/paper-capture/pages/{id}/image answers a URL for the page's image, valid 300 seconds, once the view is recorded; 410 image_removed after the 30-day purge. MCP: get_paper_page_image.
  • POST /api/v1/paper-capture/forms/{id}/target chooses the record, body {target_id}. MCP: choose_paper_form_target.
  • POST /api/v1/paper-capture/forms/{id}/form-type chooses an unprinted page's form type, body {form_key}, and reads it again. MCP: choose_paper_form_type.
  • POST /api/v1/paper-capture/forms/{id}/read reads the form, or reads it again. MCP: read_paper_form.
  • DELETE /api/v1/paper-capture/forms/{id} discards the form. MCP: discard_paper_form.
  • POST /api/v1/paper-capture/forms/{id}/apply applies the form, body {decisions: [{field, choice, value, shown_current}]} with choice accept, keep_current, blank or value: 409 stale with the rows as they are now, 422 needs_attention naming the field_ids. MCP: apply_paper_form.
  • POST /api/v1/paper-capture/forms/{id}/client chooses the client of a client sheet that matched none, body {client_id}. MCP: choose_paper_form_client.
  • POST /api/v1/paper-capture/forms/{id}/draft points the form at the draft that replaced its revised plan, body {draft_id}. MCP: retarget_paper_form_to_draft.
  • POST /api/v1/paper-capture/forms/{id}/merge joins the pages of from_form_id into the form, which then waits for a Read (US-92.19); a read already done on either form is discarded. 422 mismatch, duplicate_page or not_mergeable with the Paper inbox's sentence. MCP: join_paper_forms.
  • POST /api/v1/paper-capture/applications/{id}/undo undoes a paper update; open without the consent. MCP: undo_paper_application.
  • GET /api/v1/paper-capture/applications/latest answers the record's newest paper update not undone (target_kind, target_id), or null; open without the consent. MCP: get_latest_paper_application.

Added October 27, 2026 (US-101.38, DocuSign over the API):

  • GET /api/v1/settings/docusign reads the DocuSign settings as Settings > DocuSign shows them: the account a send goes through (account_kind agency, platform or null) with the platform's price, and under agency_connection the agency's own account (null when it never connected), with whether a Connect HMAC key is stored. No token and no key is ever answered. DELETE /api/v1/settings/docusign disconnects the agency's account; nothing to disconnect answers the same body. Admin credentials only (403 forbidden). MCP: get_docusign_settings, disconnect_docusign.
  • PUT /api/v1/settings/docusign/connect-hmac-key, body {hmac_key}, stores the agency's DocuSign Connect HMAC key, encrypted, and never shows it again; from then on a Connect delivery for the agency's envelopes is accepted only when signed with it. 422 not_connected with no current connection, 422 validation_failed for a key that is not 16 to 256 characters without spaces. DELETE /api/v1/settings/docusign/connect-hmac-key removes it. Admin credentials only. MCP: set_docusign_connect_hmac_key, remove_docusign_connect_hmac_key.
  • POST /api/v1/signed-records/{record_type}/{id}/docusign-envelopes, body {recipients} (optional; left out, the record's client and representative with an email on file), sends a draft record for signature as the record page's Send with DocuSign does and answers 202 with the envelope sending. Through HomeCareBilling's account it also answers price_microdollars and available_balance_microdollars, and too little credit answers 402 insufficient_credit with nothing written. 422 not_draft, envelope_open, not_connected, consent_required, no_recipients, invalid_email, missing_name, duplicate_role or role_not_allowed. An Idempotency-Key replay answers the first send. MCP: send_record_with_docusign.
  • GET /api/v1/signed-records/{record_type}/{id}/docusign-envelopes lists the record's envelopes, newest first, paged. MCP: list_docusign_envelopes.
  • On both envelope routes record_type is supervisor_visit or plan_of_care; any other type answers 404 not_found. Each envelope's recipients carry the signer's name, role and email.

Added October 27, 2026 (US-101.13, the agency's own DocuSign account):

  • GET, POST and DELETE /api/v1/consents/{purpose} accept the purpose docusign_agency: the disclosure an agency admin accepts before connecting the agency's own DocuSign account on /settings/docusign. Revoking it leaves a connected account connected; no account can be connected again until it is accepted. MCP: get_consent, accept_consent and revoke_consent take the same purpose.

Added October 27, 2026 (US-101.40, the caregiver app's care logs and the half-month summary):

  • With a caregiver session token: GET /api/v1/me/care-logs (your unfinished care logs, as the app's dashboard lists them; MeCareLog), GET /api/v1/me/care-logs/{id}, POST /api/v1/me/care-logs (body client_id, service_date, service_type, shift_number, visit_id; 201 new, 200 the live one of the day), POST /api/v1/me/care-logs/{id}/tasks/{task_id}/mark (the office mark's body plus expect_status), POST /api/v1/me/care-logs/{id}/finish, POST /api/v1/me/care-logs/{id}/attestation (the client's or a representative's base64 PNG, capture_method, role, signer_name, expected_content_hash) and POST /api/v1/me/care-logs/{id}/attestation-skip (reason, note). Each answers MeCareLogDetail: CareLogDetail plus signing_hash. Another caregiver's care log, another agency's, or one older than the app's reach is 404. Refusals: 403 care_log_not_enabled; 422 no_work_order, service_date_out_of_reach, task_not_on_log, visit_mismatch, invalid_image, validation_failed; 409 record_locked, content_changed, role_already_signed, voided, stale_record.
  • With a caregiver session token: POST /api/v1/me/half-month-summaries (body client_id, period_start) answers the live summary of the half or a new draft, and POST /api/v1/me/half-month-summaries/{id}/signatures (role caregiver, client or representative, a base64 PNG image, capture_method, signer_name, expected_content_hash) signs a line. Before the half's signing date it is 422 signature_period_not_reached; also 409 content_changed, role_already_signed, record_locked, voided, 422 invalid_image. A client the caregiver neither has an assignment with nor a care log for in the half is 404. No MCP twins: MCP has no caregiver actor.
  • GET /api/v1/half-month-summaries, with client_id, caregiver_id and period_start (the 1st or the 16th), answers a caregiver's half of a month for one client (HalfMonthSummary): its days, shifts and hours, record_state, signing (opens_on, open, hash, caregiver_signed, client_signed, complete) and live signatures, drafting the half when it has no summary. The read is on the PHI access log. MCP: get_half_month_summary.

Added October 27, 2026 (US-101.23, care logs reconciled with the visit evidence):

  • GET /api/v1/clients/{id}/evidence days carry care_logs (each with its source, times, attestation_method, attestation_skip_reason and its comparisons of kind care_log_times, care_log_tasks or attestation, with state, fields, conflict_key, only_care_log and only_work_order) and claim_changes (claims sent before a care log of the day changed). A care-log conflict's key is in open_conflict_keys and is dismissed through POST /api/v1/clients/{id}/evidence/dismissals as a visit conflict is; the bulk dismissal takes them too. MCP: get_client_month_evidence.
  • GET /api/v1/batches/{id}/revenue-warnings has a new kind, changed_after_claim: a care log addended or voided after its claim was sent. Every warning carries link, null except on that kind, where it opens the client-month evidence grid. Dismissed through POST /api/v1/revenue-warnings/dismissals like any other kind. MCP: list_batch_revenue_warnings.

Added October 27, 2026 (US-101.22, the Work Order assembled from care logs):

  • POST /api/v1/work-orders/{id}/fill-from-care-logs, body {lock_version}, fills the Work Order's day entries and task marks from the care logs of its client and caregiver in its month, as the Work Order page's Fill from care logs does, and answers 200 with filled, updated and unchanged days and differences and flagged (each {date, reason}). Entries and marks the office typed are kept and their days named in differences (warn, never block). A rerun with nothing changed writes nothing. Refusals: 404 not_found; 409 stale_record; 422 not_editable. A care log write also queues the same fill, so a Work Order in progress follows its care logs without the call. MCP: fill_work_order_from_care_logs.

Added October 27, 2026 (US-101.20, the client's attestation on the caregiver's phone):

  • GET /api/v1/care-logs and GET /api/v1/care-logs/{id} carry attestation_skip_reason (client_asleep_or_unwell, client_not_present, client_declined_to_sign, client_unable_to_sign or other), attestation_skip_note, attestation_skipped_at and attestation_skipped_by_caregiver_id: why the client did not sign, as the caregiver gave it with Client can't sign; all null when no reason was given. Read only: PATCH /api/v1/care-logs/{id} ignores them. MCP: list_care_logs and get_care_log.
  • GET /api/v1/care-logs takes needs_signature=true, the screen's Needs client signature box: only the care logs still awaiting the client's signature (drafts). MCP: list_care_logs (needs_signature, a boolean).

Added October 27, 2026 (US-101.39, the office's care logs):

  • GET /api/v1/care-logs lists care logs as the Care Logs screen does, newest day first, each with task_counts (done, refused, not_needed, unmarked), filtered by client_id, caregiver_id, from, to, source and state; limit defaults to 50. MCP: list_care_logs.
  • GET /api/v1/care-logs/{id} reads one care log with its tasks, times (the linked Visit's, else those entered), warnings and live signatures. MCP: get_care_log.
  • POST /api/v1/care-logs, body {client_id, caregiver_id, service_date, service_type, shift_number, visit_id}, starts a care log with source office: 201 when it is new, 200 with the live care log when the day already has one. 422 visit_mismatch. MCP: start_care_log.
  • POST /api/v1/care-logs/{id}/tasks/{task_id}/mark (task_id is the task's task_definition_id), body {status, reason_code, reason_note, count}, SETS a task's status; 422 task_not_on_log. MCP: mark_care_log_task.
  • POST /api/v1/care-logs/{id}/tasks, body {task_definition_id, status, count, reason_code, reason_note}, adds an unplanned task; 422 task_definition_not_found. MCP: add_care_log_task.
  • PATCH /api/v1/care-logs/{id}, body {lock_version, notes, time_in, time_out}; 409 stale_record. MCP: update_care_log.
  • POST /api/v1/care-logs/{id}/finish marks it finished, once. MCP: finish_care_log.
  • POST /api/v1/care-logs/{id}/paper-on-file records the client's paper signature as on file, which signs and locks the day: a multipart scan in file, or JSON {document_id} naming a document on the client's file, or neither. 201; 422 document_not_found; 409 role_already_signed. MCP: mark_care_log_paper_on_file (with document_id).
  • Every write on a care log that is not a draft answers 409 record_locked; another agency's id answers 404 whatever the body holds.
  • /api/v1/signed-records/{record_type}/... (addenda, void, history) and the MCP tools add_record_addendum, void_record and get_record_history take record_type care_log.

Added October 26, 2026 (US-101.31, complaints and critical incidents signed under the contract):

  • POST /api/v1/complaints/{id}/signatures, body {role: "office"}, signs the office investigator's line, typed as the calling member, and answers 200 and the complaint. The complainant's line (client or representative) is drawn on the device in the app, so those roles answer 422 drawn_required. MCP: sign_complaint.
  • POST /api/v1/critical-incidents/{id}/signatures, body {role}, signs office (reported by) or supervisor (supervisor review), typed as the calling member, and answers 200 and the incident. MCP: sign_critical_incident.
  • Both: the first signature locks the record. Refusals: 404 not_found (another agency's id, judged before the body); 409 stale_record, voided or content_changed; 422 already_signed, content_unreadable (the record's text cannot be read, so it cannot be signed) or validation_failed.
  • PATCH /api/v1/complaints/{id} and PATCH /api/v1/critical-incidents/{id} on a signed record take status alone; any other field answers 409 record_locked and nothing is written.
  • Complaints and critical incidents carry record_state: draft, signed, amended or voided, and complaint and critical_incident join the record_types of /api/v1/signed-records/{record_type}/{id}/addenda, /void and /history.

Added October 26, 2026 (US-101.30, the Monthly Client Report signed under the contract):

  • POST /api/v1/work-orders/{id}/monthly-report/signatures, body {signer: "office"}, signs the office attestation of the Work Order month's saved report, typed as the calling member (the staff member who conducted a phone or video check-in), and answers 200 and the report. The first signature locks the report. Refusals: 404 not_found (no report, or another agency's Work Order); 409 stale_record, voided or legacy_signed; 422 already_signed or validation_failed. MCP: sign_monthly_client_report.
  • POST /api/v1/work-orders/{id}/monthly-report on a signed report answers 409 record_locked: it is corrected with an addendum, or voided and started again as a new draft. A report the client signed before the electronic record still answers 422 client_signed.
  • The monthly client report (GET /api/v1/monthly-client-reports and the save) carries record_state: draft, signed, amended or voided.
  • monthly_client_report joins the record_types of /api/v1/signed-records/{record_type}/{id}/addenda, /void and /history.

Added October 26, 2026 (US-101.6, addenda, voids and history on signed records):

  • POST /api/v1/signed-records/{record_type}/{id}/addenda, body {body, reason, signer_name}, adds an addendum to a signed supervisory visit or Plan of Care (record_type supervisor_visit or plan_of_care) and signs it as the calling member, a typed signature, as the record page's Add addendum does; it answers 201 and the addendum, and the record reads amended. The same body and reason again within 60 seconds answers the addendum already made. Refusals: 404 not_found; 409 voided; 422 validation_failed or not_signed. MCP: add_record_addendum.
  • POST /api/v1/signed-records/{record_type}/{id}/void, body {reason}, voids a signed record, keeping it as signed, and answers 200 with its state. A voided current Plan of Care becomes past; its Work Orders are not changed. Admin credentials only (403 forbidden); 422 reason_required or not_signed; 409 voided. MCP: void_record.
  • GET /api/v1/signed-records/{record_type}/{id}/history lists the record's events oldest first, paged: signatures, voided signatures, the true copy stored, addenda, the void, and the record it replaces or that replaced it. MCP: get_record_history.
  • GET /api/v1/print/{form} for plan_of_care and supervisory_visit reads addenda_through: none prints no addenda, an addendum's id prints the record's addenda up to and including it; left out, the print carries every signed addendum after the record's own signatures, as it now does.

Added October 26, 2026 (US-101.5, the Plan of Care signed under the contract):

  • POST /api/v1/plans-of-care/{id}/signatures, body {signer_name}, signs the plan's supervisor line as the calling member, a typed signature, as the plan page's typed office signature does; it answers 201 and the plan. The plan's first signature keeps its consent wording and locks it. Refusals: 404 not_found; 409 stale_record, content_changed or voided; 422 validation_failed or already_signed. MCP: sign_plan_of_care.
  • POST /api/v1/plans-of-care/{id}/revise, body {reason}, voids a signed current plan, keeping it as signed, and answers 201 with the new current draft that replaces it (replaces_id). Admin credentials only (403 forbidden); 422 reason_required, not_signed or not_current; 409 voided. MCP: revise_plan_of_care.
  • A plan of care now reads record_state, replaces_id and signatures (each signature's role, signer_name, method and signed_at; never the image).

Added October 26, 2026 (US-101.11, the client-month evidence grid):

  • GET /api/v1/clients/{id}/evidence (caregiver_id, and month as YYYY-MM) answers the month the client's Visit evidence grid shows: every calendar day with its state (none, corroborated, single_source, conflict, conflict_dismissed), each source's visits and billable times, the keys of the day's open conflicts, and who dismissed each dismissed one, when and why. month defaults to this month (Mountain). The MCP tool get_client_month_evidence answers the same.
  • POST /api/v1/clients/{id}/evidence/dismissals (caregiver_id, month, reason of 3 to 500 characters) dismisses every conflict still open in the month under one batch, as the grid's Dismiss all does, and answers 201 with dismissed, how many; 0 when none was open. No visit changes. Another agency's client or caregiver answers 404 on both. The MCP tool dismiss_month_evidence_conflicts does the same.

Added October 26, 2026 (US-101.10, visit evidence conflicts):

  • POST /api/v1/evidence-dismissals (client_id, caregiver_id, service_date, conflict_key, reason of 3 to 500 characters) dismisses a time conflict between Sandata's record of a visit and the agency's own, as the visit page's Dismiss warning form does; neither visit changes. A new dismissal answers 201; one already dismissed 200 with already_dismissed true; a conflict_key that is no longer a conflict of that day 409 conflict_changed; another agency's client or caregiver 404. The MCP tool dismiss_evidence_conflict does the same.

Added October 26, 2026 (US-101.7, the legacy paper archive):

  • Documents take a new document_type, legacy_paper: an old scanned paper form in the client's paper archive. Two new fields, record_date (the date on the paper; a monthly form's is its month's first day) and paper_form_type (work_order, time_services_card, plan_of_care, monthly_client_report, supervisory_visit, cfc_calculator, intake_consent, complaint_incident or other, the default), are read on every document and written by POST /api/v1/clients/{id}/documents and PATCH /api/v1/documents/{id} on a legacy_paper scan; any other document ignores them. A legacy_paper scan is a PDF, JPEG or PNG on a client.
  • GET /api/v1/clients/{id}/documents takes the filters document_type, form_type, from and to (YYYY-MM-DD, compared with record_date). The MCP tools list_client_documents, upload_client_document and update_person_document take the same.

Added October 26, 2026 (US-101.12, the electronic evidence report):

  • GET /api/v1/reports/electronic-evidence (month as YYYY-MM, default the latest computed month; limit and offset page both tables) answers the share of worked client-days with electronic visit evidence for the 12 months ending with month, and for month per caregiver and per client, lowest share first, as the agency's Electronic Evidence page shows it. A month with no snapshot answers computed: false. The MCP tool get_electronic_evidence_report answers the same.

Added October 26, 2026 (US-101.9, Sandata visit import):

  • POST /api/v1/visit-imports (multipart: file, Sandata's Detail Visit Status export as CSV; dry_run) imports each row as a read-only visit beside the agency's own, as Import Sandata visits does. With dry_run true it answers 200 with the counts and unresolved rows and writes nothing (422 missing_columns, csv_parse_error, empty_file, too_many_rows, file_too_large for a file it cannot read); otherwise 202 with the run, queued. GET /api/v1/visit-imports/{id} reads the run; a run that stopped and was not resumed within 2 hours fails with abandoned. MCP: import_sandata_visits, get_visit_import.

Changed October 26, 2026 (US-101.9, imported visits are read-only):

  • A visit now carries import_system and import_external_id, set on an imported visit (source import) and null on the agency's own. PATCH /api/v1/visits/{id}, POST /api/v1/visits/{id}/transitions, POST /api/v1/visits/{id}/reassign and DELETE /api/v1/visits/{id} refuse an imported visit with 422 imported_visit, as do the MCP tools update_visit, transition_visit, reassign_visit and delete_visit. POST /api/v1/visits/bulk-verify and /bulk-cancel leave an imported visit unmoved and list it in failed with reason imported_visit, a value the VisitBulkTransitionResult enum now names.

Added October 26, 2026 (US-92.2, the paper-capture consent):

  • GET, POST and DELETE /api/v1/consents/paper_capture read, accept and revoke the agency's consent to read scanned forms with Anthropic's AI, as the Settings Paper forms tab does; admin credentials only. MCP: get_consent, accept_consent and revoke_consent with purpose paper_capture.

Changed October 26, 2026 (US-92.2, scans read only with that consent):

  • A CFC import or preview job for a scanned calculator (a PDF with no text layer, PNG, JPG or JPEG) now ends failed with error code paper_capture_consent_required, and is not retried, unless that consent is current. Spreadsheets, CSV files and PDFs with a text layer are unchanged.

Added October 24, 2026 (US-110.4, a claim's units from its EVV visits):

  • GET /api/v1/claims/{id}/evv-correction answers what billing the claim's verified EVV visit units would change: billed and EVV units, the charge now and at the same price per unit, the visits counted, the refusal applying would give (null when it would succeed) and the live correction.
  • POST /api/v1/claims/{id}/evv-correction, body {expected_billed_units}, sets an unsent claim's units and charge to those figures and answers the claim and the correction.
  • DELETE /api/v1/claims/{id}/evv-correction undoes it, answering the restored claim. Refusals: 409 changed_since or busy; 422 already_sent, batch_not_open, not_checkable, no_evv_units, no_difference, no_correction. MCP: get_claim_evv_correction, apply_claim_evv_correction, undo_claim_evv_correction.

Added October 24, 2026 (US-110.1, revenue at risk):

  • GET /api/v1/revenue-at-risk (within_days, 14 or 30, default 30; limit, offset) answers the revenue at risk in the window: the unused value of active, unrenewed PARs that end in it, plus the scheduled visits no PAR covers. The page is {data, limit, offset, total, summary}, and summary.truncated is true when the read reached its 500-PAR or 2,000-visit bound.
  • The MCP tool get_revenue_at_risk answers the same function.

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
  • visit.verified (added November 2, 2026)
  • claim.denial_withdrawn (added November 2, 2026)
  • caregiver.credential_expiring (added November 2, 2026)