A reference guide for building AI agents: every method, how to authenticate, and the permissions each one needs.
The Personio API is how an app or AI agent works with a company's HR records: listing and updating employees, logging and editing attendances, booking and cancelling time off, uploading documents, and pulling saved reports. Access is granted through an API credential that an admin turns on area by area as read or write, and narrows further to a chosen set of employee fields, so a credential can only ever see and change what it was set up for. Personio can also push a notification to a webhook when a record changes, instead of being polled.
How an app or AI agent connects to Personio decides what it can reach. Access runs through one route, an API credential made of a client id and client secret that is exchanged for a short-lived bearer token, and that credential carries exactly the areas and the employee attributes an admin chose for it when it was created.
The v1 Personnel Data API answers at api.personio.de/v1/company. Responses are JSON, wrapped in a success flag plus a data array and pagination metadata. This is the stable, broadly used generation and the subject of this reference.
A newer v2 line adds person, attendance, and absence endpoints with its own auth and token revocation, and is where new features land. It runs in parallel with v1 and is the migration target for the deprecated v1 Attendances and Projects endpoints.
Webhooks deliver a notification when a record changes, removing the need to poll. A subscription is registered against a chosen event, and Personio posts the change to a receiver URL when it happens. The webhook scope, read or write, must be present on the credential.
An API credential, a client id and client secret, is posted to the auth endpoint and exchanged for a bearer token valid for 24 hours. Stable tokens begin with a papi- prefix, and the current token is returned in the response header of each successful call so it can be rotated without re-authenticating. The credential carries the areas and attributes an admin granted it.
The Personio API is split into areas an agent can act on, such as employee records, attendances, day-based time off, hourly absence periods, documents, and saved reports. Each area is turned on per credential as read, write, or both, and the employee fields a credential can see or change are whitelisted one by one, so two credentials against the same company can have very different reach.
List employees, read one by id, create and update employees, and read an employee's leave allowance.
List logged attendance periods, add new ones for one or many employees, and update or delete a period.
List day-based time off, read one by id, book a new request, delete one, and list the available time off types.
List the document categories available in the account and upload a file to an employee under a category.
List the saved custom reports, read a report's data by id, and list the columns a report can return.
Filter by method, access, or permission, or search any path. Select a row for version detail, rate limits, the related webhook event, and the source.
| Method | Endpoint | What it does | Access | Permission | Version | |
|---|---|---|---|---|---|---|
EmployeesList employees, read one by id, create and update employees, and read an employee's leave allowance.5 | ||||||
| GET | /v1/company/employees | List company employees, with pagination and an optional filter on email or updated date. | read | Employees: read | Current | |
Needs the employees area set to read on the credential. Only the employee attributes whitelisted on the credential are returned; any field not granted is omitted from each record. Acts onemployee Permission (capability) Employees: readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /v1/company/employees/{employee_id} | Get a single employee record by id. | read | Employees: read | Current | |
Needs the employees area set to read. Which fields come back depends on the readable attributes whitelisted on the credential; restricted fields are omitted rather than refused. Acts onemployee Permission (capability) Employees: readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /v1/company/employees | Create a new employee, with status set automatically from the hire date if not supplied. | write | Employees: write | Current | |
Needs the employees area set to write. Only attributes whitelisted as writable on the credential can be set; a supervisor must reference an existing employee id. Acts onemployee Permission (capability) Employees: writeVersionAvailable since the API’s base version Webhook event employee_changedRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PATCH | /v1/company/employees/{employee_id} | Update an employee, changing only the fields included in the request body. | write | Employees: write | Current | |
Needs the employees area set to write. Only attributes whitelisted as writable can be changed; the email field cannot be updated through this endpoint. Acts onemployee Permission (capability) Employees: writeVersionAvailable since the API’s base version Webhook event employee_changedRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /v1/company/employees/{employee_id}/absences/balance | Get an employee's current leave allowance, broken down by time off type. | read | Employees: read | Current | |
Needs the employees area set to read. Returns the remaining balance per time off type for the named employee. Acts onabsence balance Permission (capability) Employees: readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
AttendancesList logged attendance periods, add new ones for one or many employees, and update or delete a period.4 | ||||||
| GET | /v1/company/attendances | List attendance periods in a date range, optionally filtered by employee. | read | Attendances: read | Deprecated | |
Needs the attendances area set to read. This v1 endpoint is deprecated with a final date of 30 August 2026; the v2 attendance-periods endpoints are the replacement. Acts onattendance period Permission (capability) Attendances: readVersionDeprecated 2026-01-31 · Sunset 2026-08-30 Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /v1/company/attendances | Add one or more attendance periods, each with an employee, date, start and end times, and break. | write | Attendances: write | Deprecated | |
Needs the attendances area set to write. Accepts a list, so several employees can be logged in one call. Deprecated v1 endpoint, final date 30 August 2026. Acts onattendance period Permission (capability) Attendances: writeVersionDeprecated 2026-01-31 · Sunset 2026-08-30 Webhook event attendance_changedRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PATCH | /v1/company/attendances/{id} | Update an existing attendance period by id. | write | Attendances: write | Deprecated | |
Needs the attendances area set to write. Deprecated v1 endpoint, final date 30 August 2026; migrate to the v2 attendance-periods endpoints. Acts onattendance period Permission (capability) Attendances: writeVersionDeprecated 2026-01-31 · Sunset 2026-08-30 Webhook event attendance_changedRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| DELETE | /v1/company/attendances/{id} | Delete an attendance period by id. | write | Attendances: write | Deprecated | |
Needs the attendances area set to write. The removal cannot be undone. Deprecated v1 endpoint, final date 30 August 2026. Acts onattendance period Permission (capability) Attendances: writeVersionDeprecated 2026-01-31 · Sunset 2026-08-30 Webhook event attendance_changedRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
Time offList day-based time off, read one by id, book a new request, delete one, and list the available time off types.5 | ||||||
| GET | /v1/company/time-off-types | List the time off types defined in the account, such as vacation or sick leave. | read | Absences: read | Current | |
Needs the time off area set to read. Returns each type's id and name, needed before booking a time off against a type. Acts ontime off type Permission (capability) Absences: readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /v1/company/time-offs | List day-based time off periods, paginated and filtered by date range or employee. | read | Absences: read | Current | |
Needs the time off area set to read. Covers absences measured in whole days; hourly absences are handled by the absence-periods endpoints. Acts ontime off period Permission (capability) Absences: readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /v1/company/time-offs/{id} | Get a single day-based time off period by id. | read | Absences: read | Current | |
Needs the time off area set to read. Returns the period's dates, type, and the employee it belongs to. Acts ontime off period Permission (capability) Absences: readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /v1/company/time-offs | Book a day-based time off for an employee against a chosen time off type. | write | Absences: write | Current | |
Needs the time off area set to write. Requires an employee id, a time off type id, and a start and end date; this creates real leave on the record. Acts ontime off period Permission (capability) Absences: writeVersionAvailable since the API’s base version Webhook event absence_changedRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| DELETE | /v1/company/time-offs/{id} | Delete a day-based time off period by id. | write | Absences: write | Current | |
Needs the time off area set to write. Cancels real leave for the employee, and the removal cannot be undone. Acts ontime off period Permission (capability) Absences: writeVersionAvailable since the API’s base version Webhook event absence_changedRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
DocumentsList the document categories available in the account and upload a file to an employee under a category.2 | ||||||
| GET | /v1/company/document-categories | List the document categories configured in the account. | read | Documents: read | Current | |
Needs the documents area set to read. Returns each category's id and name, needed to pick a category before uploading a file. Acts ondocument category Permission (capability) Documents: readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /v1/company/documents | Upload a document to an employee under a chosen category, sent as a multipart form post. | write | Documents: write | Current | |
Needs the documents area set to write. The request must be multipart/form-data with the file, the employee id, and a category id. This endpoint carries its own separate rate limit because uploads are heavier than ordinary calls. Acts ondocument Permission (capability) Documents: writeVersionAvailable since the API’s base version Webhook eventNone Rate limit60 requests per minute SourceOfficial documentation ↗ | ||||||
ReportsList the saved custom reports, read a report's data by id, and list the columns a report can return.3 | ||||||
| GET | /v1/company/custom-reports/reports | List the saved custom reports available to the credential. | read | Employees: read | Current | |
Needs read access to the underlying areas a report draws on. Returns each report's id and metadata; the reports listed are those the credential can access. Acts onreport Permission (capability) Employees: readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /v1/company/custom-reports/reports/{report_id} | Pull the data of a saved custom report by its id. | read | Employees: read | Current | |
Needs read access to the areas the report draws on. A report can return whole-company data in one call, so the credential's whitelisted attributes bound which columns it sees. Acts onreport Permission (capability) Employees: readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /v1/company/custom-reports/columns | List the column labels that custom reports can return. | read | Employees: read | Current | |
Needs read access. Returns the set of column labels available, used to interpret the columns a report returns. Acts onreport column Permission (capability) Employees: readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
Personio can notify an app or AI agent when an employee record, an attendance, or an absence changes, instead of the app repeatedly asking. A subscription is registered against a chosen event, and Personio posts the change to a receiver URL when it happens. The webhook scope, read or write, must be present on the credential that manages subscriptions.
| Event | What it signals | Triggered by |
|---|---|---|
Employee created or updated | Fires when an employee record is created or changed. The subscription posts the change to a receiver URL, and only reports data the subscribing credential is permitted to see. | /v1/company/employees/v1/company/employees/{employee_id} |
Attendance created, updated, or deleted | Fires when an attendance period is added, changed, or removed. The subscription posts the change to a receiver URL for the events the credential is allowed to receive. | /v1/company/attendances/v1/company/attendances/{id}/v1/company/attendances/{id} |
Absence created or deleted | Fires when a time off period is booked or cancelled. The subscription posts the change to a receiver URL, bounded by what the credential can see. | /v1/company/time-offs/v1/company/time-offs/{id} |
Personio limits how often a credential can call the API and answers a call that goes over with a 429 status. The limit is counted per credential, with a separate, larger ceiling counted per source IP address on the v1 endpoints, and the authentication endpoint has its own tighter limit.
Personio limits how often a credential can call the API and returns a 429 status when a call exceeds the limit, with X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers describing the current state. The limit is counted per credential, and there is a separate, larger ceiling of 2000 requests per minute counted per source IP address on the v1 endpoints. The authentication endpoint is limited more tightly, to 60 requests per minute, after which there is a 60 second cool-down before a new token can be requested. The practical model is to read the rate-limit headers and back off on a 429 rather than to assume a single fixed number across every endpoint.
List endpoints page with limit and offset query parameters and return a metadata block alongside the data, carrying the total number of elements, the current page, and the total page count. The default page size and ceiling vary by endpoint, so an integration should read the metadata to know how many pages remain rather than assuming a fixed size.
Requests and responses are JSON. Documents are uploaded as multipart/form-data against the documents endpoint, attaching a file to an employee under a chosen category. No single overall payload size limit is documented across the v1 API; the documents endpoint carries its own separate rate limit because uploads are heavier than ordinary calls.
The status codes an agent should handle, and what to do about each.
| Status | Code | Meaning | What to do |
|---|---|---|---|
| 400 | Bad Request | The request was malformed, such as an invalid parameter or a body that could not be parsed. | Check the parameters and body against the endpoint reference and resend. The body carries success false with an error code and message. |
| 401 | Unauthorized | The bearer token is missing, expired, or invalid. | Exchange the API credential for a fresh token at the auth endpoint, then retry with the new token in the Authorization header. |
| 403 | Forbidden | The token is valid but the credential lacks the area or attribute the request needs. | Widen the credential's scopes or whitelisted attributes in the API credential wizard to cover the request. |
| 404 | Not Found | The resource does not exist, or the path is wrong. | Confirm the employee id, time off id, or report id, and the path, then retry. |
| 429 | Too Many Requests | The rate limit was exceeded for the credential or the source IP address. | Read the X-RateLimit-Reset header, wait until the window resets, and back off before retrying. |
| 500 | Internal Server Error | An unexpected error occurred inside Personio. | Retry after a short pause, and contact Personio support if it persists. |
Personio runs two API generations side by side. The v1 Personnel Data API, carried in the request path, is the stable, broadly used one and the subject of this reference; a newer v2 line adds person, attendance, and absence endpoints with their own auth and is where new features land. Both are versioned by path, not by a dated header.
Personio versions by path. The v1 Personnel Data API is the stable, broadly used generation and the subject of this reference. It does not mint dated versions; changes ship continuously and are recorded in the changelog. The dated entries below are notable recent changes, newest first.
A status filter was added to the v2 list persons endpoint, letting an integration filter by employment status.
Webhooks for the Person entity were made available to all customers with Public API access, so an app can be notified of employee changes instead of polling.
Stable tokens with a papi- prefix were introduced, valid for 24 hours and returned in the response header of each successful call so an integration can rotate the token without re-authenticating.
A rate limit of 2000 requests per minute, counted per source IP address, was added on the v1 endpoints in addition to the per-credential limit.
This reference covers the v1 Personnel Data API. The v1 Attendances and Projects endpoints are deprecated with a final date of 30 August 2026; the v2 line is their replacement. Track the changelog for migration deadlines.
Personio API changelog ↗Bollard AI sits between a team's AI agents and Personio. Grant each agent exactly the access it needs, read or write, area by area, and every call is checked and logged.