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}andPOST /api/v1/service-areas/import-starter: the agency's service areas, the starter set added once (agency_settings.manageto change;open_shifts.viewto list).GET /api/v1/open-shifts,GET /api/v1/open-shifts/{id},POST /api/v1/open-shifts,PATCH /api/v1/open-shifts/{id}andPOST /api/v1/open-shifts/{id}/cancel: post, read, change and cancel a shift that needs a caregiver (open_shifts.manage;open_shifts.viewto 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 422client_info_founduntil the request repeats withacknowledgedholding the finding's fingerprint. New refusals: 409open_shifts_off,open_shift_closed,open_shift_assignedandslot_already_posted(withopen_shift_id), and 422no_shift_plan,not_a_run_dayandclient_info_found.POST /api/v1/open-shifts/cross-streets: the cross streets nearest a client's stored point, or 422cross_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) andoffset. Needsopen_shifts.manage: a view-only credential answers 403.home_areais answered only to a holder ofopen_shifts.administer.GET /api/v1/open-shiftsand the MCP toollist_open_shiftstakefilter=with_responses(at least one live response) andfilter=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 withdata.open_shift,data.notes(who takes the slot from the next Generate, who keeps the current Work Order) anddata.shift_plan_path. A schedule clash, a posted rate that differs from the caregiver's pay rate and a start that has passed arewarnings(open_shifts.schedule_clash,open_shifts.rate_differs,open_shifts.start_passed); none refuses. Needsopen_shifts.manage. A caregiver who did not respond is accepted while the agency'sapi_may_assign_non_responderis on. New refusals: 422not_a_responderandcaregiver_not_active; 409open_shift_assigned,open_shift_closedand 422no_shift_planas 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 toopenand 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 aopen_shifts.needs_attentionwarning. 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 withdata.open_shift. Needsopen_shifts.manage. New refusal: 409open_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_statusandtext_status_detail: the first that holds ofno_cell_phone,opted_out(they replied STOP; the detail is that day),no_consent,not_verifiedandphone_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), elsecan_text. Sent in a write, both are ignored. GET /api/v1/caregiverstakestext_status: one of those values, orcannot_textfor every value butcan_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 toolsupdate_caregiverandupdate_caregiver_status: a move frompotentialtoactivenow answers two warnings, never a refusal.workforce.onboarding_open_itemsnames the employee file items still open;workforce.no_employee_idsays 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 OIGrescreenjob, as it did before. The response shape is unchanged: the warnings arrive inwarnings.
Added November 9, 2026 (US-122.25, the open-shifts dashboard):
GET /api/v1/open-shifts/dashboard(getOpenShiftsDashboard): with nosection,data.counts(open,open_no_responses,assigned_upcoming,paused) anddata.coverage(per service area: open and unanswered shifts and how many people have it in reach). Withsectionone ofnot_responding,onboarding,pauses,activityoralerts_sent, that list'srowsandtotal, paged bylimitandoffset;alerts_senttakesstatus(pending,sending,sent,failed,unknown,skipped). Needsopen_shifts.administer. New refusals: 422invalid_sectionandinvalid_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 tocompleted; its Shift Plan pick and Visit stay. Before the shift's start it is refused 409not_startedwhile the agency'scomplete_before_startis off. Answers 200 withdatathe shift. Needsopen_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 iscancelledwith outcomeno_show, its responders and the assignee are told, and the assignee gets one strike. Strikes in the agency'sstrike_window_daysreachingstrikes_before_pausepause the caregiver from responding to open shifts forpause_days; sign-in, clock-in and EVV are never paused. Before the start: 409not_started. Needsopen_shifts.manage.POST /api/v1/caregivers/{id}/restore-open-shift-access(postCaregiversByIdRestoreOpenShiftAccess): clears the pause and voids every strike in one transaction. Answers 200 withdata.caregiver_id,data.voidedanddata.lifted(false when there was nothing to lift). Needsopen_shifts.administer.- New refusals, each 409:
not_assigned(a shift that is not assigned, a second complete or no-show included) andnot_started. A caregiver's late cancel (US-122.14c) now records a strike too.assignwarnsopen_shifts.caregiver_pausedfor 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) andPOST /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 sourceofficewhen the day has none, and no longer on the Work Order. They needtimesheets.managewhere they neededwork_orders.manage: a key without it answers 403forbidden, even one holdingwork_orders.manage. A combined Work Order (servicelegacy) keeps its own marks and still needswork_orders.manage.- Both answer 409
frozenfor a day a submitted, approved or exported Returned Timesheet holds, themessagenaming the Timesheet's month and status anddetailsthe Timesheet; it answers again once that Timesheet is back in draft. The PUT answers 409record_lockedwhen the day's care log is signed. - The answer is the care log's mark:
idis itscare_log_tasksid (null whencompleted: nullmet a day with no mark),completedis true fordoneand false fornot_neededorrefused, andnotesis its reason.completed: falseis stored asnot_needed, andcompleted: nullclears the mark. An unplanned task is stored asdonewith thenotesas its reason. A combined Work Order answers its own row, as before. - The MCP tools
toggle_work_order_taskandadd_unplanned_taskneedtimesheets.managetoo, 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, onGET /api/v1/work-ordersandGET /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_inandtime_outare the care log's Mountain times, so a night'stime_outis earlier than itstime_in;hours_workedis 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 MCPfind_work_ordersnow answers each Work Order'sentriesasget_work_orderdoes. - A combined Work Order (service
legacy) answers every row recorded on it as itsentries, 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}answersfindings, once the import has ended: a list of VisitImportFinding (row,rule_id,message,care_log_id,service_date,timesheet_id,status,period), today onlycare_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 MCPget_visit_importanswers it too.- An unresolved row's
reasoncan beno_work_order_for_code(no Work Order of the client and caregiver bills the visit's code) ordelivery_failed(the visit was saved but its care log was not; import the file again). care_logs.imported_for_billed_dayjoins thecodevalues of a care log'swarnings(CareLogWarning, CareLogDetail, MeCareLogDetail).
Changed November 8, 2026 (US-118.36, US-118.37, #3945, delivered-day warnings):
POST /api/v1/me/care-logs/{id}/tasksandPOST /api/v1/me/care-logs/{id}/tasks/{task_id}/markadd the findings the write raised (care_logs.over_weekly_limitand the like) to the care log'swarnings. Warnings, never refusals.- A Timesheet entry write's
warningscan holdtimesheets.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}/applylists incare_log_warnings, for either card, each day whose delivery another source recorded (kindrecorded): 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/prospectsandPATCH /api/v1/prospects/{id}keeplanguagesfor 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'slanguage_preference. The MCP toolscreate_prospectandupdate_prospectdo 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 withinserted_at,user_name("System" when no member is recorded) andchanged_fields, never an old or new value. A contact holding no relation to the client answers 404. The MCP toolget_contact_historydoes the same.
Added November 8, 2026 (US-120.19, a client's people):
GET /api/v1/clients/{id}/relationslists 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;kindnarrows to one.POST /api/v1/clients/{id}/relationsrelates a person bycontact_idor a newcontact, answering 201 with the relation andwarnings. Replacing a responsible party, representative, case manager, supervisor or CMA office names the current relation inreplaces(id,lock_version); without it, or naming one no longer current, it answers 409stale_record.POST /api/v1/clients/{id}/relations/{relation_id}/endends a relation, today when noends_onis sent; one already ended answers unchanged.GET /api/v1/contactsfinds contacts by name or organization,GET /api/v1/contacts/{id}reads one andPATCH /api/v1/contacts/{id}edits one at itslock_version. A contact is seen only through a client the caller may open.- The MCP tools
list_client_relations,set_client_relation,end_client_relationandfind_contactsdo the same. - Deprecated: the Client's
emergency_contact_nameandemergency_contact_phone("Deprecated: use /api/v1/clients/{id}/relations. Served until 2027-05-31."), now read from the client's emergency contact 1, and MCPcreate_client'sresponsible_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 contactsloser_idsnames (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 withrelation_idsandclient_ids. 422invalidfor an empty or oversized list, 404not_foundfor a contact not this agency's or already merged, 403 withoutclients.manage, 409stalewhen another write got there first. The MCP toolmerge_contactsdoes 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, writeswork_orders.manage, template and list writesagency_settings.manage, and provider type modifier and procedure code writesbilling.manage, each refused with 403forbiddenanddetails.permission.POST /api/v1/work-orders/{id}/duplicatewithmodeno longer answers 403duplicate_not_permitted; a key whose member's roles grantwork_orders.managemay 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-caregiverand thechange_work_order_caregiverMCP tool give a Work Order to another caregiver from a date, as the page's Change caregiver does. The body is aWorkOrderChangeCaregiver:caregiver_id,from(YYYY-MM-DD) andlock_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 asdataandwarnings. Refusals: 422same_caregiver(already this Work Order's caregiver), 422work_order_archived, 409 on a stalelock_version, 403forbiddenwithoutwork_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-importtakes InMyTeam's weekly schedule, printed to PDF, as the multipart fieldfile(at most 10 MB) and imports it as Import Assignments does, inside the request. It answers 200 with aScheduleImportResult:dry_run,week_startanditems, each withrow,client,caregiver,service,outcome(new,changed,unchanged,not_imported,not_on_schedule),days_before,days_after,reasonandwarnings; a real run addsimported,updated,skipped,failed(each{row, errors}),reasonsandwarnings.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 asalready_on_file. It needsimports.manageandscheduling.manage(403forbiddenwithdetails.permission); 422not_a_schedule,unreadable_pdf,file_required,file_too_large,invalid_dry_runwrite nothing.
Added November 3, 2026 (US-121.7, client, caregiver and PAR imports):
POST /api/v1/clients/import,POST /api/v1/caregivers/importandPOST /api/v1/authorizations/importimport a file sent ascsv(text) orcsv_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 aRecordImportResult:dry_run,format(hcb,inmyteam_patients,inmyteam_caregivers,inmyteam_authorizations),imported,updated,skipped,failed(each{row, errors}) andreasonsby code; the caregiver import addspay_withheld, the rows whose pay was left out for a key withoutpayroll.manage.dry_runtrue 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 asalready_on_file. They needimports.manage, and the PAR importauthorizations.managetoo (403forbiddenwithdetails.permission); 422file_required,empty_file,too_many_rows,csv_parse_error,invalid_dry_run, and for the PAR importnot_an_authorization_export. MCP:import_clients,import_caregiversandimport_authorizationsanswer the same.
Changed November 3, 2026 (US-121.11, overnight schedule rows):
PUT /api/v1/assignments/{id}/schedule: a day may carry an optional booleanends_next_day(default false) for a shift that ends after midnight, such as 22:30 to 00:30. A day whoseend_timeis before itsstart_timewithout it answers 422invalid_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 carriesends_next_day, and an overnight day'shourscount past midnight (22:30 to 00:30 is 2.0). MCP:save_assignment_scheduleandget_assignment_scheduletake and return it the same way.
Added November 3, 2026 (US-121.8, EVV rollout):
GET /api/v1/settings/evv-collectionreads the agency's EVV rollout (evv_rollout:off,pilotorall), 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-collectionsets either field; a rollout outside the three, or a start day that is not a date, answers 422validation_failedand stores nothing. Admin keys only (403forbiddenotherwise). MCP:get_evv_collectionandupdate_evv_collection.GETandPATCH /api/v1/caregivers/{id}carryevv_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,POSTandPATCH /api/v1/authorizationsand/api/v1/authorizations/{id}, and every other answer carrying aServiceAuthorization:weekly_hoursandweekly_units, decimal strings derived on every read from the PAR's total and dates (inclusive days / 7, to two places).weekly_hoursis 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_authorizationsandpar_units_remainingreturn them the same way.POST /api/v1/recurring-schedules,PATCH /api/v1/recurring-schedules/{id},POST /api/v1/recurring-schedules/{id}/linesandPATCHandDELETE /api/v1/recurring-schedules/{id}/lines/{line_id}: aRecurringLineWarningcodemay beover_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 carriesauthorization_id, the PAR anover_weekly_allowancewarning 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}/applyneeds, besidesclients.manage, the target record's own permission: a Work Orderwork_orders.manage, a timesheettimesheets.manage, a Plan of Care or supervisory visitcare_plans.manage; a Time and Services Card also needstimesheets.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, 422invalid_decisions,not_ready,no_target) are answered first. Without it the apply answers 403forbiddenwithdetails.permissionnaming what is missing, and writes nothing. MCP:apply_paper_formrefuses the same way.POST /api/v1/paper-capture/applications/{id}/undoneeds what applying did: besidesclients.manage, the target record's permission as above. Without it the undo answers 403forbiddenwithdetails.permission, and restores nothing. MCP:undo_paper_applicationrefuses the same way.
Changed November 2, 2026 (#3683, remittance matching has no cap):
GET /api/v1/remittances/{id}:completeis false only for a remittance with no parse (nullreconciliation, nolines). A parsed remittance is matched against every one of the agency's claims, so it always answers true, and a line's nullclaim_idmeans it matched none of them, never that matching stopped early. The descriptions ofcompleteand of a line'sclaim_idsay 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.dataiscaregiver_id,credential(criminal_background_expiry,dora_expiry,caps_expiry,driver_license_expiryormain_training_expiry),expires_onandlead(monthorweek). 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 whoseclaim.deniedfor that claim was delivered.datais the denial'sclaim_id,batch_id,response_idandpayment_status_code, pluswithdrawn_event_id, the id of theclaim.deniedit withdraws. No order is promised between it and a laterclaim.deniedof 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). Itsdatacarriesvisit_id,client_id,caregiver_idandstatusonly; 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/videosandGET /api/v1/university/videos/{slug}: the narrated training videos in the order/universityshows 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; 404not_foundfor a slug the catalog does not list. The MCP toolslist_university_videosandget_university_videoanswer the same.
Added November 1, 2026 (US-117.6, one store for dismissed warnings):
POST /api/v1/finding-dismissalsdismisses any warning by itsrule_id,subject_type,subject_id(andsubject_datefor a warning about one day), thefingerprintit was listed with, itscontextand, where its rule asks why, areasonof 3 to 500 characters; it answers 201 with theFindingDismissal, the same one again for a warning already dismissed at those figures.POST /api/v1/finding-dismissals/{id}/restoreshows it again and answers 200 with the dismissal, kept, itsrestored_atset. Refusals: 409stale_findingwhen the fingerprint is not the warning's current one; 422unknown_rule,not_dismissibleandreason_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 toolsdismiss_findingandrestore_findinganswer the same functions.POST /api/v1/revenue-warnings/dismissalsnow answers 409stale_findingwhen the fingerprint is not the warning's current one (its figures changed since it was listed), and writes nothing.DELETEon 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, thenstatuspauses, resumes or ends it),POST /api/v1/recurring-schedules/{id}/lines,PATCH /api/v1/recurring-schedules/{id}/lines/{line_id}(statuspauses 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}/holdandPOST /api/v1/recurring-runs/{id}/rerun. A write answers the record and awarningsarray, which never blocks it. Every write and the proposal needhcb.submitand full access: 403insufficient_scope,read_onlyorsubmission_blockedotherwise. Refusals use the schedule page's words: 409run_status,period_moved(with the schedule'snext_period),schedule_exists,stale_record; 422batch_in_progress,schedule_ended,nothing_to_bill,no_submission_access,patient_limit_exceeded. The MCP toolspropose_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_runandrerun_recurring_periodrun 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 itsidanddeleted_at. The plan leavesGET /api/v1/plans-of-careand every other read; the audit trail keeps it. A signed plan answers 422plan_signed: void it first. Deleting a current plan leaves its service with no current plan. The MCP tooldelete_plan_of_caredoes the same.
Added October 30, 2026 (#3362, a client's calendar):
GET /api/v1/clients/{id}/calendar-eventslists a client's calendar events as the client's Calendar tab does, earliest due first, future events included;open=upcomingoropen=overduenarrows it to the open ones due today or later, or past their date. Any event it lists can be closed withPOST /api/v1/reminders/{id}/completeor/dismiss. The MCP toollist_client_calendar_eventsanswers 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_personto an agency API key (hcb_key_), before the record is looked up:POST .../signatureson 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, andPOST /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}/tasksadds 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 (422task_not_on_log) now points the caregiver token at this route.- A care log's
warningsmay holdtimes_missing: no Visit is linked and the time in or time out is empty, so the day counts 0 hours. Itstask_definition_idis null. A warning only; nothing refuses on it. POST /api/v1/care-logs/{id}/paper-on-fileanswers 422invalid_scanfor 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. Adocument_idwhose virus scan has not finished answers 409scan_pending, and one the scan found infected or could not scan answers 422scan_not_clean.POST /api/v1/me/care-logs/{id}/attestation-skipwith an unknownreasonnow names the reasons that are allowed in its 422.
Changed October 30, 2026 (US-101.47, DocuSign sends the contract records):
POSTandGET /api/v1/signed-records/{record_type}/{id}/docusign-envelopestakeclient_consent_form,client_emergency_infoandmonthly_client_reportasrecord_type, besidesplan_of_careandsupervisor_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 422role_not_allowed.complaintandcritical_incidentstay unsupported and answer 404not_found. The MCP toolssend_record_with_docusignandlist_docusign_envelopestake the samerecord_typevalues.
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. 422validation_failednames the rule (a UUID; a secret of 8 to 256 characters without spaces), never the value.DELETE /api/v1/settings/docusign/own-keyremoves 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(andget_docusign_settings) answerown_key_setandown_key_set_at.
Changed October 29, 2026 (#3319, the authenticator code kept out of logs):
PUT /api/v1/settings/securitytakes the authenticator code asotp_code.codeis deprecated: it is still read whenotp_codeis absent, until April 30, 2027. The MCP toolupdate_security_settingstakes the same arguments.
Changed October 29, 2026 (care-log epic area fix, half-month):
POST /api/v1/me/half-month-summaries/{id}/client-skipanswers 409caregiver_not_signedon 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-logslists indifferences, ordered by date, each day an office-set mark or a date marked not worked kept the fill from writing; thereasonof 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-ticketstakes optionalscreen,record_ids,steps_to_reproduce,expected,actualandfollow_up_id. A bug report missing what the server cannot work out from the user's recent activity answers 422needs_more_infoand files nothing: itsdetailsname themissingitems, thequestionsto ask the user, and afollow_up_id. Send the request again with the answers and thatfollow_up_id; it files the request whatever is still missing, once however often it is sent. Afollow_up_idthe server did not give that user in that agency is asked again like a first call.- A
record_idsthat is not up to 10 record ids, "any" or "don't know" answers 422invalid_record_ids; afollow_up_idthat is not an id answers 422invalid_follow_up_id.
Added October 29, 2026 (US-111.20, the SFTP drop's port):
PUT /api/v1/payroll/connection/sftptakesport, an integer 1 to 65535 or the empty string (the schema'soneOf); absent or null keeps the saved one, the empty string clears it, and none saved connects on 22. Another value answers 422invalid_port. A new host or port forgets the trusted server key. MCPset_payroll_sftptakes it too.- The connection's
settingscarriessftp_port, null when unset.
Added October 29, 2026 (US-111.24, Add to ADP):
POST /api/v1/caregivers/{id}/adp-hiresends 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) orunconfirmed(ADP did not answer). New answers: 409hire_push_off(not RUN, orallow_hire_pushoff), 409already_linked(an ADP worker or an open send), 422hire_refused, 502adp_unreachable. Agency-admin only, at full access (403submission_blocked, 403read_only). MCP:add_caregiver_to_adp.DELETE /api/v1/caregivers/{id}/adp-hireis "I checked RUN: not there": it clears anunconfirmedorpending_in_adpsend (409hire_not_abandonableotherwise), at full access or while billing blocks submission (403read_onlyonly). MCP:add_caregiver_to_adpwithnot_in_run: true, at the same levels.PATCH /api/v1/payroll/connectiontakesallow_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-codeanswers 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 (403forbiddenotherwise); 409payroll_integration_offwhile connecting through ADP Marketplace is off for the agency. Issued only where the tab offers one, changing nothing otherwise: 409marketplace_not_offeredunless the connection's ADP is RUN and HomeCareBilling's ADP Marketplace listing is set; 409already_connectedwhile 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. Filterstypes,service_type,caregiver_id,fromandto;limit(default 50, at most 200) andoffset. Another agency's client is 404; a filter it cannot read is 400 naming it. The MCP toolget_client_chartanswers the same.
Changed October 29, 2026 (care logs meet the contract records):
GET /api/v1/print/care_logreadsaddenda_throughas 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}: therecord_typedescription, andrecord_typeonRecordAddendumandSignedRecordState, 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 unknownrecord_type's 404 names them too. No type was added or removed.POST /api/v1/care-logs/{id}/paper-on-filewith adocument_idtakes 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 422document_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/loglogs the client's open monthly follow-up as the Log form of Operations > Follow-Ups does:contact_typeandcontact_date(not in the future), and optionalnotes. A client with nothing open is 422no_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/sftpsaves the SFTP drop'shost,user,folderandprivate_keyas 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 422invalid_private_key. MCPset_payroll_sftpdoes 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, andsettings.sftp_host_key_fingerprint, the server key trusted at the first successful Test connection;secrets_set.sftp_private_keysays whether a key is saved. The key itself is never answered. POST /api/v1/payroll/connection/testtests the SFTP drop on an:sftp_dropconnection: it signs in, lists the folder and answers "Connected. {folder} holds {count} files." or which step failed.POST /api/v1/payroll-exports/{id}/submissionson an SFTP drop connection uploads the export's Workforce Now paydata file once; withresend: trueafter ADP holds the file it answers 409not_replaceable.
Changed October 28, 2026 (US-111.12, Test connection):
POST /api/v1/payroll/connection/testanswers 409not_api_connectionand 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. MCPtest_payroll_connectionrefuses with the same sentence.
Added October 28, 2026 (US-111.18, connection health):
GET /api/v1/payroll/connection(and PATCH's answer) carrieshealth:status,last_success_at,last_failure_at,consecutive_failures,certificate_expires_at,status_reason(token_refused,circuit_open,certificate_expired,method_pausedor Test connection's code),message(the reconnect banner's sentence) andpaused_until(while HomeCareBilling has paused calls to ADP). MCPget_payroll_connectionanswers the same.
Added October 28, 2026 (US-111.17, Fix and resend):
POST /api/v1/payroll-exports/{id}/submissionstakes an optional body:resend: truereplaces what ADP holds as "Fix and resend" on /payroll-exports does, superseding the earlier send, andchoices(per caregiver id,replaceorkeep) answers a 409needs_choice, whosedetails.linesgive 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 withunchanged: true. New answers: 409resend_required(the hours changed after a send ADP holds lines of), 409awaiting_confirmation, 409export_exported, 502read_back_failed. MCP:send_payroll_exporttakesresendandchoices, and answersneeds_choicewith the same lines.
Added October 28, 2026 (US-111.15, Send to ADP):
POST /api/v1/payroll-exports/{id}/submissionssends 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. 422unsendable(with the findings) when the check finds it cannot be sent, 422not_sendable_statuswhen it is not generated (or was regenerated or marked downloaded while the send was being built), 403submission_blockedorread_onlyfor an agency whose HomeCareBilling billing pauses sending, 403insufficient_scopefor a grant withouthcb.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/syncqueues 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 (403forbiddenotherwise); 409payroll_integration_offwhile the API connection is off and 409not_api_connectionwhile the agency sends payroll by file or SFTP. MCP:sync_payroll_codes.POST /api/v1/payroll-exports/:id/checkcan 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_leaveandrate_differs.
Added October 28, 2026 (US-111.13, ADP workers and their caregivers):
GET /api/v1/payroll/workerspages the ADP workers of the agency's API connection beside their caregivers (filterall, 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}, andDELETE /api/v1/payroll/workers/{id}/linklink and unlink as /payroll/workers does; 409already_linkedorcaregiver_already_linkedwhen the worker or the caregiver is taken.POST /api/v1/payroll/workers/syncqueues a read of every ADP worker and answers{queued: true}. All four are agency-admin only (403forbiddenotherwise), answer 409payroll_integration_offwhile the API connection is off and 409not_api_connectionwhile the agency sends payroll by file or SFTP. MCP:list_payroll_workers,link_payroll_worker,unlink_payroll_worker(argumentpayroll_worker_id),sync_payroll_workers.
Added October 28, 2026 (US-111.12, the ADP API Central connect flow):
POST /api/v1/payroll/connection/csrmakes 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 asGET /api/v1/payroll/connectiondoes. A certificate that is not one, was not signed for HomeCareBilling's request or current key, or has expired answers 422invalid_certificatewith the sentence Settings > Payroll shows, and nothing is saved.POST /api/v1/payroll/connection/testmakes one read at ADP and answers{connected, message}, the sentence the tab shows. All three are agency-admin only (403forbiddenotherwise) and answer 409payroll_integration_offwhile 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/connectionanswers 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_atandsecrets_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 namingrun_company_code; a method not offered for the product storesfile, andnoticesays so. Both are agency-admin only (403forbiddenotherwise) and answer 409payroll_integration_offwhile the integration is off, except a PATCH turningenabledon when the platform and the plan allow it. MCP:get_payroll_connection,update_payroll_connection.GET/PATCH /api/v1/settings/adpare unchanged.
Added October 28, 2026 (US-111.6, ADP-format import files):
GET /api/v1/payroll-exports/{id}/filetakes an optionalformatquery parameter.adp_importanswers 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, fileMonthly-03012026-03312026.csvand 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_sheetanswers the RUN sheet the office types from (Entry sheet (to type from)). A format answers 409payroll_integration_offwhile 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 422unknown_file_formatfor another value. Withoutformatthe answer is unchanged. Any member at every access level. MCP:get_payroll_export_filetakes the sameformat.
Added October 28, 2026 (US-111.5, the pre-send payroll check):
POST /api/v1/payroll-exports/{id}/checkanswers{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.codeis an enum naming the rule, RUN'srate_codes_assumedandtoo_many_ratesamong 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 404not_found; 409payroll_integration_offwhile 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-mappingslists the twelve ADP earning-code slots/payroll/earningsshows, every hour kind (regular,weekly_overtime,daily_overtime,travel,attendant,cash_advance) foremployeethencontractor: each the saved code, or HomeCareBilling's proposal withsavedfalse. 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 blankearning_codeclears it back to its proposal. A refused field answers 422validation_failednaming it.- Both are admin credentials only (403
forbidden) and answer 409payroll_integration_offwhile 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) andmissing_signers(each open line'srolesandlabel). InGET /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-visitsandGET /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 inmissing_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_visitsnow 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-reportanswers 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
RecordSignatureSummaryschema (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 gainsigned_at,signing_completeandmissing_signers; theirsignaturesitems keep their own schemas.
Added October 28, 2026 (US-101.42, the missing-intake warning):
- Every client now carries
intake_missinginGET /api/v1/clientsandGET /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_clientcarries 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 storedmissing_formsgoes 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 422drawn_requiredhere. MCP:sign_client_emergency_info.- Every emergency information revision now carries
record_state(draft,signed,amended,voided) inGET /api/v1/clients/{id}/emergency-infoand wherever a revision is answered. DELETE /api/v1/emergency-info/{id}answers 409record_lockedfor a signed, amended or voided revision and deletes nothing. A draft deletes as before.client_emergency_infojoins therecord_typevalues 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, bodyreason(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 withHalfMonthSummary(client_skip_reasonset); the same reason again answers it unchanged. 409record_lockedwhen the client's or a representative's line is signed or the half is already complete, 409voided, 422validation_failedfor 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/exceptionslists 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 itsreasonsandrecording_document_id(the client's kept recording, if clean). Filtersreason,fromandto; paged bylimit(default 25, at most 100) andoffset. 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 withalready_dismissedtrue 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_reportreadsreport, 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_missingcounts 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-formslists a client's intake notices (the agency disclosure notice and the client rights acknowledgement), newest first, paged withlimit(default 25) andoffset. 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 indefaulted_keysuntil someone picks it. MCP:start_client_consent_form.GET /api/v1/consent-forms/{id}andPATCH /api/v1/consent-forms/{id}, body{answers, lock_version}. A key sent counts as chosen and leavesdefaulted_keys. A signed notice answers 409record_locked, a stalelock_version409stale_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 needsdeclined_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 422drawn_required. MCP:sign_client_consent_form.- All: another agency's id answers 404
not_foundbefore the body is judged.client_consent_formjoins therecord_types of/api/v1/signed-records/{record_type}/{id}/addenda,/voidand/history, and the print isGET /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/scansuploads a photo or scan (multipart fieldfile, up to 10 MB), from the recordorigin_target_kindandorigin_target_idname or none, after the agency's reading credit is checked against its pages (422insufficient_credit); 201 and the scan. MCP:upload_paper_scan.POST /api/v1/paper-capture/scans/uploadsanswers a single-use slot, valid 30 minutes, for a file up to 25 MB. MCP:upload_paper_scanwithoutfile_base64.PUT /api/v1/paper-capture/scans/uploads/{token}stores the slot's bytes once (409upload_slot_used, 409upload_slot_in_progress, 410upload_slot_expired); an AI connection PUTs to/mcp/paper-capture/uploads/{token}.GET /api/v1/paper-capture/formslists the Paper inbox's forms, paged (limitdefault 50, at most 100), narrowed bystatusor byscan_idto one upload's forms, each with the actions the inbox offers, the scan it was read from andtotal_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 anddraft_id. MCP:get_paper_form.GET /api/v1/paper-capture/pages/{id}/imageanswers a URL for the page's image, valid 300 seconds, once the view is recorded; 410image_removedafter the 30-day purge. MCP:get_paper_page_image.POST /api/v1/paper-capture/forms/{id}/targetchooses the record, body{target_id}. MCP:choose_paper_form_target.POST /api/v1/paper-capture/forms/{id}/form-typechooses 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}/readreads 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}/applyapplies the form, body{decisions: [{field, choice, value, shown_current}]}withchoiceaccept,keep_current,blankorvalue: 409stalewith the rows as they are now, 422needs_attentionnaming thefield_ids. MCP:apply_paper_form.POST /api/v1/paper-capture/forms/{id}/clientchooses the client of a client sheet that matched none, body{client_id}. MCP:choose_paper_form_client.POST /api/v1/paper-capture/forms/{id}/draftpoints 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}/mergejoins the pages offrom_form_idinto the form, which then waits for a Read (US-92.19); a read already done on either form is discarded. 422mismatch,duplicate_pageornot_mergeablewith the Paper inbox's sentence. MCP:join_paper_forms.POST /api/v1/paper-capture/applications/{id}/undoundoes a paper update; open without the consent. MCP:undo_paper_application.GET /api/v1/paper-capture/applications/latestanswers 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/docusignreads the DocuSign settings as Settings > DocuSign shows them: the account a send goes through (account_kindagency,platformor null) with the platform's price, and underagency_connectionthe 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/docusigndisconnects the agency's account; nothing to disconnect answers the same body. Admin credentials only (403forbidden). 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. 422not_connectedwith no current connection, 422validation_failedfor a key that is not 16 to 256 characters without spaces.DELETE /api/v1/settings/docusign/connect-hmac-keyremoves 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 answersprice_microdollarsandavailable_balance_microdollars, and too little credit answers 402insufficient_creditwith nothing written. 422not_draft,envelope_open,not_connected,consent_required,no_recipients,invalid_email,missing_name,duplicate_roleorrole_not_allowed. An Idempotency-Key replay answers the first send. MCP:send_record_with_docusign.GET /api/v1/signed-records/{record_type}/{id}/docusign-envelopeslists the record's envelopes, newest first, paged. MCP:list_docusign_envelopes.- On both envelope routes
record_typeissupervisor_visitorplan_of_care; any other type answers 404not_found. Each envelope'srecipientscarry the signer'sname,roleandemail.
Added October 27, 2026 (US-101.13, the agency's own DocuSign account):
GET,POSTandDELETE /api/v1/consents/{purpose}accept the purposedocusign_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_consentandrevoke_consenttake 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(bodyclient_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 plusexpect_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) andPOST /api/v1/me/care-logs/{id}/attestation-skip(reason,note). Each answersMeCareLogDetail:CareLogDetailplussigning_hash. Another caregiver's care log, another agency's, or one older than the app's reach is 404. Refusals: 403care_log_not_enabled; 422no_work_order,service_date_out_of_reach,task_not_on_log,visit_mismatch,invalid_image,validation_failed; 409record_locked,content_changed,role_already_signed,voided,stale_record. - With a caregiver session token:
POST /api/v1/me/half-month-summaries(bodyclient_id,period_start) answers the live summary of the half or a new draft, andPOST /api/v1/me/half-month-summaries/{id}/signatures(rolecaregiver, client or representative, a base64 PNGimage,capture_method,signer_name,expected_content_hash) signs a line. Before the half's signing date it is 422signature_period_not_reached; also 409content_changed,role_already_signed,record_locked,voided, 422invalid_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, withclient_id,caregiver_idandperiod_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 livesignatures, 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}/evidencedays carrycare_logs(each with itssource, times,attestation_method,attestation_skip_reasonand itscomparisonsof kindcare_log_times,care_log_tasksorattestation, withstate,fields,conflict_key,only_care_logandonly_work_order) andclaim_changes(claims sent before a care log of the day changed). A care-log conflict's key is inopen_conflict_keysand is dismissed throughPOST /api/v1/clients/{id}/evidence/dismissalsas a visit conflict is; the bulk dismissal takes them too. MCP:get_client_month_evidence.GET /api/v1/batches/{id}/revenue-warningshas a new kind,changed_after_claim: a care log addended or voided after its claim was sent. Every warning carrieslink, null except on that kind, where it opens the client-month evidence grid. Dismissed throughPOST /api/v1/revenue-warnings/dismissalslike 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 withfilled,updatedandunchangeddays anddifferencesandflagged(each{date, reason}). Entries and marks the office typed are kept and their days named indifferences(warn, never block). A rerun with nothing changed writes nothing. Refusals: 404not_found; 409stale_record; 422not_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-logsandGET /api/v1/care-logs/{id}carryattestation_skip_reason(client_asleep_or_unwell,client_not_present,client_declined_to_sign,client_unable_to_signorother),attestation_skip_note,attestation_skipped_atandattestation_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_logsandget_care_log.GET /api/v1/care-logstakesneeds_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-logslists care logs as the Care Logs screen does, newest day first, each withtask_counts(done,refused,not_needed,unmarked), filtered byclient_id,caregiver_id,from,to,sourceandstate;limitdefaults 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),warningsand livesignatures. 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 sourceoffice: 201 when it is new, 200 with the live care log when the day already has one. 422visit_mismatch. MCP:start_care_log.POST /api/v1/care-logs/{id}/tasks/{task_id}/mark(task_idis the task'stask_definition_id), body{status, reason_code, reason_note, count}, SETS a task's status; 422task_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; 422task_definition_not_found. MCP:add_care_log_task.PATCH /api/v1/care-logs/{id}, body{lock_version, notes, time_in, time_out}; 409stale_record. MCP:update_care_log.POST /api/v1/care-logs/{id}/finishmarks it finished, once. MCP:finish_care_log.POST /api/v1/care-logs/{id}/paper-on-filerecords the client's paper signature as on file, which signs and locks the day: a multipart scan infile, or JSON{document_id}naming a document on the client's file, or neither. 201; 422document_not_found; 409role_already_signed. MCP:mark_care_log_paper_on_file(withdocument_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 toolsadd_record_addendum,void_recordandget_record_historytakerecord_typecare_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 (clientorrepresentative) is drawn on the device in the app, so those roles answer 422drawn_required. MCP:sign_complaint.POST /api/v1/critical-incidents/{id}/signatures, body{role}, signsoffice(reported by) orsupervisor(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); 409stale_record,voidedorcontent_changed; 422already_signed,content_unreadable(the record's text cannot be read, so it cannot be signed) orvalidation_failed. PATCH /api/v1/complaints/{id}andPATCH /api/v1/critical-incidents/{id}on a signed record takestatusalone; any other field answers 409record_lockedand nothing is written.- Complaints and critical incidents carry
record_state:draft,signed,amendedorvoided, andcomplaintandcritical_incidentjoin therecord_types of/api/v1/signed-records/{record_type}/{id}/addenda,/voidand/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: 404not_found(no report, or another agency's Work Order); 409stale_record,voidedorlegacy_signed; 422already_signedorvalidation_failed. MCP:sign_monthly_client_report.POST /api/v1/work-orders/{id}/monthly-reporton a signed report answers 409record_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 422client_signed.- The monthly client report (
GET /api/v1/monthly-client-reportsand the save) carriesrecord_state:draft,signed,amendedorvoided. monthly_client_reportjoins therecord_types of/api/v1/signed-records/{record_type}/{id}/addenda,/voidand/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_typesupervisor_visitorplan_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 readsamended. The same body and reason again within 60 seconds answers the addendum already made. Refusals: 404not_found; 409voided; 422validation_failedornot_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 (403forbidden); 422reason_requiredornot_signed; 409voided. MCP:void_record.GET /api/v1/signed-records/{record_type}/{id}/historylists 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}forplan_of_careandsupervisory_visitreadsaddenda_through:noneprints 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: 404not_found; 409stale_record,content_changedorvoided; 422validation_failedoralready_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 (403forbidden); 422reason_required,not_signedornot_current; 409voided. MCP:revise_plan_of_care.- A plan of care now reads
record_state,replaces_idandsignatures(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, andmonthas YYYY-MM) answers the month the client's Visit evidence grid shows: every calendar day with itsstate(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.monthdefaults to this month (Mountain). The MCP toolget_client_month_evidenceanswers the same.POST /api/v1/clients/{id}/evidence/dismissals(caregiver_id,month,reasonof 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 withdismissed, how many; 0 when none was open. No visit changes. Another agency's client or caregiver answers 404 on both. The MCP tooldismiss_month_evidence_conflictsdoes 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,reasonof 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 withalready_dismissedtrue; aconflict_keythat is no longer a conflict of that day 409conflict_changed; another agency's client or caregiver 404. The MCP tooldismiss_evidence_conflictdoes 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) andpaper_form_type(work_order,time_services_card,plan_of_care,monthly_client_report,supervisory_visit,cfc_calculator,intake_consent,complaint_incidentorother, the default), are read on every document and written byPOST /api/v1/clients/{id}/documentsandPATCH /api/v1/documents/{id}on alegacy_paperscan; any other document ignores them. Alegacy_paperscan is a PDF, JPEG or PNG on a client. GET /api/v1/clients/{id}/documentstakes the filtersdocument_type,form_type,fromandto(YYYY-MM-DD, compared withrecord_date). The MCP toolslist_client_documents,upload_client_documentandupdate_person_documenttake the same.
Added October 26, 2026 (US-101.12, the electronic evidence report):
GET /api/v1/reports/electronic-evidence(monthasYYYY-MM, default the latest computed month;limitandoffsetpage both tables) answers the share of worked client-days with electronic visit evidence for the 12 months ending withmonth, and formonthper caregiver and per client, lowest share first, as the agency's Electronic Evidence page shows it. A month with no snapshot answerscomputed: false. The MCP toolget_electronic_evidence_reportanswers 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. Withdry_runtrue it answers 200 with the counts and unresolved rows and writes nothing (422missing_columns,csv_parse_error,empty_file,too_many_rows,file_too_largefor 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 withabandoned. MCP:import_sandata_visits,get_visit_import.
Changed October 26, 2026 (US-101.9, imported visits are read-only):
- A visit now carries
import_systemandimport_external_id, set on an imported visit (sourceimport) and null on the agency's own.PATCH /api/v1/visits/{id},POST /api/v1/visits/{id}/transitions,POST /api/v1/visits/{id}/reassignandDELETE /api/v1/visits/{id}refuse an imported visit with 422imported_visit, as do the MCP toolsupdate_visit,transition_visit,reassign_visitanddelete_visit.POST /api/v1/visits/bulk-verifyand/bulk-cancelleave an imported visit unmoved and list it infailedwith reasonimported_visit, a value theVisitBulkTransitionResultenum now names.
Added October 26, 2026 (US-92.2, the paper-capture consent):
GET,POSTandDELETE /api/v1/consents/paper_captureread, 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_consentandrevoke_consentwith purposepaper_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
failedwith error codepaper_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-correctionanswers 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-correctionundoes it, answering the restored claim. Refusals: 409changed_sinceorbusy; 422already_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}, andsummary.truncatedis true when the read reached its 500-PAR or 2,000-visit bound.- The MCP tool
get_revenue_at_riskanswers 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 toolget_workforce_reportanswers the same function.
Changed October 24, 2026 (#2997, file answers that survive a cut):
- MCP file answers carry base64 beside the
download_urlonly 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}.pdfand theget_print_documenttool refuse a parameter the form does not read, naming the ones it does (400bad_request; a tool error over MCP). It used to be ignored, so a client that sentdate_fromfor a communication report'sfromgot the default range with no sign of it. The operations' descriptions and the tool'sparamslist what each form reads.- A print's PDF is served
inlinerather thanattachment, so a person who opens an assistant'sdownload_urlsees 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_urlthat 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 isprivate, no-storeand 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 optionaldelivery:auto, the default, answers as before (base64 up to 1 MiB, else adownload_url);urlanswers only the/mcp/filesdownload_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, andstatus): sets each caregiver to the status, saving each one on its own so a refused save leaves the others saved. The answer listsupdatedandfailed, 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 422validation_failed, and nothing is written.- The MCP tool
update_caregiver_statusesanswers 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 carrieskind(due_today,overdue,compliance,oig,supervisory_visit,recertification,authorization_ending,follow_up),subject_type(client,caregiver, oragencyfor a reminder with no client),subject_id,subject_name("Last, First"),due_on,action_label("Renew by Nov 3") andpath, the app page that does it.limitdefaults to 20 and is at most 100;totalis the true count. An unknownkindis 422invalid_kind.- The MCP tool
needs_attentionanswers the same function.
Changed October 22, 2026 (Epic 108, US-108.9, the dollars unused on a PAR):
GET /api/v1/authorizationsandGET /api/v1/authorizations/{id}carryunused_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 toolsfind_authorizationsandget_authorizationcarry 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 carriesclaim_id,client_id, the service and paid dates,procedure_code,modifiers,units,published_rate,tenant_rate,expected,paid,gap,carcs(each with itsdescription), and thekindandfingerprintto dismiss it with. The page addstotal_gap,truncated(more than 5,000 paid claims in the period, so only the newest-paid were judged),paid_fromandpaid_to. Paid dates default to the last 90 days; a range over 366 days is 400. Dismissed rows are left out unlessinclude_dismissedis true. Dismissing isPOST /api/v1/revenue-warnings/dismissalswith kindunderpayment.- The MCP tool
list_underpaymentsanswers 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 (idandclaim_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 unlessinclude_dismissed=true; dismiss one withPOST /api/v1/revenue-warnings/dismissals, kindresubmission_deadline.- The MCP tool
list_resubmission_deadlinesanswers 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/dismissalswith 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 422unknown_kind.- The MCP tools
list_batch_revenue_warnings,dismiss_revenue_warningandrestore_revenue_warninganswer 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}andDELETE /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 clearslast_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 givenprovider_revalidation_id) anddelete_provider_revalidationanswer 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 formclient_work_orderswithclient_idandmonth(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-planandget_shift_plancarryother_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), andhma, the client's HMA calculator week (plan_id,weekly_minutes) or null.POST /api/v1/plans-of-care/{id}/work-orders/distributeanddistribute_plan_work_orderscarryshift_plan_work_orders, the Work Orders the client's Shift Plan made that are in force in the month, each with itsshift_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-planandget_shift_plan: each card row gainsmin_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) andweek(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 toolget_print_documenttake the formshift_planwithclient_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=pdfanswers 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 toolset_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 422too_long, a shift id no plan has 404.GET /api/v1/clients/{id}/shift-plan:settings.care_instructions; each card'safter,care_instructionsandcaregiver_week(the shift's caregiver's week across the agency's clients, null with no active caregiver); each day'sby_day, true when the shift starts at a time of its own that day (set throughshift_settingsby_day in PATCH); each service'soff_tasks; each task row'ssplit. A split task is no longer amongwarnings, 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 toolset_shift_plan_caregiver: save the caregiver picked for a shift, or let go of it withcaregiver_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-planandget_shift_plancarrycaregivers, shift id => the caregiver picked for it.POST /api/v1/clients/{id}/shift-plan/generateandgenerate_shift_plan_work_orders: a shift left out ofcaregiverstakes 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 asno_caregiverand 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/addand the MCP tooladd_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 422unknown_task.DELETE /api/v1/clients/{id}/shift-plan/tasks/{service}/{task}and the MCP toolremove_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_tablelists each service's tasks in the state form's order, under the form's names ("Meal Prep/Menu Planning", "Bladder Care"); each row gainsnorm,maxandover_max(the state's weekly maximum, a warning only). Newtask_totals(each service's Min / week and CFC hours) andaddable(the form's tasks Add task offers).
Changed October 21, 2026 (US-107.9):
POST /api/v1/cfc-calculatorand the MCP toolcreate_client_from_cfc_calculator: a new client from a CFC calculator. The card read from it (last_nameandfirst_namerequired;medicaid_id,addressandphonewhen the calculator has them) makes the client, and the calculator's import job starts for it, asPOST /api/v1/clients/{id}/cfc-calculatorstarts one. The answer'soutcomeiscreated,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) orconflict(the Medicaid ID is on file under another name: 200,importnull, nothing written). A card the client form refuses answers 422validation_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/cellsandset_shift_plan_celltake nolock_versionand 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. Alock_versionstill sent is ignored.POST /api/v1/clients/{id}/shift-plan/undoandundo_shift_plan_editslet 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'seditedis true exactly where the office set it.
Changed October 21, 2026 (Epic 104, the Shift Plan):
GET /api/v1/clients/{id}/shift-planand the MCP toolget_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,warningsandprint_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-planandupdate_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/cellsandset_shift_plan_cell: one day cell, against the card'slock_version; a Work Order written since answers 409stale_recordand nothing is saved.POST /api/v1/clients/{id}/shift-plan/undoandundo_shift_plan_edits: the screen's Undo my changes, answeringundone_shifts.POST /api/v1/clients/{id}/shift-plan/tasksandupdate_shift_plan_task: one task-table figure (times,min_taskormin_week); a value not above 0 answers 422invalid_figure, one past a week 422too_large.POST /api/v1/clients/{id}/shift-plan/generateandgenerate_shift_plan_work_orders: the screen's Generate, with optionalcaregiversper shift, answeringgenerated(the Work Orders written, replaced, archived and skipped, and the warnings). Nothing is refused for the layout.GET /api/v1/clients/{id}/shift-plan/exportandexport_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/broadcastsand the MCP toolsend_broadcasttakerecipient_scopepick, implied by either new field:caregiver_ids, the agency's caregivers to send to whatever their status (former ones included, at most 1000), andtag, every caregiver carrying it (any case), active ones only unlessinclude_formeris true. An id that is not one of the agency's caregivers answers 422validation_failed. A caregiver opted out of SMS is never texted, onbothtoo.Broadcastgainsreply_countandyes_count.GET /api/v1/broadcastsand the MCP toollist_broadcasts: the agency's broadcasts, newest first, paged, each withmessage,reply_countandyes_count.GET /api/v1/broadcasts/{id}/repliesand the MCP toollist_broadcast_replies: the caregivers who texted back to a broadcast, latest first, each with the reply,yesandreplied_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-summaryand the MCP toolget_payroll_summary: the Payroll Summary of a month (year,month, both required) or one of its pay periods (period, an index intopay_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 withlimitandoffset, andtotalsare over every row. A cash advance another payroll file holds is listed incash_advance_held, worded as the page words it ("$50.00 on the Oct 01 - Oct 15, 2026 file"), and is in neithercash_advancenor the totals. Each read is audited against the caregivers it returned.GET /api/v1/cash-advancesand the MCP toollist_cash_advances: the agency's cash advances, newest first, filtered bystatus,searchanddeduct_in_month(YYYY-MM), paged, withtotalsofamountandremaining_balanceover every advance the filters match.CashAdvancegainsreason, in every answer, andcaregiver_name, in the list.GET /api/v1/payroll/w4-changesand the MCP toollist_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 withlimitandoffset; each read is audited against the caregivers it returned.GET /api/v1/supervisory-visits/dueandsupervisory_visits_duetakeplanned_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 carriesplanned_day, the day capped to the month's last, null when no day is set. Any other form ofplanned_foris400.
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}andDELETE /api/v1/client-other-services/{id}, and the MCP toolslist_client_other_services,add_client_other_service,update_client_other_serviceanddelete_client_other_service: a client's other services, the outside providers serving it (kindadult_day, cna, rn, pt or other;company,phone,address,description;days, any of su mo tu we th fr sa, kept in week order; andtimes, 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 answers422naming 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), onGET /api/v1/clients/{id}, the list and the MCP toolget_client.POST /api/v1/clients/{id}/agency-services-onlyand the MCP toolset_agency_services_onlyset it, withvalueand thelock_versionthe client was read with; a client changed since answers409 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 toolsget_agency_profileandupdate_agency_profile, admins only on write).
Changed October 16, 2026 (US-102.35):
POST /api/v1/clients/{id}/supervisory-planand the MCP toolset_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 is422 validation_failed, and alock_versionread before another write is409 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}/duplicateandduplicate_work_ordertake an optionalmode(keep_both,close_previous,temporary) witheffective_date,closing_date,temporary_from,temporary_to,client_id,caregiver_idandlock_version: a new standing Work Order with the next WO #, as the page's Duplicate makes it, answered as its first month withwarnings. An admin or office manager only (403 duplicate_not_permitted).close_previousneeds thelock_versionthe Work Order was read with (409 stale_recordwhen it changed since); a choice the page refuses, a missing Effective Date included, is422 duplicate_refusedin its words, a close of an archived Work Order422 work_order_archived. A field another mode takes, or these fields mixed withmonthandyear, is400. A body withoutmodecopies one month, as before.POST /api/v1/caregivers/{id}/w4-sent-to-payrolland the MCP toolmark_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 optionalw4_changed_atclears only the change read at that time (409 stale_recordotherwise); a caregiver with none waiting is422 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 toolsend_sandata_certification_case: sends one Sandata certification test case, admin only and in the certification tenant only. The certification page read carriescases, each with itsid, round,applied(null in round 1), why it isblocked, andstate, how many of its records areaccepted,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) andto_send.404 not_foundfor an unknown case,409 not_readywhile 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_recordswith no sample records,409 nothing_to_sendwhen every record of it is accepted, waiting, parked or held back,500 case_incompletewhen its change failed and changed nothing.PATCH /api/v1/settings/sandata/certification/dry-runand the MCP toolset_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 carriesdry_run, which is on until someone turns it off.POST /api/v1/settings/sandata/certification/sendand the MCP toolsend_sandata_sample_recordssend the Employees and then the Clients test case, each on its own, and answerdry_runand each case's result besidequeued, which is false in a dry run. A case refused while the other went carriesrefused, thecodeandmessagethe case's own send would answer.POST /api/v1/settings/sandata/certification/send-visitsand the MCP toolsend_sandata_sample_visitssend the next visit test case whose visits Sandata does not hold yet, one per call, and answer itscasebesidequeued_visits;409 not_readyis 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 toolsupdate_caregiverandcreate_caregiver). Null until set. Over MCP it answers as{"untrusted_text": ...}, as text someone typed. -
The MCP tools
update_caregiverandupdate_clientanswer 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, asget_caregiverandget_clientalready did.update_clientanswers 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/v1and over MCP, rather than the texterror; a caregiver's SSN that can no longer be read answersssn_maskednull rather than failing the request. -
Over MCP, a date of birth an import stored as
MMDDYYYYorM/D/YYYYanswers as theYYYY-MM-DDdate 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 409upload_slot_usedalways 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 toolget_work_order) answersseen_by_date: each date of its month to an opaque value (US-95.99). Send a date's value asseentoPUT /api/v1/work-orders/{id}/days/{date}orset_work_order_day, and a date changed since that read is refused (409stale_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/v1twin refused that token, which is valid for/mcponly, so such a URL could not be fetched at all. The/api/v1file routes are unchanged and still take an agency key. -
Every error status an operation's description names is now in its
responses, in the sharedErrorenvelope, with the codes the description gives (US-95.54). The resources' list, get, create and update operations declare 400bad_request, 404not_found, 409stale_recordand 422validation_failedwhere 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_recordon 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 422validation_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
nullableis 422null_not_allowednaming 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'slock_versionamong 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/uploadschecks the document's details and answers a single-useupload_url, bound to the credential and the agency, andPUT /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 toolupload_company_documentanswers such a slot, under/mcp, when it is called withoutfile_base64or 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-verifyand/api/v1/visit-exceptions/resolveids answers 422validation_failedat both. -
The rest of the Settings page is on the API (US-95.47), admin credentials only:
GET /api/v1/settings/securityandPUT /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, andGET /api/v1/consents/{purpose},POST /api/v1/consents/{purpose}andDELETE /api/v1/consents/{purpose}forexternal_ai_clientsandapi_access.GET /api/v1/me/reminder-preferencesandPUT /api/v1/me/reminder-preferencesread 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-billingand the MCP toolverify_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 thelock_versionthe Work Order was read with and answers the Work Order,timesheet(what happened to the report) andcompletion(completed_noworalready_complete). AddedPOST /api/v1/work-orders/{id}/timesheet/overwriteand the MCP tooloverwrite_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 409has_claims, itsdetailsgivingtotal,by_statusandtimesheet_ids, and nothing changes; one with entries typed from the card answers 409entries_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, andformat=pdfanswers 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 toolget_print_documentanswers the PDF. - The agency profile update refuses a null or blank
nameasnull_not_allowed, naming it, before the save is tried (US-95.73); it was refused asvalidation_failedfrom 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_nameorcommentsempties 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 thenothing_to_changeandinvalid_answersrefusals 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_unavailablewithRetry-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-timesheetsanswers 409stale_recordwhen 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_foundwhatever 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 thelock_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_idtakes null to unlink its PAR. An id that is not a PAR of the plan's own client, not deleted, now answers 422 namingauthorization_idon 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/testandGET /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/sendandPOST /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-resubmissionandPOST /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-overrideandPOST /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}andGET /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 (404not_scanned_cleanbefore).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}andPOST /api/v1/meeting-minutes/{id}/finalize(US-95.43): the Compliance meeting minutes pages, from draft to finalized. Finalized minutes refuse any change (422not_draft).GET /api/v1/oig-attestations,POST /api/v1/oig-attestationsandGET /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 bypayment_date_from/payment_date_toandmember, each CARC and RARC with its plain-Englishmeaning.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}/exportandPOST /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 carriesevv_clock_in,evv_clock_outandvisit_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 fullssn, which is never returned. Anssnin a body used to be ignored. GET /api/v1/clients/{id}/medicalandPATCH /api/v1/clients/{id}/medicalread and write the client page's Medical tab.GET /api/v1/batches/{id}/837downloads 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 declarenullableis 422null_not_allowednaming 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_failedfor a blankfirst_nameor claim default,field_requiredfor a blank support ticketsubject). - These fields are now declared not nullable, since the record requires them:
a service rate's
procedure_code,rate_per_unitandeffective_date; an assignment'sbilling_codeandeffective_date; a plan of care'seffective_date; a prospect'sfirst_name,last_nameandphone; a task set template'sname; a note'snote_dateandnote_text; a training'scompleted. A null on one wasvalidation_failed, and on a plan'seffective_datea 200 that changed nothing; it is nownull_not_allowed. - A null or a blank on a field the schema declares
nullablereaches the write as before. On a PATCH it empties the field, or, on a field the record still requires (an authorization'sauthorized_units, a complaint'scomplaint_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'sexpiry_dateis 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
tasksholding 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_missingwhere it saidno_file.GET /api/v1/company-documents/{id}/file: 410 or 500 where it said 503retrieve_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 409export_failed, its message the export's own reason, where a failed export said 409not_ready.POST /api/v1/provider-care-plans/{id}/reconciliation/preview: 503, 500 or 410 where a PCSP the store could not read said 422unreadable_document.POST /api/v1/company-documentsandPOST /api/v1/clients/{id}/pcsp-documents: 503 or 500 where a store, scan-queue or upload failure said 422validation_failed.POST /api/v1/client-notes/{id}/attachmentsandPOST /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 422not_savedorfile_required, and 500internal_errorwhere a refused audit record said 422not_saved.POST /api/v1/payroll-exports/{id}/generate: 503 or 500 where a store failure said a 500 that kept the Idempotency-Key, and 500internal_errorthat 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 staysprocessing, itserror_messagesaying it is retried automatically, until the last attempt marks itfailed, saying to start a new export; one whose file the store refused isfailedat once, where both used to readfailedbetween attempts. A completed export'serror_messageis 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), andPOST /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.acceptedbatch.rejectedremittance.postedclaim.deniedvisit.verified(added November 2, 2026)claim.denial_withdrawn(added November 2, 2026)caregiver.credential_expiring(added November 2, 2026)