⚙ What Can We Build
Every AxisCare capability mapped to a specific Nerve Center feature -- what's live, what's ready, and what's blocked.
Esmeralda matches incoming phone numbers to clients/caregivers. On every incoming call, the Nerve Center searches all client and caregiver phone fields and returns the matching name and profile.
GET /api/clientsGET /api/caregivers
Full client info on demand. After identifying a caller, Esmeralda pulls the full profile -- services, schedule, priority notes, allergies, languages.
GET /api/clients/{id}
Full caregiver info on demand. Same as client lookup but for caregivers.
GET /api/caregivers/{id}
What visits are happening today. Esmeralda or any staff member can ask "What's on the schedule today?" and get a complete list of visits with caregivers, clients, and times.
GET /api/visits
Audit trail for every Esmeralda call. After every call, Esmeralda creates a call log entry with the caller's name, phone, subject, and notes.
POST /api/call-logs
Is a caregiver clocked in? When a client calls asking "Where is my caregiver?", Esmeralda checks if today's visit has a clock-in time.
GET /api/visits
Handle caregiver call-offs. When a caregiver reports they can't make a shift, the visit can be reassigned to another caregiver.
PATCH /api/visits/{id}
Catch canceled visits before they become billing losses. When a visit is deleted, the Nerve Center batches cancellations by client (5-min window), enriches with details, and emails scheduling staff.
scheduling.visit.remove
Track electronic visit verification. Twice daily (10 AM and 3:30 PM), the Nerve Center pulls today's visits and flags any where clock methods aren't Mobile or Telephony for BA- service codes.
GET /api/visits
Daily confirmation texts to caregivers. Every morning, pulls tomorrow's visits, groups by caregiver, and sends a consolidated SMS: "You have 3 visits tomorrow. Reply YES to confirm." Tracks responses. At 3 PM cutoff, unconfirmed shifts trigger coverage outreach.
GET /api/visitsGET /api/caregiversscheduling.visit.createdFromSchedule
Automated call-out replacement. When a caregiver calls out, ranks all available caregivers by: driving distance to client, familiarity with client, overtime risk, response history. Sends outreach SMS/calls. First responder gets the shift.
GET /api/caregiversGET /api/visitsPATCH /api/visitsscheduling.visit.caregiver
Real-time missing clock alerts. Every 2 minutes, checks for visits where the scheduled start has passed but no clock-in received. Sends escalating alerts: text caregiver -> call caregiver -> text client (carefully).
GET /api/visitsscheduling.visit.clockedInscheduling.visit.clockedOut
Automated lead creation from calls. When Esmeralda handles an inquiry call, she creates the lead in AxisCare and the Nerve Center starts the follow-up workflow.
POST /api/leadslead.created
Automated recruiting workflow. New applicant -> AI interview invite -> interview completion -> background check -> credentialing -> caregiver record created.
POST /api/applicantsPOST /api/caregiversapplicant.createdcaregiver.created
Bulk verify clean visits. Automatically verify visits where both clock events are present, methods are valid, times are within tolerance, and signatures are captured. Only flags exceptions for human review.
PATCH /api/visits/{id}scheduling.visit.verify
Monitor care task documentation. Track which ADLs were documented per visit vs. what the care plan requires. Flag visits with missing ADL documentation.
GET /api/clients/{id}/adlsscheduling.visit.adls.*
Create/modify recurring patterns. Case managers can create and modify recurring schedules from the Nerve Center UI instead of logging into AxisCare.
POST /api/schedulesPATCH /api/schedulesDELETE /api/schedulesrecurring_schedule.*
Catch billing issues before claims go out. Flag visits where billable is false, rate is zero, or rate doesn't match the expected rate for the service code. Alert before claims are submitted.
GET /api/visitsscheduling.visit.billablescheduling.visit.billableRate.updated
Real-time AxisCare data sync. Instead of pulling all visits every time, only fetch visits that changed since the last check. Run every 2 minutes for near-real-time sync without API abuse.
GET /api/visits?updatedSinceDate
Alert family members when something happens that they should know about (schedule change, missed visit, incident). Pull the responsible party contacts and send notifications.
GET /api/clients/{id}/responsibleParties
⚠ BLOCKED: Responsible parties endpoint returns 404 on site 13131. Need AxisCare support to enable.
These features would require AxisCare UI access or support intervention:
Service Codes List
Regions List
Admin/User List
Authorizations
Custom Fields
Forms
Documents
Reports
Billing/Invoices
Payroll
EVV Endpoint (403)
Notes Write
Webhook Management
</> Code Patterns
Ready-to-use JavaScript code for common integration tasks.
API Constants
const AXC = {
site: process.env.AXISCARE_SITE || '13131',
token: process.env.AXISCARE_TOKEN,
version: '2023-10-01',
get base() { return `https://${this.site}.axiscare.com/api`; },
get headers() {
return {
'Authorization': `Bearer ${this.token}`,
'X-AxisCare-Api-Version': this.version,
'Content-Type': 'application/json',
};
},
};
Pagination Helper
async function fetchAllPages(endpoint, params = {}) {
const all = [];
let cursor = null;
do {
const url = new URL(`${AXC.base}${endpoint}`);
Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v));
if (cursor) url.searchParams.set('startAfterId', cursor);
const res = await fetch(url, { headers: AXC.headers });
if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);
const json = await res.json();
const items = Array.isArray(json) ? json : json.data || [];
all.push(...items);
// Determine next cursor
cursor = json.nextPageToken || (items.length ? items[items.length - 1].id : null);
} while (cursor);
return all;
}
Fetch with Retry
async function axcFetch(path, options = {}, retries = 3) {
const url = `${AXC.base}${path}`;
for (let i = 0; i < retries; i++) {
try {
const res = await fetch(url, {
...options,
headers: { ...AXC.headers, ...options.headers },
});
if (res.status === 429) {
await new Promise(r => setTimeout(r, 2000 * (i + 1)));
continue;
}
return res;
} catch (err) {
if (i === retries - 1) throw err;
await new Promise(r => setTimeout(r, 1000 * (i + 1)));
}
}
}
Webhook Receiver (Express.js)
const express = require('express');
const app = express();
app.use(express.json());
app.post('/webhooks/axiscare', (req, res) => {
const { event, data, siteNumber } = req.body;
const webhookId = req.headers['x-webhook-id'];
console.log(`[Webhook] ${event} site=${siteNumber} id=${webhookId}`);
// Process by event type
switch (event) {
case 'scheduling.visit.clockedIn':
handleClockIn(data);
break;
case 'scheduling.visit.remove':
handleVisitRemoved(data);
break;
case 'client.updated':
handleClientUpdate(data);
break;
default:
console.log(`Unhandled event: ${event}`);
}
// Respond quickly (within 5s)
res.status(200).json({ received: true });
});
EVV Compliance Checker
const VALID_EVV_METHODS = ['GPS', 'Telephony'];
function checkEVVCompliance(visit) {
const needsEVV = visit.serviceCode?.startsWith('BA');
if (!needsEVV) return { required: false, compliant: true };
const checks = {
clockedIn: !!visit.clockInTime,
clockedOut: !!visit.clockOutTime,
validClockInMethod: VALID_EVV_METHODS.includes(visit.clockInMethod),
validClockOutMethod: VALID_EVV_METHODS.includes(visit.clockOutMethod),
};
return {
required: true,
compliant: Object.values(checks).every(Boolean),
checks,
};
}
Available Caregivers Finder
async function findAvailableCaregivers(date, startTime, endTime) {
// 1. Get all active caregivers
const caregivers = await fetchAllPages('/caregivers', { statuses: 'Active' });
// 2. Get visits for the date
const visits = await fetchAllPages('/visits', {
startDate: date,
endDate: date,
});
// 3. Find caregivers without overlapping visits
const busyIds = new Set(
visits
.filter(v => v.startTime < endTime && v.endTime > startTime)
.map(v => v.caregiverId)
);
return caregivers.filter(c => !busyIds.has(c.id));
}
⚠ Gotchas & Tips
Known quirks, edge cases, and things to watch out for.
⚠
Data structure inconsistency: GET /api/caregivers returns an object with a data property, while GET /api/clients returns an array directly. Always check the response shape.
⚠
Applicant singular vs plural path: Some AxisCare sites use /api/applicant/{id} (singular) instead of /api/applicants/{id} (plural). Try both if you get 404 errors.
⚠
Visit ID format: Visit IDs follow the pattern s=XXXX:d=YYYY-MM-DD. These must be URL-encoded when used in path parameters.
⚠
Responsible parties use listNumber: Responsible parties are accessed by their 1-based listNumber position, not by a unique ID.
⚠
Schedules use nextPageToken: The schedules endpoint uses nextPageToken for pagination instead of startAfterId like other endpoints.
⚠
firstName requires lastName on update: When updating caregivers or clients with PATCH, sending firstName requires also sending lastName and vice versa.
⚠
All call log fields required on create: Unlike other POST endpoints, POST /api/call-logs requires every single field including tags (pass [] if empty).
⚠
Visits updatedSinceDate for incremental sync: Use updatedSinceDate parameter instead of date ranges when doing incremental data sync to catch all modifications.
⚠
DELETE visits accepts modificationReason: When deleting visits, pass a modificationReason integer ID as a query parameter to record why the visit was removed.
⚠
DELETE schedules accepts effectiveDate: When deleting schedules, the effectiveDate parameter defaults to today and cannot be set to a past date.