HarmonyWFM REST API
Everything your team needs to read from and write to HarmonyWFM: employees, time, time off, scheduling, attendance points and every company configuration object your active modules expose. HarmonyWFM issues the API key — the integration itself is built and operated on your side.
1. What you get, and what you build
- A company-scoped API key (Settings → Integrations)
- The endpoints described in this document
- Signed outbound webhooks and delivery logs
- Uptime of the API itself
- The client / middleware that calls the API
- Secure storage and rotation of the key
- A public HTTPS endpoint if you want webhooks
- Field mapping, scheduling, retries and monitoring
2. Setup checklist
- In HarmonyWFM, open Settings → Integrations → API keys. Name the key after the system that will use it (e.g. "ADP payroll export").
- Choose the scope. Leave write access off unless the integration must change data. Keys carry
readand optionallywrite. - Copy the
hwfm_…value immediately — it is shown once and stored only as a hash. Put it in your secret manager, never in source control. - Call
GET /api/public/v1/configto confirm the key works and to see which modules and resources the company has. - Map your fields against the responses, then build your sync. Start read-only in a staging job before enabling writes.
- Optional: add a webhook in the same tab, store the
whsec_…secret and verify signatures (section 7).
3. Base URL and authentication
Every key is bound to one company. There is no tenant parameter — the key determines which company's data you see, and cross-company access is impossible.
Base URL https://harmonywfm.com/api/public/v1
Header Authorization: Bearer hwfm_xxxxxxxxxxxxxxxxxxxxxxxx
Header Content-Type: application/json (writes only)
curl -H "Authorization: Bearer hwfm_YOUR_KEY" \
"https://harmonywfm.com/api/public/v1/config"- TLS is required; plain HTTP is rejected.
- Scope enforcement: GET needs
read; POST/PATCH/DELETE needwrite. - Revoking a key in the Integrations tab takes effect immediately.
- Last-used timestamps are recorded so unused keys can be spotted and retired.
4. Endpoints
/config/me/openapi/company/company/employees/employees/employees/:id/employees/:id/punches/punches/punches/:id/punches/:id/timecards/timecards/:id/timecards/:id/pto-requests/pto-requests/pto-requests/:id/schedules/schedules/schedules/:id/schedules/:id/points/points/points/:id/points/:id/config/:resource/config/:resource/config/:resource/:id/config/:resource/:id/config/:resource/:id5. Configuration resources by module
Resources marked with a module are only reachable when that module is active for the company; otherwise the API returns 403. Singleton resources hold one row per company and are updated with PATCH /config/:resource (no id).
/config/locationsWorksites with timezone, address and geofence settings./config/departmentsDepartment tree, default manager and cost centers./config/jobsJob titles, manager flag and default pay settings./config/skillsSkill catalog used for scheduling and learning./config/job-skill-requirementsSkills required to work a given job./config/employee-groupsGroups used for bulk profile assignment and filtering./config/custom-field-definitionsCustom employee fields (type, options, required)./config/custom-field-valuesCustom field values per employee./config/change-reason-codesReason codes for effective-dated employee changes./config/profile-setup-profilesRole-based navigation / feature visibility profiles./config/approval-delegationsTemporary approval delegation between managers./config/holiday-calendarsNamed holiday calendars./config/holiday-calendar-datesDated holidays inside a calendar./config/holiday-calendar-assignmentsCalendar assignment to company, location, department or employee./config/employee-emergency-contactsEmergency contacts per employee./config/employee-identifiersExternal system IDs mapped to an employee./config/employee-credentialsLicenses and certifications with expiry tracking./config/employee-skillsSkills held by an employee./config/form-templatesCustom form definitions./config/form-template-fieldsFields belonging to a form template./config/form-assignmentsForms assigned to employees and their responses./config/pto-plansAccrual plans, caps, carryover and waiting periods./config/pto-plan-tiersTenure-based accrual tiers inside a plan./config/pto-profilesBundles of PTO plans assigned to employees./config/employee-pto-plan-assignmentsAd-hoc plan assignment per employee./config/pto-balancesCurrent balances per employee and plan./config/time-off-request-profilesRequest notice, approval chain and limits./config/time-off-blackoutsBlackout windows for time off./config/time-off-coverage-limitsMax concurrent time off per location/department./config/background-checksBackground check requests, vendor, status and adjudication./config/employee-documentsDocuments filed against an employee record./config/employee-bank-accountsDirect deposit accounts (write-only fields are masked)./config/employee-tax-withholdingsFederal / state withholding elections./config/position-history/config/assignment-history/config/compensation-history/config/pto-carryover-events/config/pto-tier-grants/config/notifications/config/company-modules/config/company-members/config/background-jobs/config/audit-log/config/timesheet-profilesRounding, OT/DT, meal & break, overnight and attestation rules./config/pay-period-profilesPay frequency, anchor date and lock behavior./config/pay-periodsGenerated pay periods (lock / unlock via PATCH)./config/exception-rulesTime exception rulebook (missing punch, late, long shift…)./config/rate-profilesAlternate pay rate profiles./config/rate-profile-rulesRules inside a rate profile./config/premium-pay-profilesShift differentials and premium pay bundles./config/premium-pay-rulesIndividual premium rules (time of day, day of week, thresholds)./config/labor-distribution-profilesCost allocation profiles./config/labor-distribution-allocationsAllocation percentages inside a distribution profile./config/employee-rate-profilesRate profile assignment per employee./config/employee-premium-pay-profilesPremium pay profile assignment per employee./config/timecard-days/config/punch-edit-requestsEmployee-submitted punch corrections./config/punch-attestations/config/missing-punch-alerts/config/time-exception-notesManager notes on time exceptions./config/timecards/config/scheduling-settings/config/shift-templatesReusable shift patterns./config/schedule-budgetsHour / cost budgets per period and org unit./config/employee-schedule-targetsTarget hours per employee./config/availability-profilesEmployee availability windows./config/shift-swap-requestsShift swap workflow./config/shift-claimsOpen shift claims / bidding./config/points-settings/config/points-thresholdsDisciplinary thresholds and actions./config/points-threshold-events/config/compliance-settings/config/compliance-violations/config/break-violations/config/onboarding-workflowsNew-hire workflow definitions./config/onboarding-workflow-stepsSteps inside an onboarding workflow./config/onboarding-step-documentsDocuments attached to a workflow step./config/onboardingsIndividual onboarding records and status./config/offboardingsOffboarding records and status./config/offboarding-tasksTasks inside an offboarding./config/onboarding-acknowledgements/config/learning-modulesCourses./config/learning-lessonsLessons inside a course./config/learning-seriesCourse series / paths./config/learning-series-modulesCourses within a series./config/learning-profilesLearning profiles assigned to groups of employees./config/learning-profile-itemsCourses inside a learning profile./config/learning-assignment-rulesAuto-assignment rules by job, location or department./config/learning-assignmentsAssignments and completion status./config/learning-quizzesQuizzes attached to lessons./config/learning-quiz-questionsQuiz questions./config/learning-lesson-progress/config/learning-quiz-attempts/config/learning-certificates/config/expense-settings/config/expense-approversApproval chain configuration./config/expense-submittersWho may submit expenses./config/expense-requestsExpense reports and their status./config/expense-itemsLine items on an expense report./config/comp-bandsSalary bands per job / level / geo./config/comp-cyclesMerit / comp review cycles./config/comp-cycle-itemsPer-employee proposals inside a cycle./config/saved-reportsSaved report definitions./config/report-subscriptionsScheduled report email delivery./config/review-templatesReview templates and rating scales./config/review-sectionsSections inside a review template./config/review-questionsQuestions inside a review section./config/reviewsReview cycles per employee and their stage/status./config/review-responsesAnswers submitted on a review./config/review-outcomesRating, merit and promotion outcomes./config/hc-clientsHome care clients / patients./config/hc-client-contactsClient family and emergency contacts./config/hc-client-authorizationsPayer authorizations, units and date ranges./config/hc-care-teamCaregivers assigned to a client./config/hc-care-tasksCare plan task catalog per client./config/hc-care-plan-versionsPublished care plan versions./config/hc-visitsScheduled and completed visits (EVV)./config/hc-visit-tasksTask completion per visit./config/hc-visit-events/config/hc-visit-exceptionsMissed, late and out-of-geofence visits./config/hc-visit-recurrencesRecurring visit patterns./config/hc-medicationsClient medication list (eMAR)./config/hc-med-administrationsMedication administration records./config/hc-vitalsVitals captured during a visit./config/hc-incidentsIncident reports and follow-up./config/meetingsMeetings, agendas, recaps and AI summaries./config/meeting-seriesRecurring meeting series./config/meeting-attendeesAttendance per meeting./config/meeting-todosAction items created in meetings./config/meeting-winsRecognition / wins logged in meetings.6. Request and response shapes
# List with filters, paging and ordering
GET /api/public/v1/config/locations?is_active=true&limit=50&offset=0&order=name
{ "resource": "locations", "count": 2, "data": [ { "id": "…", "name": "Detroit Plant", … } ] }
# Create
POST /api/public/v1/config/departments
{ "name": "Maintenance", "code": "MNT" }
→ 201 { "resource": "departments", "data": { "id": "…", … } }
# Update a singleton
PATCH /api/public/v1/config/points-settings
{ "late_points": 0.5, "ncns_points": 4 }
# New hire
POST /api/public/v1/employees
{ "first_name": "Dana", "last_name": "Reyes", "email": "dana@acme.com",
"hire_date": "2026-09-01", "location_id": "…", "job_id": "…",
"pay_type": "hourly", "hourly_rate": 24.5 }200 / 201Success. Reads return { data }, writes return the affected record.400Validation error. Body: { "error": "…" }.401Missing or invalid API key.403Key lacks the required scope, or the module isn't enabled for the company.404Unknown resource or record not found in this company.405Method not allowed for that resource (read-only or singleton).500Server error — safe to retry with backoff.Fields id, company_id, created_at and updated_at are managed by HarmonyWFM and ignored if sent. Dates use YYYY-MM-DD; timestamps are ISO-8601 UTC. Punch and shift times are stored in UTC and displayed in the employee's location timezone.
7. Webhooks
Add an endpoint under Settings → Integrations → Webhooks, pick events, and store the signing secret. Each delivery is a POST with a JSON body and these headers: x-harmony-event, x-harmony-timestamp (unix seconds) and x-harmony-signature.
punch.createdA punch is recorded from any source.timecard.approvedA timecard moves to approved.pay_period.lockedA pay period is locked for payroll.pto.requestedAn employee submits time off.pto.approvedA time-off request is approved.employee.createdA new hire record is created.employee.terminatedAn employee is terminated.points.assessedAttendance points are assessed.// Node — verify the signature before trusting the payload
import crypto from "node:crypto";
app.post("/hooks/harmony", express.raw({ type: "*/*" }), (req, res) => {
const ts = req.header("x-harmony-timestamp");
const sig = req.header("x-harmony-signature");
const body = req.body.toString("utf8");
const expected = crypto
.createHmac("sha256", process.env.HARMONY_WEBHOOK_SECRET)
.update(`${ts}.${body}`)
.digest("hex");
if (!sig || !crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected)))
return res.status(401).end();
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return res.status(400).end();
const { event, company_id, sent_at, data } = JSON.parse(body);
// enqueue and return quickly
res.status(200).end();
});- Respond within 10 seconds with a 2xx; anything else is logged as a failure.
- Deliveries are logged in the Integrations tab with status, duration and error.
- Use the Send test button to fire a signed ping while you build.
- Handle duplicates idempotently — treat the payload id as the dedupe key.
8. Operating guidance
- Page large reads with
limit/offset; keep batches ≤ 500. - Retry 5xx and network failures with exponential backoff; never retry 4xx blindly.
- Sync incrementally where possible — filter on
updated_ator a date range instead of pulling everything each run. - Write to payroll-relevant objects (punches, timecards) before the pay period locks; locked periods reject edits.
- Use separate keys per integration so one can be revoked without breaking others.
- Rotate keys on a schedule and whenever staff with access leave.
Questions about a specific field or object? Call GET /api/public/v1/config for the live catalog for that company — it always reflects the modules currently active.