API reference
Exports, reports and erasure
People as CSV, a person's data for an access request, the headcount report and erasing a former employee.
4 actions · base URL https://api.bizisy.com/v1 · generated from the same definitions as the API.
Erase a former employee's personal data#
POST/v1/org/people.eraseDestructive
Anonymises a person whose employment has fully ended (every job row ended by today; none current or scheduled): names become 'Erased person', the work email becomes a placeholder, contact, private and custom fields and payroll identifiers are cleared, the profile photo, documents (with their files), pay history, reminder records, approval requests about them and their checklists (and their comments on others' tasks) are deleted, invite emails, email delivery records, webhook payloads sent about them and termination reasons are scrubbed. Job rows (dates, titles and contract terms) are kept, anonymised, for history; open invites are revoked and any login is disabled. Irreversible. Owners and admins only; you cannot erase yourself.
- Who can call it
- Manage key owner admin
- MCP tool
org_people_eraseon HR Assistant- Preview
?dry_run=trueruns every check and saves nothing- Retries
- An Idempotency-Key prevents a second run, but the result is never stored (it holds a secret or personal data): a retry gets a 409 that points to Activity
Input
person_idstringrequired
Returns
person_idstringrequirederasedtruerequiredclosed_requestsintegerrequired
Errors
validation_failed unauthenticated forbidden not_found conflict rate_limited internal
curl https://api.bizisy.com/v1/org/people.erase \
-H "Authorization: Bearer $BIZISY_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"person_id":"p1"}'const res = await fetch('https://api.bizisy.com/v1/org/people.erase', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.BIZISY_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify({
"person_id": "p1"
}),
});
const body = await res.json();
if (!res.ok) throw new Error(`${body.error.code}: ${body.error.message}`);
console.log(body.data);import os, uuid
import requests
res = requests.post(
"https://api.bizisy.com/v1/org/people.erase",
headers={"Authorization": f"Bearer {os.environ['BIZISY_API_KEY']}", "Idempotency-Key": str(uuid.uuid4())},
json={
"person_id": "p1",
},
)
body = res.json()
if not res.ok:
raise RuntimeError(f"{body['error']['code']}: {body['error']['message']}")
print(body["data"]){
"data": {
"person_id": "p1",
"erased": true,
"closed_requests": 0
}
}Export people as CSV#
POST/v1/org/people.export_csvRead
Exports people as a CSV file (UTF-8, comma-separated by default; delimiter ";" suits Excel in most of Europe; one row per person) as of a date: names, work email and phone, status, start date, current job (title, team, manager, location, legal entity, employment type, FTE, contract terms) and active custom fields (archived fields are left out; personal-data exports include them). status defaults to active + pre_hire ("all" includes leavers). include_private adds personal contact details, birthday, address, tax id, social security number, IBAN and private custom fields: owners, admins and HR in the app only, never over MCP or an API key. Pay is not included.
- Who can call it
- Manage key owner admin hr
- Keys and apps
- include_private is refused.
- MCP tool
org_people_export_csvon HR Assistant- Method
POSTwith a JSON body, orGETwith the input as query parameters
Input
as_ofstringstatus"active" | "pre_hire" | "terminated" | "all"include_privatebooleandelimiter"," | ";"
Returns
filenamestringrequiredcsvstringrequiredrowsintegerrequiredcolumnsstring[]required
Errors
validation_failed unauthenticated forbidden not_found rate_limited internal
curl https://api.bizisy.com/v1/org/people.export_csv \
-H "Authorization: Bearer $BIZISY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"status":"all","as_of":"2026-10-04","delimiter":";"}'const res = await fetch('https://api.bizisy.com/v1/org/people.export_csv', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.BIZISY_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"status": "all",
"as_of": "2026-10-04",
"delimiter": ";"
}),
});
const body = await res.json();
if (!res.ok) throw new Error(`${body.error.code}: ${body.error.message}`);
console.log(body.data);import os
import requests
res = requests.post(
"https://api.bizisy.com/v1/org/people.export_csv",
headers={"Authorization": f"Bearer {os.environ['BIZISY_API_KEY']}"},
json={
"status": "all",
"as_of": "2026-10-04",
"delimiter": ";",
},
)
body = res.json()
if not res.ok:
raise RuntimeError(f"{body['error']['code']}: {body['error']['message']}")
print(body["data"]){
"data": {
"filename": "people-2026-10-04.csv",
"csv": "given_name,family_name\r\nAna,Ferreira\r\n",
"rows": 1,
"columns": [
"given_name",
"family_name"
]
}
}Export a person's data (GDPR access request)#
POST/v1/org/people.export_dataRead
Returns everything Bizisy holds about one person in this organization as JSON, to answer a data access request: profile (all fields, including private and custom), the profile photo (base64), every document of the person (metadata, plus document_files: 5-minute download links the web app puts in one zip), job history, pay history, invites, their logins (email, role, sign-in methods), their API keys (names and dates, never secrets), their Activity, open positions they filled or are recorded as replaced in, change requests about them (approvals), their checklists (about them, assigned to them, and their comments) and webhook deliveries about them in the last 30 days. Owners, admins and HR, in the app only: it contains private data, so over MCP or an API key it only works for yourself (or use org_me_export_data).
- Who can call it
- Manage key owner admin hr
- Keys and apps
- Only for yourself (or use org.me.export_data).
- MCP tool
org_people_export_dataon HR Assistant- Method
POSTwith a JSON body, orGETwith the input as query parameters
Input
person_idstringrequired
Returns
22 fields
format"bizisy.person-data.v1"requiredgenerated_atstringrequiredorganization_idstringrequiredpersonobjectrequiredphotoobject | nullrequired3 fields
content_typestringrequireddata_base64stringrequiredupdated_atstringrequired
jobsobject[]required17 fields
idstringrequiredvalid_fromstringrequiredvalid_tostring | nullrequiredtitlestringrequiredunitobject | nullrequired2 fields
idstringrequirednamestringrequired
managerobject | nullrequired4 fields
idstringrequirednamestringrequiredtitlestring | nullrequiredphoto_urlstring | nullrequired
locationobject | nullrequired2 fields
idstringrequirednamestringrequired
legal_entityobject | nullrequired2 fields
idstringrequirednamestringrequired
employment_type"full_time" | "part_time" | "contractor" | "intern"requiredftenumberrequiredreasonstringrequiredend_reasonstring | nullrequiredcontract_type"permanent" | "fixed_term" | "temporary" | "internship" | "freelance"requiredcontract_end_datestring | nullrequiredprobation_end_datestring | nullrequiredweekly_hoursnumber | nullrequirednotice_period_daysinteger | nullrequired
payobject[]required8 fields
idstringrequiredvalid_fromstringrequiredvalid_tostring | nullrequiredamountnumberrequiredcurrencystringrequiredperiod"year" | "month" | "hour"requirednotestring | nullrequiredcreated_atstringrequired
invitesobject[]required6 fields
emailstringrequiredrolestringrequiredcreated_atstringrequiredexpires_atstringrequiredaccepted_atstring | nullrequiredrevoked_atstring | nullrequired
loginsobject[]requiredapi_keysobject[]requiredconnected_appsobject[]requiredactivityobject[]requiredactivity_truncatedbooleanrequirednotificationsobject[]required3 fields
typestringrequiredcreated_atstringrequiredread_atstring | nullrequired
remindersobject[]required3 fields
kindstringrequireddatestringrequiredsent_atstringrequired
positionsobject[]required4 fields
idstringrequiredtitlestringrequiredstatusstringrequiredrole"filled" | "replaced"required
approvalsobject[]requiredchecklistsobjectrequired5 fields
about_youobject[]required6 fields
namestringrequiredkindstringrequiredstatusstringrequiredanchor_datestringrequiredstarted_atstringrequiredtasksobject[]required6 fields
titlestringrequireddue_datestringrequiredstatusstringrequiredskip_reasonstring | nullrequiredresolved_atstring | nullrequiredcommentsobject[]required3 fields
textstringrequiredatstringrequiredby_youbooleanrequired
assigned_to_youobject[]required5 fields
checkliststringrequiredtitlestringrequireddue_datestringrequiredstatusstringrequiredresolved_atstring | nullrequired
your_commentsobject[]required4 fields
checkliststringrequiredtaskstringrequiredtextstringrequiredatstringrequired
resolved_by_youobject[]required5 fields
checkliststringrequiredtaskstringrequiredstatusstringrequiredskip_reasonstring | nullrequiredresolved_atstring | nullrequired
template_tasksobject[]required2 fields
templatestringrequiredtaskstringrequired
webhook_deliveriesobject[]required4 fields
event_typestringrequiredendpoint_hoststringrequiredcreated_atstringrequiredstatusstringrequired
documentsobject[]requireddocument_filesobject[]required2 fields
namestringrequiredurlstringrequired
filenamestringrequired
Errors
validation_failed unauthenticated forbidden not_found rate_limited internal
curl https://api.bizisy.com/v1/org/people.export_data \
-H "Authorization: Bearer $BIZISY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"person_id":"p1"}'const res = await fetch('https://api.bizisy.com/v1/org/people.export_data', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.BIZISY_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"person_id": "p1"
}),
});
const body = await res.json();
if (!res.ok) throw new Error(`${body.error.code}: ${body.error.message}`);
console.log(body.data);import os
import requests
res = requests.post(
"https://api.bizisy.com/v1/org/people.export_data",
headers={"Authorization": f"Bearer {os.environ['BIZISY_API_KEY']}"},
json={
"person_id": "p1",
},
)
body = res.json()
if not res.ok:
raise RuntimeError(f"{body['error']['code']}: {body['error']['message']}")
print(body["data"]){
"data": {
"format": "bizisy.person-data.v1",
"generated_at": "2026-10-04T10:00:00.000Z",
"organization_id": "o1",
"filename": "ana-ferreira-data-2026-10-04.json",
"person": {
"id": "p1",
"name": "Ana Ferreira"
},
"photo": {
"content_type": "image/webp",
"data_base64": "UklGRg==",
"updated_at": "2026-10-04T10:00:00.000Z"
},
"jobs": [
{
"id": "j1",
"valid_from": "2024-01-15",
"valid_to": null,
"title": "Engineer",
"unit": {
"id": "u2",
"name": "Engineering"
},
"manager": {
"id": "p2",
"name": "Rui Costa",
"title": "CTO",
"photo_url": "https://acme.bizisy.com/api/photos/people/p2?v=01k0000000000000000000000b"
},
"location": {
"id": "l1",
"name": "Head office"
},
"legal_entity": {
"id": "e1",
"name": "Acme Lda"
},
"employment_type": "full_time",
"fte": 1,
"reason": "hire",
"end_reason": null,
"contract_type": "fixed_term",
"contract_end_date": "2026-01-14",
"probation_end_date": "2024-07-14",
"weekly_hours": 40,
"notice_period_days": 30
}
],
"pay": [
{
"id": "pay1",
"valid_from": "2024-01-15",
"valid_to": null,
"amount": 42000,
"currency": "EUR",
"period": "year",
"note": null,
"created_at": "2026-10-04T10:00:00.000Z"
}
],
"invites": [
{
"email": "ana@acme.test",
"role": "member",
"created_at": "2026-10-04T10:00:00.000Z",
"expires_at": "2026-10-18T10:00:00.000Z",
"accepted_at": null,
"revoked_at": null
}
],
"logins": [
{
"email": "ana@acme.test",
"roles": [
"hr"
]
}
],
"api_keys": [],
"connected_apps": [
{
"app": "Claude",
"access": "me"
}
],
"activity": [
{
"at": "2026-10-04T10:00:00.000Z",
"summary": "Updated your profile"
}
],
"activity_truncated": false,
"notifications": [
{
"type": "approval_request",
"created_at": "2026-10-04T10:00:00.000Z",
"read_at": null
}
],
"reminders": [
{
"kind": "probation_end",
"date": "2024-07-14",
"sent_at": "2024-06-30T06:00:00.000Z"
}
],
"positions": [
{
"id": "pos1",
"title": "Engineer",
"status": "filled",
"role": "filled"
}
],
"approvals": [
{
"kind": "job_change",
"status": "approved",
"effective_date": "2026-11-01",
"proposed_at": "2026-10-04T10:00:00.000Z",
"closed_at": "2026-10-05T09:00:00.000Z",
"change": {
"title": "Senior Engineer"
},
"steps": [
{
"role": "hr",
"state": "approved",
"decided_at": "2026-10-05T09:00:00.000Z",
"comment": null,
"automatic": false
}
]
}
],
"checklists": {
"about_you": [
{
"name": "Onboarding",
"kind": "onboarding",
"status": "completed",
"anchor_date": "2024-03-04",
"started_at": "2024-02-20T10:00:00.000Z",
"tasks": [
{
"title": "Complete your profile",
"due_date": "2024-03-04",
"status": "done",
"skip_reason": null,
"resolved_at": "2024-03-04T09:00:00.000Z",
"comments": [
{
"text": "Done on day one",
"at": "2024-03-04T09:00:00.000Z",
"by_you": true
}
]
}
]
}
],
"assigned_to_you": [
{
"checklist": "Onboarding",
"title": "Plan the first week",
"due_date": "2026-10-31",
"status": "open",
"resolved_at": null
}
],
"your_comments": [
{
"checklist": "Onboarding",
"task": "Plan the first week",
"text": "Agenda shared",
"at": "2026-10-04T10:00:00.000Z"
}
],
"resolved_by_you": [
{
"checklist": "Onboarding",
"task": "Plan the first week",
"status": "done",
"skip_reason": null,
"resolved_at": "2026-10-04T10:00:00.000Z"
}
],
"template_tasks": [
{
"template": "IT onboarding",
"task": "Laptop"
}
]
},
"webhook_deliveries": [
{
"event_type": "person.hired",
"endpoint_host": "hooks.example.com",
"created_at": "2026-10-04T10:01:00.000Z",
"status": "succeeded"
}
],
"documents": [
{
"id": "d1",
"title": "Contract 2026",
"category": "Contract",
"file": "documents/people/p1/d1-Contract 2026.pdf"
}
],
"document_files": [
{
"name": "documents/people/p1/d1-Contract 2026.pdf",
"url": "https://storage.googleapis.com/b/orgs/o1/files/d1?X-Goog-Signature=x"
}
]
}
}Headcount report#
POST/v1/org/reports.headcountRead
Monthly workforce numbers from the job history, from from_month to to_month (YYYY-MM, at most 36 months; default the last 12 months): headcount on the first and last day, FTE at month end, joiners (employment periods starting that month, rehires included), leavers (last day that month) and turnover_rate (leavers / average headcount; null when the average is under one person). The current month is counted as of today. breakdown counts people employed at the end of to_month (or today, if that is earlier), grouped by group_by: unit (default), location, legal_entity, employment_type or contract_type. totals sums the period. planned (when the report reaches today; else null): headcount employed today, open = positions with status open (not drafts or on-hold ones), planned = headcount + open; each breakdown row then also has open, the open positions in that group (null when grouped by employment_type, which positions do not have), and a group with only open positions gets a row with count 0. To list the people behind a number: each month's range (the days counted; the current month ends today) as org_people_list joined_between or left_between; a breakdown group as org_people_list with unit_id, location_id or legal_entity_id, as_of = as_of and status "active" (erased people are counted, anonymously, up to the day before their erase, but never listed). Owners, admins and HR.
- Who can call it
- Manage key owner admin hr
- MCP tool
org_reports_headcounton HR Assistant- Method
POSTwith a JSON body, orGETwith the input as query parameters
Input
from_monthstringPattern
^\d{4}-(0[1-9]|1[0-2])$.to_monthstringPattern
^\d{4}-(0[1-9]|1[0-2])$.group_by"unit" | "location" | "legal_entity" | "employment_type" | "contract_type"Default
"unit".
Returns
8 fields
from_monthstringrequiredto_monthstringrequiredgroup_by"unit" | "location" | "legal_entity" | "employment_type" | "contract_type"requiredas_ofstringrequiredmonthsobject[]required8 fields
monthstringrequiredheadcount_startintegerrequiredheadcount_endintegerrequiredfte_endnumberrequiredjoinersintegerrequiredleaversintegerrequiredturnover_ratenumber | nullrequiredrangeobjectrequired2 fields
fromstringrequiredtostringrequired
breakdownobject[]required5 fields
keystring | nullrequiredlabelstringrequiredcountintegerrequiredftenumberrequiredopeninteger | nullrequired
plannedobject | nullrequired3 fields
headcountintegerrequiredopenintegerrequiredplannedintegerrequired
totalsobjectrequired3 fields
joinersintegerrequiredleaversintegerrequiredturnover_ratenumber | nullrequired
Errors
validation_failed unauthenticated forbidden not_found rate_limited internal
curl https://api.bizisy.com/v1/org/reports.headcount \
-H "Authorization: Bearer $BIZISY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"from_month":"2025-11","to_month":"2026-10","group_by":"location"}'const res = await fetch('https://api.bizisy.com/v1/org/reports.headcount', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.BIZISY_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"from_month": "2025-11",
"to_month": "2026-10",
"group_by": "location"
}),
});
const body = await res.json();
if (!res.ok) throw new Error(`${body.error.code}: ${body.error.message}`);
console.log(body.data);import os
import requests
res = requests.post(
"https://api.bizisy.com/v1/org/reports.headcount",
headers={"Authorization": f"Bearer {os.environ['BIZISY_API_KEY']}"},
json={
"from_month": "2025-11",
"to_month": "2026-10",
"group_by": "location",
},
)
body = res.json()
if not res.ok:
raise RuntimeError(f"{body['error']['code']}: {body['error']['message']}")
print(body["data"]){
"data": {
"from_month": "2025-11",
"to_month": "2026-10",
"group_by": "location",
"as_of": "2026-10-04",
"months": [
{
"month": "2026-09",
"headcount_start": 10,
"headcount_end": 11,
"fte_end": 10.5,
"joiners": 1,
"leavers": 0,
"turnover_rate": 0,
"range": {
"from": "2026-09-01",
"to": "2026-09-30"
}
},
{
"month": "2026-10",
"headcount_start": 11,
"headcount_end": 11,
"fte_end": 10.5,
"joiners": 0,
"leavers": 0,
"turnover_rate": null,
"range": {
"from": "2026-10-01",
"to": "2026-10-04"
}
}
],
"breakdown": [
{
"key": "u2",
"label": "Engineering",
"count": 6,
"fte": 5.5,
"open": 2
},
{
"key": null,
"label": "None",
"count": 5,
"fte": 5,
"open": 0
}
],
"totals": {
"joiners": 1,
"leavers": 0,
"turnover_rate": 0
},
"planned": {
"headcount": 11,
"open": 2,
"planned": 13
}
}
}Something missing or wrong on this page? Write to hello@bizisy.com.