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.
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:
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.