Users
The people directory: who works in this company, in what roles, under which supervisor. Built for syncing from an HR system (an “HRIS”: Personio, Workday, BambooHR and the like), where that system is the source of record for who works here: it replays the employee list and this endpoint converges Hivebuy to match. This is the /api/v2/ successor to the legacy /api/company/user-sync/ endpoint, the write is the same batch upsert with the same payload, so an existing integration can move by changing the URL. Reads list the URL company's members; the batch write provisions, updates, deactivates and re-addresses people.
Understand the size of this grant. master-data:write on this route assigns roles, and roles include O (OWNER, company admin). An HR system is the system of record for who works here and in what capacity, so that is the point of the endpoint, not a side effect, but it means the scope should be treated as "manage people", not "edit reference lists". Every role change is audit-logged with the acting API key.
How an item is matched
Everything keys off email (required, matched case-insensitively, login emails are unique across the platform). Each item walks this ladder:
- Email-change mode. An item carrying
newEmailis not an upsert: it moves an existing user's login to a new address and touches nothing else. The target must hold an active membership of the URL company, a user outside it answersUser not found., deliberately indistinguishable from a user that does not exist. - An existing user with that email is updated: the profile fields you sent, plus
rolesandsupervisoron their membership of the URL company. If the user's home company is a sibling in your tenant, an active membership of the URL company is created, that is how one HR-system feed staffs several companies. If it is in a different tenant, the item fails (User belongs to a company in a different tenant.). - A pending invitation for that email in the URL company is updated (roles, departments), and the person keeps their original invite link.
- Nothing matched: create. By default an invitation is created and the person signs themselves up. With
createUser: truethe user row is created immediately, no invite step, and exported to the identity provider, the mode for an HR system that owns onboarding.
Items are processed in two phases, every item is validated first, then the valid ones are written, each in its own transaction. Two consequences worth knowing: one bad item never fails the batch, and an item can not reference a supervisor or department that an earlier item in the same batch just created. Send dependencies in an earlier request.
The sharp edges, stated plainly
rolesomitted means[], and[]strips roles. The update path applies the role set on every item, so always send the person's complete role set, never a delta.- The last OWNER is protected. An item that would leave the company with no active OWNER (by omitting
rolesor sending a set withoutO) is refused per-item. isActive: falsedeactivates the login, not just this company's membership.- An unresolvable
supervisoris silently ignored, not an error, a legacy behaviour this route preserves. Verify supervisors landed by reading back.
Roles
O OWNER (company admin) · MD MANAGING DIRECTOR · AC ACCOUNTANT · BU BUYER · AP APPROVER · AL APPROVER_LIMITED · CO CONTRACT_OWNER · AU API_USER · CR CONTROLLER · NA NEWS_ADMIN · AD AUDITOR · LA LEGALENTITYACCOUNTANT. An empty set means a basic user.
Batch response semantics
Up to 50 items; a longer list is refused whole with 400 naming the limit (the legacy route silently truncated, this one does not). Otherwise: 200 with an empty body when every item succeeded, 200 with the error list on partial success, 400 with the error list when every item failed. The error list is the legacy shape, kept verbatim because existing integrations parse it: a top-level JSON array with one entry per failed item, a single error object for most failures, but an array of error objects for an item that failed several validations at once.
Operations
Reads need master-data:read, the batch write master-data:write. There is no update or delete verb, an HR system upserts; it never deletes a person.
- GET
/api/v2/{companyId}/users/: the URL company's members, ordered by email.rolesandsupervisorare that company's membership values, service accounts are excluded, and deactivated members are included, an HR system needs to see who it deactivated. - GET
/api/v2/{companyId}/users/{id}/: one member. - POST
/api/v2/{companyId}/users/: the batch upsert described above.
Endpoints
/api/v2/{companyId}/users/?page=1&pageSize=25&fields=&omit=
/api/v2/{companyId}/users/
/api/v2/{companyId}/users/{id}/