Skip to content

Guides

Sync people to another system

On this page

Keep another system (payroll, IT accounts, a badge system, a data warehouse) in step with Bizisy. The pattern has two halves: a full read to start and to reconcile, and webhooks plus the API for every change in between.

You need a Manage key (an HR key reads job details of everyone) and an owner or admin to add the webhook endpoint.

1. The full read#

org.people.list returns the whole directory (public fields) in one call. Read each person in full with org.people.get when you need job details.

JavaScript
const api = (action, input = {}) => fetch(`https://api.bizisy.com/v1/${action}`, {
  method: 'POST',
  headers: { Authorization: `Bearer ${process.env.BIZISY_API_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify(input),
}).then(async (res) => {
  const body = await res.json();
  if (!res.ok) throw new Error(`${body.error.code}: ${body.error.message} (${res.headers.get('x-request-id')})`);
  return body.data;
});

const people = await api('org/people.list', { status: 'all' });
for (const p of people) {
  const full = await api('org/people.get', { person_id: p.id });
  await upsertPerson(full);
}

Mind the rate limit (300 a minute): for a large company, pace the per-person reads, or keep what org.people.list gives you (name, title, team, location, manager, status, start date) when that's enough.

2. Subscribe to changes#

In Settings → Webhooks, add your endpoint with the events you handle, typically person.hired, person.updated, person.job_changed, person.terminated, person.rehired and person.erased (event types). Store the signing secret.

3. Handle each event#

Verify the signature, answer 204, then work from the current state rather than the order events arrived in:

JavaScript
app.post('/webhooks/bizisy', express.raw({ type: 'application/json' }), async (req, res) => {
  if (!verifyBizisyWebhook(req.body, req.headers, process.env.BIZISY_WEBHOOK_SECRET)) return res.sendStatus(400);
  res.sendStatus(204);
  const event = JSON.parse(req.body);
  if (await seen(req.headers['webhook-id'])) return; // at least once: skip duplicates
  if (event.type === 'person.erased') return deletePerson(event.data.person_id);
  if (event.type.startsWith('person.')) await upsertPerson(await api('org/people.get', { person_id: event.data.person_id }));
});

The payload's snapshot (data.person) already has the public and job details; fetch with the API when you need the full record or want to be sure you have the latest.

4. Future-dated changes#

Hires, job changes and terminations can be scheduled. person.job_changed arrives when the change is recorded, with its effective_date; the job itself changes on that day. Either apply it on that day in your system, or read the person as_of the effective date. person.terminated carries last_day the same way.

5. Reconcile#

Run the full read again nightly, or after an endpoint was turned off for failing, to catch anything you missed. Compare by person id (stable; never reused).

What you won't get#

A key never receives other people's private details or pay (What machines can see). If your payroll needs bank details or salaries, those stay in Bizisy: export them from the app by a person, or let people enter them in the payroll system.

Something missing or wrong on this page? Write to hello@bizisy.com.

Developer docs