MASKDocs

Integration API

Recommended sync flows

Five patterns cover most integrations. Each names the scope it needs; combine them as your system requires.

1. Nightly employee pull#

Scope employees:read. Page through GET /integration/employees?status=all&pageSize=200 and upsert by id.

  • The employee's updatedAt moves when their own record changes: name, email, personalId, language, status. A PATCH that changes nothing leaves it.
  • A membership change (added, edited, ended, reactivated) moves only that membership's memberships[].updatedAt, or adds a membership, not the employee's updatedAt. Compare both to see what changed.
  • A person who disappears from the list has lost every membership in your institutions, or the key was rescoped.
  • MASK ids are the only identifier. Keep a mapping from your own employee number to the MASK id returned by POST /employees, and reconcile names and personalId nightly.

2. Employee master data push#

Scope employees:write. Create with POST /integration/employees, sending an Idempotency-Key derived from your own record (hr-<your id>-create). Change with PATCH, and end or reactivate employment with the membership PATCH.

Pushing your full state every night is safe: a PATCH that changes nothing writes nothing and leaves updatedAt alone. Expect 403 institution_not_allowed for people who also work at a site outside your key; that site's administrator owns their record.

3. Monthly payroll pull#

Scope reports:read. After the month closes, call GET /integration/reports/payroll?institutionId=…&year=…&month=… for each institution of GET /integration/institutions. Pull again before your payroll deadline to pick up late corrections: reports always read the current data.

4. Clock event push#

Scope events:write. POST /integration/events with your own event id as the Idempotency-Key. On a timeout, a 5xx, a 429 or a 409 idempotency_in_progress, retry with the same key after the delay.

Store the MASK id you get back: you need it to correct (PATCH) or void (DELETE) the event later. Send events within 62 days of their business date.

5. Mirroring events#

Scope events:read. Each night, read a sliding window of business dates (for example the last 7 days) with status=all, and upsert by id.

  • A row that became corrected or voided no longer counts.
  • A row with correctsEventId replaces the one it names.
  • Administrators can correct older data at any time, so re-read older windows before you close a period.

Polling instead of webhooks#

v1 has no webhooks: your system asks. A few minutes between pulls keeps data fresh well inside the default limit of 120 requests a minute; a nightly pull is enough for payroll. If you need near-real-time data, poll GET /integration/events for today's business date with a short interval and upsert by id.