> **Building with AI coding agents?** Install the authstack plugin with one command. This equips your agent with accurate Scalekit implementation patterns.
>
> **Recommended** (the `-y` flags skip prompts, so the command runs without an interactive terminal):
> ```bash
> npx -y @scalekit-inc/cli setup -y
> ```
>
> Global:
> ```bash
> npm install -g @scalekit-inc/cli
> scalekit setup -y
> ```
>
> Supports Claude Code, Cursor, GitHub Copilot, Codex + skills for other Agent Skills-compatible agents in `~/.agents/skills`.
> Skills: integrate-agentkit, implement-saaskit, add-mcp-oauth, implement-sso, implement-scim.
> [Full setup guide](https://docs.scalekit.com/dev-kit/build-with-ai/)

---

# Connect AI agents to Personio

The Personio connector lets your AI agent act in each user's Personio account. Each user signs in to Personio once, and Scalekit stores and refreshes their tokens, so your agent never handles credentials. It comes with 53 tools.

**Authentication:** API Credentials (OAuth 2.0 Client Credentials)
**Categories:** Productivity, Accounting & Finance
**Tools:** 53: 39 read, 14 write, 0 destructive
**Users sign in with:** Service account
**Built by:** Scalekit connector
**Try it:** [Playground in the Scalekit dashboard](https://app.scalekit.com/ws/signup?sk_intent=playground&provider=PERSONIO)

## Setup

1. ### Install the SDK

   **Node.js**

   ```bash
   npm install @scalekit-sdk/node dotenv
   ```

   **Python**

   ```bash
   pip install scalekit-sdk-python python-dotenv
   ```

2. ### Set your credentials

   Add your Scalekit credentials to your `.env` file. Find values in **[app.scalekit.com](https://app.scalekit.com)** > **Developers** > **API Credentials**.

   ```sh title=".env"
   SCALEKIT_ENVIRONMENT_URL=<your-environment-url>
   SCALEKIT_CLIENT_ID=<your-client-id>
   SCALEKIT_CLIENT_SECRET=<your-client-secret>
   ```

3. ### Create the Personio connection

   In **AgentKit > Connections**, create a Personio connection. The name you give it is the `connection_name` your code passes. See [Configure connections](/agentkit/connections/).

## Tools

Pass the exact name to `execute_tool`, with an input like each tool's example. To ask for a tool that's missing, use the [request form](https://scalekitsupport.portal.usepylon.com/forms/request-a-connector-tool).

**Node.js**

```typescript
const result = await actions.executeTool({
  toolName: 'personio_absence_period_breakdown_list',
  toolInput: {
    absence_period_id: '<absence_period_id>',
  },
  connector: 'personio',
  identifier: 'user_123',
})
```

**Python**

```python
result = actions.execute_tool(
    tool_name="personio_absence_period_breakdown_list",
    tool_input={
        "absence_period_id": "<absence_period_id>",
    },
    connection_name="personio",
    identifier="user_123",
)
```

`result.data` is the app's response as JSON, and `result.execution_id` (`executionId` in Node.js) is the ID of the call.

### `personio_absence_period_breakdown_list`

List Absence Period Breakdowns · Read-only

List the day-by-day breakdown of one absence period in Personio.
Returns one entry per day with the date and the effective duration of the absence on that day.
Use this to see how much time an absence actually takes on each day. Use personio_absence_period_get for the absence itself.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `absence_period_id` (`string`, required): The ID of the absence period. Get it from personio_absence_period_list. Example: 493eff0a-2c5a-467e-8966-f70b4e3805a6.
- `cursor` (`string`, optional): Pagination cursor for the breakdowns list. Leave empty for the first page. To get the next page, pass the cursor from the previous response's _meta.links.next.href (the value of its cursor query parameter). Example: cur_82sQwR2eZvKilo2duNh219Kw.
- `limit` (`integer`, optional): Maximum number of daily breakdowns to return in one page, from 1 to 100. Leave empty to use the Personio default of 28. Example: 50.

Example input: `{"absence_period_id":"<absence_period_id>"}`

### `personio_absence_period_get`

Get Absence Period · Read-only

Get one absence period in Personio by ID.
Returns the person, absence type, start and end (date-time and half-day type), timezone, comment, approval status and timestamps.
Use this when you have the absence period ID. Use personio_absence_period_list to search.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `absence_period_id` (`string`, required): The ID of the absence period. Get it from personio_absence_period_list. Example: 493eff0a-2c5a-467e-8966-f70b4e3805a6.

Example input: `{"absence_period_id":"<absence_period_id>"}`

### `personio_absence_period_list`

List Absence Periods · Read-only

List absence periods (time off such as vacation or sick leave) in Personio, filtered by person, absence type, date range or update time.
Returns a page of absence periods with id, person, absence type, start and end (date-time and half-day type), timezone, comment, approval status and timestamps.
Use this to see who is or was off and when. Use personio_absence_period_get for one known absence period.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `absence_type_id` (`string`, optional): Only return absences of these absence types. Separate multiple IDs with commas; get them from personio_absence_type_list. Example: cba6fa09-d8fe-4de0-be03-f0a1d48df766.
- `cursor` (`string`, optional): Pagination cursor for the absence periods list. Leave empty for the first page. To get the next page, pass the cursor from the previous response's _meta.links.next.href (the value of its cursor query parameter). Example: cur_82sQwR2eZvKilo2duNh219Kw.
- `ends_at_gte` (`string`, optional): Only return absences ending at or after this date-time (RFC 3339). Example: 2025-01-01T00:00:00Z.
- `ends_at_lte` (`string`, optional): Only return absences ending at or before this date-time (RFC 3339). Example: 2025-12-31T23:59:59Z.
- `id` (`string`, optional): Only return absence periods with these IDs. Separate multiple IDs with commas. Example: abc6fa09-d8fe-4de0-be03-f0a1d48df766.
- `limit` (`integer`, optional): Maximum number of absence periods to return in one page, from 1 to 100. Leave empty to use the Personio default of 100. Example: 50.
- `person_id` (`string`, optional): Only return absences of these persons. Separate multiple person IDs with commas. Example: 12345,67890.
- `starts_from_gte` (`string`, optional): Only return absences starting at or after this date-time (RFC 3339). Example: 2025-01-01T00:00:00Z.
- `starts_from_lte` (`string`, optional): Only return absences starting at or before this date-time (RFC 3339). Example: 2025-12-31T23:59:59Z.
- `updated_at_gte` (`string`, optional): Only return absences updated at or after this date-time (RFC 3339). Example: 2025-06-01T00:00:00Z.
- `updated_at_lte` (`string`, optional): Only return absences updated at or before this date-time (RFC 3339). Example: 2025-06-30T23:59:59Z.

Example input: `{}`

### `personio_absence_type_get`

Get Absence Type · Read-only

Get one absence type in Personio by ID.
Returns the absence type's id, name, category and unit (DAY for days and half days, HOUR for hourly absences).
Use this to check whether a type is booked in days or hours before creating an absence. Use personio_absence_type_list to find the ID.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `absence_type_id` (`string`, required): The ID of the absence type. Get it from personio_absence_type_list. Example: 137a2048-41e9-4d49-9201-e6a032521495.

Example input: `{"absence_type_id":"<absence_type_id>"}`

### `personio_absence_type_list`

List Absence Types · Read-only

List the absence types configured in Personio, such as paid vacation or sick leave.
Returns a page of absence types with their id, name, category and unit (DAY or HOUR).
Use this to find the absence type ID needed by personio_absence_period_create. Use personio_absence_type_get for one known type.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `cursor` (`string`, optional): Pagination cursor for the absence types list. Leave empty for the first page. To get the next page, pass the cursor from the previous response's _meta.links.next.href (the value of its cursor query parameter). Example: cur_82sQwR2eZvKilo2duNh219Kw.
- `limit` (`integer`, optional): Maximum number of absence types to return in one page, from 1 to 100. Leave empty to use the Personio default of 100. Example: 50.

Example input: `{}`

### `personio_attendance_period_get`

Get Attendance Period · Read-only

Get one attendance period (tracked work or break) in Personio by ID.
Returns the person, type, start, end, duration, attribution date, approval status, project and comment.
Use this when you have the attendance period ID. Use personio_attendance_period_list to search.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `attendance_period_id` (`string`, required): The ID of the attendance period. Get it from personio_attendance_period_list. Example: bd242cd1-5116-41a0-99aa-c12af4837c81.

Example input: `{"attendance_period_id":"<attendance_period_id>"}`

### `personio_attendance_period_list`

List Attendance Periods · Read-only

List attendance periods (tracked working time and breaks) in Personio, filtered by person, project, status, date range or update time.
Returns a page of attendance periods with id, person, type (WORK or BREAK), start, end, duration, attribution date, approval status, project and comment.
Use this to review tracked hours. Use personio_attendance_period_get for one known period.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `attribution_date_gte` (`string`, optional): Only return periods attributed to this date or later (YYYY-MM-DD). Example: 2025-01-01.
- `attribution_date_lte` (`string`, optional): Only return periods attributed to this date or earlier (YYYY-MM-DD). Example: 2025-01-31.
- `cursor` (`string`, optional): Pagination cursor for the attendance periods list. Leave empty for the first page. To get the next page, pass the cursor from the previous response's _meta.links.next.href (the value of its cursor query parameter). Example: cur_82sQwR2eZvKilo2duNh219Kw.
- `end_gte` (`string`, optional): Only return periods ending at or after this time, as a local date-time without a timezone offset (YYYY-MM-DDTHH:MM:SS). Example: 2025-01-01T00:00:00.
- `end_lte` (`string`, optional): Only return periods ending at or before this time, as a local date-time without a timezone offset (YYYY-MM-DDTHH:MM:SS). Example: 2025-01-31T23:59:59.
- `id` (`array`, optional): Only return attendance periods with these IDs. Example: ["bd242cd1-5116-41a0-99aa-c12af4837c81"].
- `limit` (`integer`, optional): Maximum number of attendance periods to return in one page, from 1 to 100. Leave empty to use the Personio default of 100. Example: 50.
- `person_id` (`array`, optional): Only return attendance periods of these persons. Example: ["12345", "67890"].
- `project_id` (`array`, optional): Only return attendance periods booked on these projects. Example: ["1234"].
- `sort` (`string`, optional): Comma-separated sort fields; prefix a field with - for descending. Allowed fields: person.id, start.date_time, end.date_time, updated_at, status. Default: person.id,start.date_time,end.date_time. Example: -start.date_time.
- `start_gte` (`string`, optional): Only return periods starting at or after this time, as a local date-time without a timezone offset (YYYY-MM-DDTHH:MM:SS). Example: 2025-01-01T00:00:00.
- `start_lte` (`string`, optional): Only return periods starting at or before this time, as a local date-time without a timezone offset (YYYY-MM-DDTHH:MM:SS). Example: 2025-01-31T23:59:59.
- `status` (`string`, optional): Only return attendance periods with this approval status. Example: CONFIRMED. One of: `PENDING`, `CONFIRMED`, `REJECTED`.
- `updated_at_gte` (`string`, optional): Only return periods updated at or after this date-time (RFC 3339). Example: 2025-06-01T00:00:00Z.
- `updated_at_lte` (`string`, optional): Only return periods updated at or before this date-time (RFC 3339). Example: 2025-06-30T23:59:59Z.

Example input: `{}`

### `personio_compensation_list`

List Compensations · Read-only

List payroll compensations in Personio for a period of up to one month, optionally for specific people or legal entities.
Returns a page of compensations with id, person, legal entity, compensation type, amount and currency, interval, effective date and working hours, covering base salary, hourly pay, one-time and recurring payments and bonuses.
Use this for payroll reviews. Use personio_compensation_create to add a compensation.
Needs a credential with the personio:compensations:read scope.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `cursor` (`string`, optional): Pagination cursor for the compensations list. Leave empty for the first page. To get the next page, pass the cursor from the previous response's _meta.links.next.href (the value of its cursor query parameter). Example: cur_82sQwR2eZvKilo2duNh219Kw.
- `end_date` (`string`, optional): Last day of the period (YYYY-MM-DD). The period can be at most one month. Defaults to the last day of the current month, or of start_date's month. Example: 2025-01-31.
- `legal_entity_id` (`string`, optional): Only return compensations of people in these legal entities. Separate multiple IDs with commas. Example: 123.
- `limit` (`integer`, optional): Maximum number of compensations to return in one page, from 1 to 100. Leave empty to use the Personio default of 100. Example: 50.
- `person_id` (`string`, optional): Only return compensations of these persons. Separate multiple IDs with commas. Example: 12345,67890.
- `start_date` (`string`, optional): First day of the period (YYYY-MM-DD). The period from start_date to end_date can be at most one month. Defaults to the first day of the current month, or of end_date's month. Example: 2025-01-01.

Example input: `{}`

### `personio_compensation_type_list`

List Compensation Types · Read-only

List the compensation types configured in Personio, including one-time and recurring types.
Returns a page of compensation types with id, name and category.
Use this to find the type ID needed by personio_compensation_create. Use personio_compensation_type_create to add a new type.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `cursor` (`string`, optional): Pagination cursor for the compensation types list. Leave empty for the first page. To get the next page, pass the cursor from the previous response's _meta.links.next.href (the value of its cursor query parameter). Example: cur_82sQwR2eZvKilo2duNh219Kw.
- `limit` (`integer`, optional): Maximum number of compensation types to return in one page, from 1 to 100. Leave empty to use the Personio default of 100. Example: 50.

Example input: `{}`

### `personio_cost_center_list`

List Cost Centers · Read-only

List the cost centers of the Personio account, optionally filtered by ID or name.
Returns a page of cost centers with id and name.
Use this to find cost center IDs for employments or projects.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `cursor` (`string`, optional): Pagination cursor for the cost centers list. Leave empty for the first page. To get the next page, pass the cursor from the previous response's _meta.links.next.href (the value of its cursor query parameter). Example: cur_82sQwR2eZvKilo2duNh219Kw.
- `id` (`string`, optional): Only return cost centers with these IDs. Separate multiple IDs with commas. Example: 123,456.
- `limit` (`integer`, optional): Maximum number of cost centers to return in one page, from 1 to 100. Leave empty to use the Personio default of 50. Example: 50.
- `name` (`string`, optional): Only return cost centers with these names. Separate multiple names with commas. Example: Sales,IT.
- `sort` (`string`, optional): Comma-separated sort fields, name and/or id; prefix with - for descending. Default: id ascending. Example: name,-id.

Example input: `{}`

### `personio_document_list`

List Documents · Read-only

List the metadata of documents stored in Personio for one owner (a person), optionally filtered by category or creation date. File contents are not returned.
Returns a page of documents with id, name, date, comment, category, owner, file type, size, creation time, virus scan status and e-signature status.
Use this to see which documents an employee has. Use personio_document_update to rename or recategorize one.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `owner_id` (`string`, required): ID of the person who owns the documents. Get it from personio_person_list. Example: 12345.
- `category_id` (`string`, optional): Only return documents in this document category. Example: 123.
- `created_at_gte` (`string`, optional): Only return documents created on or after this date (YYYY-MM-DD). Example: 2025-03-25.
- `created_at_lt` (`string`, optional): Only return documents created before this date (YYYY-MM-DD); documents created on this date are excluded. Example: 2025-03-26.
- `cursor` (`string`, optional): Pagination cursor for the documents list. Leave empty for the first page. To get the next page, pass the cursor from the previous response's _meta.links.next.href (the value of its cursor query parameter). Example: cur_82sQwR2eZvKilo2duNh219Kw.
- `limit` (`integer`, optional): Maximum number of documents to return in one page, from 1 to 200. Leave empty to use the Personio default of 100. Example: 50.

Example input: `{"owner_id":"<owner_id>"}`

### `personio_employment_get`

Get Employment · Read-only

Get one employment of a person in Personio by ID.
Returns the employment's status, position, type, dates, working hours, supervisor, office, org units, legal entity, job, cost centers and termination details.
Use this when you have both the person ID and employment ID. Use personio_employment_list to find the employment ID.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `employment_id` (`string`, required): The ID of the employment. Get it from personio_employment_list. Example: 493eff0a-2c5a-467e-8966-f70b4e3805a6.
- `person_id` (`string`, required): The ID of the person. Example: 12345.

Example input: `{"employment_id":"<employment_id>","person_id":"<person_id>"}`

### `personio_employment_list`

List Employments · Read-only

List the employments of one person in Personio, most recent first.
Returns a page of employments with id, status, position, type, start, end and probation dates, working hours, supervisor, office, org units, legal entity, job, cost centers and termination details.
Use this to see a person's employment history or find an employment ID. Use personio_employment_get for one known employment.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `person_id` (`string`, required): The ID of the person whose employments to list. Get it from personio_person_list. Example: 12345.
- `cursor` (`string`, optional): Pagination cursor for the employments list. Leave empty for the first page. To get the next page, pass the cursor from the previous response's _meta.links.next.href (the value of its cursor query parameter). Example: cur_82sQwR2eZvKilo2duNh219Kw.
- `id` (`string`, optional): Only return employments with these IDs. Separate multiple IDs with commas. Example: 493eff0a-2c5a-467e-8966-f70b4e3805a6.
- `limit` (`integer`, optional): Maximum number of employments to return in one page, from 1 to 50. Leave empty to use the Personio default of 10. Example: 50.
- `updated_at_gt` (`string`, optional): Only return employments updated after this date-time (RFC 3339). Example: 2024-06-01T00:00:00Z.
- `updated_at_lt` (`string`, optional): Only return employments updated before this date-time (RFC 3339). Example: 2024-06-30T23:59:59Z.

Example input: `{"person_id":"<person_id>"}`

### `personio_job_get`

Get Job · Read-only

Get one job from Personio's job catalogue by UUID.
Returns the job's id, name, job family, level, job track and linked salary band IDs.
Use this when you have a job ID, for example from an employment. Use personio_job_list to browse the catalogue.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `job_id` (`string`, required): The ID of the job (UUID). Get it from personio_job_list. Example: a1b2c3d4-e5f6-7890-abcd-ef1234567890.

Example input: `{"job_id":"<job_id>"}`

### `personio_job_list`

List Jobs · Read-only

List the jobs in Personio's job catalogue (internal job definitions linked to employments and salary bands, not recruiting job postings), optionally filtered by ID or name.
Returns a page of jobs with their id, name, job family, level, job track and linked salary band IDs.
Use this to find a job ID for an employment. Use personio_recruiting_job_list for open positions in recruiting.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `cursor` (`string`, optional): Pagination cursor for the jobs list. Leave empty for the first page. To get the next page, pass the cursor from the previous response's _meta.links.next.href (the value of its cursor query parameter). Example: cur_82sQwR2eZvKilo2duNh219Kw.
- `id` (`string`, optional): Only return jobs with these UUIDs. Separate multiple IDs with commas. Example: a1b2c3d4-e5f6-7890-abcd-ef1234567890.
- `limit` (`integer`, optional): Maximum number of jobs to return in one page, from 1 to 100. Leave empty to use the Personio default of 50. Example: 50.
- `name` (`string`, optional): Only return jobs with these names. Separate multiple names with commas. Example: Software Engineer,Product Manager.
- `sort` (`string`, optional): Comma-separated sort fields, name and/or id; prefix with - for descending. Default: id descending. Example: name.

Example input: `{}`

### `personio_legal_entity_get`

Get Legal Entity · Read-only

Get one legal entity (employing company) in Personio by ID.
Returns the entity's status, country, name, type, registration number, industry, contact person, addresses and bank details.
Use this when you have the legal entity ID. Use personio_legal_entity_list to browse entities.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `legal_entity_id` (`string`, required): The ID of the legal entity. Get it from personio_legal_entity_list. Example: 123.

Example input: `{"legal_entity_id":"<legal_entity_id>"}`

### `personio_legal_entity_list`

List Legal Entities · Read-only

List the legal entities (employing companies) of the Personio account, newest first.
Returns a page of legal entities with id, status, main-entity flag, country, name, type, registration number, industry, contact details, addresses and bank details.
Use this to find a legal entity ID. Use personio_legal_entity_get for one known entity.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `country` (`string`, optional): Only return legal entities registered in these countries, as ISO 3166-1 alpha-2 codes separated by commas. This is the entity's country, not its address country. Example: DE,IE.
- `cursor` (`string`, optional): Pagination cursor for the legal entities list. Leave empty for the first page. To get the next page, pass the cursor from the previous response's _meta.links.next.href (the value of its cursor query parameter). Example: cur_82sQwR2eZvKilo2duNh219Kw.
- `id` (`string`, optional): Only return legal entities with these IDs. Separate multiple IDs with commas. Example: 123,456.
- `limit` (`integer`, optional): Maximum number of legal entities to return in one page, from 1 to 100. Leave empty to use the Personio default of 20. Example: 50.

Example input: `{}`

### `personio_org_unit_get`

Get Org Unit · Read-only

Get one org unit (department or team) in Personio by ID and type.
Returns the unit's name, abbreviation, description, parent id, creation time and leads, and optionally its full parent chain.
Use this when you have the org unit ID, for example from an employment. Use personio_org_unit_list to browse units.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `org_unit_id` (`integer`, required): ID of the org unit, for example from an employment's org_units or another unit's parent_id. Example: 1234.
- `type` (`string`, required): Type of the org unit, for example department or team. Example: department.
- `include_parent_chain` (`boolean`, optional): Set to true to include the full details of each parent unit up the chain. Example: true.

Example input: `{"org_unit_id":1234,"type":"<type>"}`

### `personio_org_unit_list`

List Org Units · Read-only

List org units of one type (for example departments or teams) in Personio.
Returns a page of org units with id, type, name, abbreviation, description, parent id and creation time, and optionally the IDs of their parent chain.
Use this to find department or team IDs. Use personio_org_unit_get for one unit with its leads.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `type` (`string`, required): Type of org unit to list, for example department or team. Example: department.
- `cursor` (`string`, optional): Pagination cursor for the org units list. Leave empty for the first page. To get the next page, pass the cursor from the previous response's _meta.links.next.href (the value of its cursor query parameter). Example: cur_82sQwR2eZvKilo2duNh219Kw.
- `include_parent_chain` (`boolean`, optional): Set to true to include the IDs of each unit's parent chain. Example: true.
- `limit` (`integer`, optional): Maximum number of org units to return in one page, from 1 to 100. Leave empty to use the Personio default of 20. Example: 50.
- `sort` (`string`, optional): Sort order: name, -name, id or -id (minus means descending). Default: id. Example: name. One of: `name`, `-name`, `id`, `-id`.

Example input: `{"type":"<type>"}`

### `personio_person_get`

Get Person · Read-only

Get one person (employee) in Personio by ID.
Returns the person's id, email, names, gender, status, profile picture, custom attributes and employments.
Use this when you already have the person ID. Use personio_person_list to search by name or email.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `person_id` (`string`, required): The ID of the person. Get it from personio_person_list. Example: 12345.

Example input: `{"person_id":"<person_id>"}`

### `personio_person_list`

List Persons · Read-only

List people (employees) in Personio, filtered by ID, email, name, status, or created/updated date.
Returns a page of persons with id, email, first and last name, preferred name, gender, status, custom attributes and a summary of their employments, plus _meta.links for the next page.
Use this to find a person's ID or browse employees. Use personio_person_get for one known person.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `created_at_gt` (`string`, optional): Only return persons created after this date-time (RFC 3339). Example: 2024-01-01T00:00:00Z.
- `created_at_lt` (`string`, optional): Only return persons created before this date-time (RFC 3339). Example: 2024-12-31T23:59:59Z.
- `cursor` (`string`, optional): Pagination cursor for the persons list. Leave empty for the first page. To get the next page, pass the cursor from the previous response's _meta.links.next.href (the value of its cursor query parameter). Example: cur_82sQwR2eZvKilo2duNh219Kw.
- `email` (`string`, optional): Only return persons with these email addresses. Separate multiple emails with commas. Example: jane.doe@example.com.
- `first_name` (`string`, optional): Only return persons with this exact first name. Example: Jane.
- `id` (`string`, optional): Only return persons with these IDs. Separate multiple IDs with commas. Example: 12345,67890.
- `last_name` (`string`, optional): Only return persons with this exact last name. Example: Doe.
- `limit` (`integer`, optional): Maximum number of persons to return in one page, from 1 to 50. Leave empty to use the Personio default of 10. Example: 50.
- `preferred_name` (`string`, optional): Only return persons with this preferred name. Example: JJ.
- `status` (`string`, optional): Filter by employment status. ACTIVE includes persons whose latest employment is active, on leave, or onboarding; INACTIVE includes persons whose latest employment is inactive. Example: ACTIVE. One of: `ACTIVE`, `INACTIVE`.
- `updated_at_gt` (`string`, optional): Only return persons updated after this date-time (RFC 3339). Useful for incremental syncs. Example: 2024-06-01T00:00:00Z.
- `updated_at_lt` (`string`, optional): Only return persons updated before this date-time (RFC 3339). Example: 2024-06-30T23:59:59Z.

Example input: `{}`

### `personio_project_get`

Get Project · Read-only

Get one attendance project in Personio by ID.
Returns the project's name, status, code, description, cost center, parent project, dates, billable flag, client name and type, plus optional tracked-time totals.
Use this when you have the project ID. Use personio_project_list to search.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `project_id` (`string`, required): The ID of the project. Get it from personio_project_list. Example: 1234.
- `include` (`string`, optional): Extra fields to add, comma-separated: tracked_minutes, sub_projects_tracked_minutes, sub_projects_count, tracked_periods_count. Example: tracked_minutes.

Example input: `{"project_id":"<project_id>"}`

### `personio_project_list`

List Projects · Read-only

List attendance projects in Personio, filtered by ID, name, code, status or parent project.
Returns a page of projects with id, name, status, project code, description, cost center, parent project, start and end dates, billable flag, client name and project type, plus optional tracked-time totals.
Use this to find a project ID for time tracking. Use personio_project_get for one known project.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `cursor` (`string`, optional): Pagination cursor for the projects list. Leave empty for the first page. To get the next page, pass the cursor from the previous response's _meta.links.next.href (the value of its cursor query parameter). Example: cur_82sQwR2eZvKilo2duNh219Kw.
- `id` (`array`, optional): Only return projects with these IDs. Example: ["1234"].
- `include` (`string`, optional): Extra fields to add to each project, comma-separated: tracked_minutes, sub_projects_tracked_minutes, sub_projects_count, tracked_periods_count. Example: tracked_minutes,sub_projects_count.
- `limit` (`integer`, optional): Maximum number of projects to return in one page, from 1 to 200. Leave empty to use the Personio default of 200. Example: 50.
- `name` (`string`, optional): Only return projects with these names. Separate multiple names with commas. Example: Website Relaunch.
- `parent_project_id` (`string`, optional): Only return sub-projects of these parent projects. Separate multiple IDs with commas. Example: 1234.
- `project_code` (`string`, optional): Only return projects with these project codes. Separate multiple codes with commas. Example: PRJ-1234.
- `status` (`string`, optional): Only return projects with this status. Example: ACTIVE. One of: `ACTIVE`, `ARCHIVED`.
- `top_level_only` (`boolean`, optional): Set to true to return only top-level projects (projects without a parent). Example: true.

Example input: `{}`

### `personio_project_member_list`

List Project Members · Read-only

List the people assigned to an attendance project in Personio.
Returns a page of members, each with the person reference.
Use this to see who can track time on a project. Use personio_project_member_add to assign more people.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `project_id` (`string`, required): The ID of the project. Get it from personio_project_list. Example: 1234.
- `cursor` (`string`, optional): Pagination cursor for the members list. Leave empty for the first page. To get the next page, pass the cursor from the previous response's _meta.links.next.href (the value of its cursor query parameter). Example: cur_82sQwR2eZvKilo2duNh219Kw.
- `limit` (`integer`, optional): Maximum number of members to return in one page, from 1 to 200. Leave empty to use the Personio default of 200. Example: 50.

Example input: `{"project_id":"<project_id>"}`

### `personio_recruiting_application_get`

Get Recruiting Application · Read-only

Get one job application in Personio Recruiting by ID.
Returns the candidate, job, current stage, application date, channel, anonymization flag, hiring team and timestamps. Custom attributes and tags are not returned.
Use this when you have the application ID. Use personio_recruiting_application_stage_transition_list for its stage history.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `application_id` (`string`, required): The ID of the application. Get it from personio_recruiting_application_list. Example: 495039.

Example input: `{"application_id":"<application_id>"}`

### `personio_recruiting_application_list`

List Recruiting Applications · Read-only

List job applications in Personio Recruiting, newest update first, optionally filtered by candidate email or update time.
Returns a page of applications with id, candidate, job, current stage, application date, channel, hiring team and timestamps. Custom attributes and tags are not returned.
Use this to track applicants. Use personio_recruiting_application_get for one known application.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `candidate_email` (`string`, optional): Only return applications of the candidate with this email. Example: john.doe@example.com.
- `cursor` (`string`, optional): Pagination cursor for the applications list. Leave empty for the first page. To get the next page, pass the cursor from the previous response's _meta.links.next.href (the value of its cursor query parameter). Example: cur_82sQwR2eZvKilo2duNh219Kw.
- `limit` (`integer`, optional): Maximum number of applications to return in one page, from 1 to 200. Leave empty to use the Personio default of 100. Example: 50.
- `updated_at_gt` (`string`, optional): Only return applications updated after this date-time (RFC 3339). Cannot be combined with updated_at_lt. Example: 2025-06-01T00:00:00Z.
- `updated_at_lt` (`string`, optional): Only return applications updated before this date-time (RFC 3339). Cannot be combined with updated_at_gt. Example: 2025-06-30T23:59:59Z.

Example input: `{}`

### `personio_recruiting_application_stage_transition_list`

List Application Stage Transitions · Read-only

List the stage history of one job application in Personio Recruiting, latest first.
Returns each stage the application entered and when it entered it.
Use this to see how an application moved through the hiring pipeline. Use personio_recruiting_application_get for its current stage.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `application_id` (`string`, required): The ID of the application. Get it from personio_recruiting_application_list. Example: 495039.

Example input: `{"application_id":"<application_id>"}`

### `personio_recruiting_candidate_get`

Get Recruiting Candidate · Read-only

Get one candidate in Personio Recruiting by ID.
Returns the candidate's name, email, phone, gender, birthday, location, availability date, LinkedIn profile, applications and timestamps. Custom attributes and tags are not returned.
Use this when you have the candidate ID. Use personio_recruiting_candidate_list to search by email.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `candidate_id` (`string`, required): The ID of the candidate. Get it from personio_recruiting_candidate_list. Example: 495039.

Example input: `{"candidate_id":"<candidate_id>"}`

### `personio_recruiting_candidate_list`

List Recruiting Candidates · Read-only

List candidates in Personio Recruiting, newest update first, optionally filtered by email or update time.
Returns a page of candidates with id, name, email, phone, gender, birthday, location, availability date, LinkedIn profile, their applications and timestamps. Custom attributes and tags are not returned.
Use this to look up applicants as people. Use personio_recruiting_application_list for applications to specific jobs.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `cursor` (`string`, optional): Pagination cursor for the candidates list. Leave empty for the first page. To get the next page, pass the cursor from the previous response's _meta.links.next.href (the value of its cursor query parameter). Example: cur_82sQwR2eZvKilo2duNh219Kw.
- `email` (`string`, optional): Only return the candidate with this email. Example: john.doe@example.com.
- `limit` (`integer`, optional): Maximum number of candidates to return in one page, from 1 to 200. Leave empty to use the Personio default of 100. Example: 50.
- `updated_at_gt` (`string`, optional): Only return candidates updated after this date-time (RFC 3339). Cannot be combined with updated_at_lt. Example: 2025-06-01T00:00:00Z.
- `updated_at_lt` (`string`, optional): Only return candidates updated before this date-time (RFC 3339). Cannot be combined with updated_at_gt. Example: 2025-06-30T23:59:59Z.

Example input: `{}`

### `personio_recruiting_category_get`

Get Recruiting Job Category · Read-only

Get one job category in Personio Recruiting by ID.
Returns the category's name and its hiring pipeline stages.
Use this when you have the category ID. Use personio_recruiting_category_list to browse categories.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `category_id` (`string`, required): The ID of the job category. Get it from personio_recruiting_category_list. Example: 495039.

Example input: `{"category_id":"<category_id>"}`

### `personio_recruiting_category_list`

List Recruiting Job Categories · Read-only

List the job categories configured in Personio Recruiting.
Returns each category's id, name and hiring pipeline stages.
Use this to see which pipeline stages a category's jobs use. Use personio_recruiting_category_get for one category.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs: none.

Example input: `{}`

### `personio_recruiting_job_get`

Get Recruiting Job · Read-only

Get one job position in Personio Recruiting by ID.
Returns the job's id, name, department, category, company, hiring team and timestamps.
Use this when you have the recruiting job ID. Use personio_recruiting_job_list to browse positions.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `job_id` (`string`, required): The ID of the recruiting job. Get it from personio_recruiting_job_list. Example: 495039.

Example input: `{"job_id":"<job_id>"}`

### `personio_recruiting_job_list`

List Recruiting Jobs · Read-only

List job positions in Personio Recruiting, newest update first, optionally filtered by update time.
Returns a page of recruiting jobs with their id, name, department, category, company, hiring team and timestamps.
Use this to find a job position ID for applications. Use personio_job_list for the internal job catalogue instead.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `cursor` (`string`, optional): Pagination cursor for the jobs list. Leave empty for the first page. To get the next page, pass the cursor from the previous response's _meta.links.next.href (the value of its cursor query parameter). Example: cur_82sQwR2eZvKilo2duNh219Kw.
- `limit` (`integer`, optional): Maximum number of jobs to return in one page, from 1 to 200. Leave empty to use the Personio default of 100. Example: 50.
- `updated_at_gt` (`string`, optional): Only return jobs updated after this date-time (RFC 3339). Cannot be combined with updated_at_lt. Example: 2025-06-01T00:00:00Z.
- `updated_at_lt` (`string`, optional): Only return jobs updated before this date-time (RFC 3339). Cannot be combined with updated_at_gt. Example: 2025-06-30T23:59:59Z.

Example input: `{}`

### `personio_report_attribute_list`

List Report Attributes · Read-only

List the attributes (columns) that Personio reports can use for this company.
Returns each attribute's name, display label, description, data type, and whether it can be used for filtering and segmenting.
Use this to understand the columns in personio_report_get results.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `locale` (`string`, optional): Locale for labels in the response. Default: en. Example: de.

Example input: `{}`

### `personio_report_get`

Get Report · Read-only

Get a custom report and its data rows from Personio by ID.
Returns the report configuration (columns, time range, filters, grouping) and the table rows, plus a cursor when more rows are available.
Use this to read report data. Use personio_report_list to find the report ID and personio_report_attribute_list to understand the columns.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `report_id` (`string`, required): The ID of the report (UUID). Get it from personio_report_list. Example: 3f1c2b3a-9d4e-4f5a-8b7c-1d2e3f4a5b6c.
- `cursor` (`string`, optional): Cursor from a previous response to fetch the next set of rows. Example: 1.
- `limit` (`integer`, optional): Maximum number of table rows to return. Leave empty to return all rows. Example: 25.
- `locale` (`string`, optional): Locale for labels in the response. Default: en. Example: de.

Example input: `{"report_id":"<report_id>"}`

### `personio_report_list`

List Reports · Read-only

List the custom reports available in the Personio account, most recent first, optionally filtered by name.
Returns a page of reports with id, name, chart type, owner, sharing flag and created, edited and last-viewed times.
Use this to find a report ID. Use personio_report_get to read a report's data.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `cursor` (`string`, optional): Pagination cursor from the previous response. When you pass a cursor, pass only limit with it; other filters make the request fail. Example: kLMvcsaXMDdWQ1XREWY=.
- `limit` (`integer`, optional): Maximum number of reports to return. A value of 0 or less returns all reports. Example: 25.
- `name` (`string`, optional): Only return reports whose name matches this search text. Do not combine with cursor. Example: absences 2025.

Example input: `{}`

### `personio_salary_band_get`

Get Salary Band · Read-only

Get one salary band in Personio by UUID.
Returns the band's minimum, middle and maximum amounts, currency and workplaces.
Use this when you have the salary band ID. Use personio_salary_band_list to browse bands.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `salary_band_id` (`string`, required): The ID of the salary band (UUID). Get it from personio_salary_band_list. Example: e1f2a3b4-c5d6-7890-abcd-ef1234567890.

Example input: `{"salary_band_id":"<salary_band_id>"}`

### `personio_salary_band_list`

List Salary Bands · Read-only

List the salary bands defined in Personio, optionally filtered by ID.
Returns a page of salary bands with id, minimum, middle and maximum amounts, currency and workplaces.
Use this to review pay ranges. Use personio_salary_band_get for one known band.
Needs a credential with the personio:salary-bands:read scope.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `cursor` (`string`, optional): Pagination cursor for the salary bands list. Leave empty for the first page. To get the next page, pass the cursor from the previous response's _meta.links.next.href (the value of its cursor query parameter). Example: cur_82sQwR2eZvKilo2duNh219Kw.
- `id` (`string`, optional): Only return salary bands with these UUIDs. Separate multiple IDs with commas. Example: e1f2a3b4-c5d6-7890-abcd-ef1234567890.
- `limit` (`integer`, optional): Maximum number of salary bands to return in one page, from 1 to 100. Leave empty to use the Personio default of 50. Example: 50.

Example input: `{}`

### `personio_workplace_list`

List Workplaces · Read-only

List the workplaces (offices and locations) of the Personio account, optionally filtered by ID or name.
Returns a page of workplaces with id and name.
Use this to find workplace IDs.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `cursor` (`string`, optional): Pagination cursor for the workplaces list. Leave empty for the first page. To get the next page, pass the cursor from the previous response's _meta.links.next.href (the value of its cursor query parameter). Example: cur_82sQwR2eZvKilo2duNh219Kw.
- `id` (`string`, optional): Only return workplaces with these IDs. Separate multiple IDs with commas. Example: 1,2.
- `limit` (`integer`, optional): Maximum number of workplaces to return in one page, from 1 to 100. Leave empty to use the Personio default of 50. Example: 50.
- `name` (`string`, optional): Only return workplaces with these names. Separate multiple names with commas. Example: Main Office.
- `sort` (`string`, optional): Comma-separated sort fields, name and/or id; prefix with - for descending. Default: id ascending. Example: name.

Example input: `{}`

### `personio_absence_period_create`

Create Absence Period · Write

Create an absence period (time off) for a person in Personio, such as vacation or sick leave.
Returns the new absence period's id.
Use this to book time off. Use personio_absence_period_update to change an existing one.
Get the absence type ID from personio_absence_type_list first; whether hours or half days are allowed depends on that type's unit.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `absence_type_id` (`string`, required): ID of the absence type (for example Paid vacation). Get it from personio_absence_type_list. Example: cba6fa09-d8fe-4de0-be03-f0a1d48df766.
- `person_id` (`string`, required): ID of the person taking the absence. Get it from personio_person_list. Example: 12345.
- `starts_from` (`string`, required): When the absence starts, as a local date-time without a timezone offset (YYYY-MM-DDTHH:MM:SS), in the person's timezone. Do not add Z or an offset. Example: 2025-07-01T00:00:00.
- `comment` (`string`, optional): Comment attached to the absence. Example: Summer vacation.
- `ends_at` (`string`, optional): When the absence ends, as a local date-time without a timezone offset (YYYY-MM-DDTHH:MM:SS), in the person's timezone. Leave empty for an open-ended absence such as long-term sick leave. Example: 2025-07-05T00:00:00.
- `ends_at_type` (`string`, optional): For half-day absence types, whether the absence ends after the FIRST_HALF or SECOND_HALF of the end day. Only used with ends_at. Example: SECOND_HALF. One of: `FIRST_HALF`, `SECOND_HALF`.
- `skip_approval` (`boolean`, optional): Set to true to skip any approval step this change would otherwise need in Personio (for example, a manager approval). Leave empty or false to follow the company's normal approval rules. Example: false.
- `starts_from_type` (`string`, optional): For half-day absence types, whether the absence starts in the FIRST_HALF or SECOND_HALF of the start day. Leave empty for full days or hourly types. Example: FIRST_HALF. One of: `FIRST_HALF`, `SECOND_HALF`.
- `substitute_id` (`string`, optional): Person ID of the colleague covering during the absence. Only used if the absence type's policy allows substitutes. Example: 67890.

Example input: `{"absence_type_id":"<absence_type_id>","person_id":"<person_id>","starts_from":"<starts_from>"}`

### `personio_absence_period_update`

Update Absence Period · Write

Change the start, end or comment of an existing absence period in Personio.
Returns an empty response on success (HTTP 204).
Use this to move or extend booked time off. Use personio_absence_period_create to book new time off.

Read only: no. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `absence_period_id` (`string`, required): The ID of the absence period to update. Get it from personio_absence_period_list. Example: 493eff0a-2c5a-467e-8966-f70b4e3805a6.
- `comment` (`string`, optional): New comment for the absence. Example: Moved by one day.
- `ends_at` (`string`, optional): New end, as a local date-time without a timezone offset (YYYY-MM-DDTHH:MM:SS), in the person's timezone. Example: 2025-07-06T00:00:00.
- `ends_at_type` (`string`, optional): For half-day absence types, FIRST_HALF or SECOND_HALF of the new end day. Only used with ends_at. Example: FIRST_HALF. One of: `FIRST_HALF`, `SECOND_HALF`.
- `skip_approval` (`boolean`, optional): Set to true to skip any approval step this change would otherwise need in Personio (for example, a manager approval). Leave empty or false to follow the company's normal approval rules. Example: false.
- `starts_from` (`string`, optional): New start, as a local date-time without a timezone offset (YYYY-MM-DDTHH:MM:SS), in the person's timezone. Example: 2025-07-02T00:00:00.
- `starts_from_type` (`string`, optional): For half-day absence types, FIRST_HALF or SECOND_HALF of the new start day. Only used with starts_from. Example: SECOND_HALF. One of: `FIRST_HALF`, `SECOND_HALF`.

Example input: `{"absence_period_id":"<absence_period_id>"}`

### `personio_attendance_period_create`

Create Attendance Period · Write

Record an attendance period (working time or a break) for a person in Personio, optionally on a project.
Returns the new attendance period's id and any other periods the change affected.
Use this to log hours. Use personio_attendance_period_update to change a logged period.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `person_id` (`string`, required): ID of the person the time belongs to. Get it from personio_person_list. Example: 12345.
- `start` (`string`, required): When the period starts, as a local date-time without a timezone offset (YYYY-MM-DDTHH:MM:SS). Do not add Z or an offset. Example: 2025-01-15T09:00:00.
- `type` (`string`, required): WORK for working time, BREAK for a break. Example: WORK. One of: `WORK`, `BREAK`.
- `comment` (`string`, optional): Comment for the period. Example: Customer workshop.
- `end` (`string`, optional): When the period ends, as a local date-time without a timezone offset (YYYY-MM-DDTHH:MM:SS). Leave empty for a period that is still running. Example: 2025-01-15T17:30:00.
- `project_id` (`string`, optional): ID of an ACTIVE project to book the time on. Not allowed for BREAK periods. Get it from personio_project_list. Example: 1234.
- `skip_approval` (`boolean`, optional): Set to true to skip any approval step this change would otherwise need in Personio (for example, a manager approval). Leave empty or false to follow the company's normal approval rules. Example: false.

Example input: `{"person_id":"<person_id>","start":"<start>","type":"WORK"}`

### `personio_attendance_period_update`

Update Attendance Period · Write

Change the start, end, comment or project of a logged attendance period in Personio.
Returns an empty response on success (HTTP 204).
Use this to correct tracked time. Use personio_attendance_period_create to log new time.

Read only: no. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `attendance_period_id` (`string`, required): The ID of the attendance period to update. Get it from personio_attendance_period_list. Example: bd242cd1-5116-41a0-99aa-c12af4837c81.
- `comment` (`string`, optional): New comment. Example: Adjusted start time.
- `end` (`string`, optional): New end, as a local date-time without a timezone offset (YYYY-MM-DDTHH:MM:SS). Example: 2025-01-15T17:00:00.
- `project_id` (`string`, optional): ID of an ACTIVE project to book the time on instead. Not allowed for BREAK periods. Example: 1234.
- `skip_approval` (`boolean`, optional): Set to true to skip any approval step this change would otherwise need in Personio (for example, a manager approval). Leave empty or false to follow the company's normal approval rules. Example: false.
- `start` (`string`, optional): New start, as a local date-time without a timezone offset (YYYY-MM-DDTHH:MM:SS). Example: 2025-01-15T08:30:00.

Example input: `{"attendance_period_id":"<attendance_period_id>"}`

### `personio_compensation_create`

Create Compensation · Write

Create a one-time, recurring, fixed or hourly compensation for a person in Personio. Bonuses are not supported.
Returns the created compensation with person, type, value, currency, effective date, interval and comment.
Use this to add a payment for payroll. Use personio_compensation_list to review existing compensations.
Get the compensation type ID from personio_compensation_type_list first. Needs a credential with both personio:compensations:read and personio:compensations:write.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `effective_from` (`string`, required): Date the compensation takes effect (YYYY-MM-DD). For YEARLY compensations the payout month is this date's month. Example: 2025-01-15.
- `person_id` (`string`, required): ID of the person receiving the compensation. Get it from personio_person_list. Example: 12345.
- `type_id` (`string`, required): ID of the compensation type. Get it from personio_compensation_type_list. Example: 12e21d39-58f3-4acb-b5ba-9b5ae228ea51.
- `value` (`number`, required): Amount in the currency's main unit, with up to two decimals (20.50 means twenty euros and fifty cents for EUR). Example: 2500.50.
- `comment` (`string`, optional): Comment about the compensation. Example: Gym allowance.
- `currency` (`string`, optional): Currency as an ISO 4217 code. Example: EUR. One of: `AED`, `AFN`, `ALL`, `AMD`, `ANG`, `AOA`, `ARS`, `AUD`, `AWG`, `AZN`, `BAM`, `BBD`, `BDT`, `BGN`, `BHD`, `BIF`, `BMD`, `BND`, `BOB`, `BRL`, `BSD`, `BTN`, `BWP`, `BYN`, `BZD`, `CAD`, `CDF`, `CHF`, `CLP`, `CNY`, `COP`, `CRC`, `CUC`, `CUP`, `CVE`, `CZK`, `DJF`, `DKK`, `DOP`, `DZD`, `EGP`, `ERN`, `ETB`, `EUR`, `FJD`, `FKP`, `GBP`, `GEL`, `GHS`, `GIP`, `GMD`, `GNF`, `GTQ`, `GYD`, `HKD`, `HNL`, `HRK`, `HTG`, `HUF`, `IDR`, `ILS`, `INR`, `IQD`, `IRR`, `ISK`, `JMD`, `JOD`, `JPY`, `KES`, `KGS`, `KHR`, `KMF`, `KPW`, `KRW`, `KWD`, `KYD`, `KZT`, `LAK`, `LBP`, `LKR`, `LRD`, `LSL`, `LYD`, `MAD`, `MDL`, `MGA`, `MKD`, `MMK`, `MNT`, `MOP`, `MRU`, `MUR`, `MVR`, `MWK`, `MXN`, `MYR`, `MZN`, `NAD`, `NGN`, `NIO`, `NOK`, `NPR`, `NZD`, `OMR`, `PAB`, `PEN`, `PGK`, `PHP`, `PKR`, `PLN`, `PYG`, `QAR`, `RON`, `RSD`, `RUB`, `RWF`, `SAR`, `SBD`, `SCR`, `SDG`, `SEK`, `SGD`, `SHP`, `SLE`, `SLL`, `SOS`, `SRD`, `SSP`, `STN`, `SVC`, `SYP`, `SZL`, `THB`, `TJS`, `TMT`, `TND`, `TOP`, `TRY`, `TTD`, `TWD`, `TZS`, `UAH`, `UGX`, `USD`, `UYU`, `UZS`, `VES`, `VND`, `VUV`, `WST`, `XAF`, `XCD`, `XOF`, `XPF`, `YER`, `ZAR`, `ZMW`, `ZWL`.
- `interval` (`string`, optional): Payout interval. Required for every compensation type except ONE_TIME, where it is ignored. Example: MONTHLY. One of: `MONTHLY`, `QUARTERLY`, `HALF-YEARLY`, `YEARLY`.

Example input: `{"effective_from":"<effective_from>","person_id":"<person_id>","type_id":"<type_id>","value":2500.5}`

### `personio_compensation_type_create`

Create Compensation Type · Write

Create a one-time or recurring compensation type in Personio, such as a gym benefit or a signing bonus.
Returns the new type with its id, name and category.
Use this when no existing type fits. Use personio_compensation_type_list to check existing types first.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `category` (`string`, required): Payout frequency of compensations of this type: RECURRING or ONE_TIME. Hourly types are not supported. Example: RECURRING. One of: `RECURRING`, `ONE_TIME`.
- `name` (`string`, required): Name of the compensation type. Example: Gym benefit.

Example input: `{"category":"RECURRING","name":"<name>"}`

### `personio_document_update`

Update Document Metadata · Write

Update the metadata of a document in Personio: its name, date, comment or category. The file itself is not changed.
Returns an empty response on success (HTTP 204).
Use this to rename or recategorize a document. Use personio_document_list to find the document ID.

Read only: no. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `document_id` (`string`, required): The ID of the document. Get it from personio_document_list. Example: 123.
- `category_id` (`string`, optional): ID of the document category to move the document to. Example: 123.
- `comment` (`string`, optional): New comment for the document. Example: Signed copy.
- `date` (`string`, optional): New document date (YYYY-MM-DD); Personio orders documents by this date. Example: 2025-01-01.
- `name` (`string`, optional): New document name. Example: Employment contract 2025.

Example input: `{"document_id":"<document_id>"}`

### `personio_employment_update`

Update Employment · Write

Update a person's employment in Personio: status, type, dates, position, working hours, supervisor, office, org units, legal entity, job or cost centers.
Returns an empty response on success (HTTP 204).
Use this for job and contract changes. Use personio_person_update for personal data such as name or email.
Get the employment ID from personio_employment_list first.

Read only: no. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `employment_id` (`string`, required): The ID of the employment to update. Get it from personio_employment_list. Example: 493eff0a-2c5a-467e-8966-f70b4e3805a6.
- `person_id` (`string`, required): The ID of the person. Example: 12345.
- `contract_end_date` (`string`, optional): Date a temporary employment contract ends (YYYY-MM-DD). Example: 2025-12-31.
- `cost_centers` (`array`, optional): Split of the employment across cost centers by percentage; this replaces the current split. Each item has the cost center id (from personio_cost_center_list) and a weight; weights must add up to 100. Example: [{"id": "123", "weight": 60}, {"id": "456", "weight": 40}].
- `employment_start_date` (`string`, optional): Date the employment contract starts (YYYY-MM-DD). Example: 2025-01-01.
- `full_time_weekly_working_hours` (`number`, optional): Hours per week that count as full time for this employment. Example: 40.
- `job_id` (`string`, optional): UUID of the job (from the Jobs catalogue) to link to the employment. Get it from personio_job_list. Example: a1b2c3d4-e5f6-7890-abcd-ef1234567890.
- `legal_entity_id` (`string`, optional): ID of the legal entity that employs the person. Get it from personio_legal_entity_list. Example: 123.
- `office_id` (`string`, optional): ID of the office the person works from. Example: 1234.
- `org_units` (`array`, optional): All org units (departments and teams) for the employment; this replaces the current list. Each item has a type (for example department or team) and the org unit id from personio_org_unit_list. Example: [{"type": "department", "id": "1234"}, {"type": "team", "id": "5678"}].
- `position_title` (`string`, optional): Job title (position) of the employment. Example: Senior Engineer.
- `probation_end_date` (`string`, optional): Date the probation period ends (YYYY-MM-DD). Set this or probation_period_length, not both. Example: 2025-06-30.
- `probation_period_length` (`integer`, optional): Length of the probation period. Set this or probation_end_date, not both. Example: 6.
- `status` (`string`, optional): New employment status. Example: ACTIVE. One of: `ACTIVE`, `INACTIVE`, `ONBOARDING`, `LEAVE`.
- `supervisor_id` (`string`, optional): Person ID of the new supervisor. Get it from personio_person_list. Example: 67890.
- `type` (`string`, optional): Employment type: INTERNAL for employees, EXTERNAL for contractors. Example: INTERNAL. One of: `INTERNAL`, `EXTERNAL`.
- `weekly_working_hours` (`number`, optional): Hours the person works per week. Example: 40.

Example input: `{"employment_id":"<employment_id>","person_id":"<person_id>"}`

### `personio_person_create`

Create Person · Write

Create a new person (employee) in Personio together with their employment.
Returns the new person's id and the ids of the employments created.
Use this to add a new hire. Use personio_person_update to change an existing person, or personio_employment_update to change employment details.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `first_name` (`string`, required): First name of the person. Example: Jane.
- `last_name` (`string`, required): Last name of the person. Example: Doe.
- `custom_attributes` (`array`, optional): Custom attribute values for the person. Each item has the attribute id and a value (a string, or a list of strings for multi-select attributes). Example: [{"id": "dynamic_12345", "value": "Berlin"}].
- `email` (`string`, optional): Work email of the person. It must be unique across the company. Example: jane.doe@example.com.
- `employments` (`array`, optional): Employment to create with the person, as a list with one employment object. Each employment can set its status (ACTIVE, INACTIVE, ONBOARDING or LEAVE), type (INTERNAL or EXTERNAL), employment_start_date, contract and probation end dates, weekly and full-time weekly working hours, a position title, and references by ID to the supervisor, office, legal_entity, job, org_units (each with a type such as department or team) and cost_centers (each with a percentage weight; weights must total 100). Example: [{"status": "ACTIVE", "type": "INTERNAL", "employment_start_date": "2025-01-01", "position": {"title": "Engineer"}, "weekly_working_hours": 40, "supervisor": {"id": "12345"}}].
- `gender` (`string`, optional): Gender of the person. Example: FEMALE. One of: `MALE`, `FEMALE`, `DIVERSE`, `UNKNOWN`, `UNDEFINED`.
- `language_code` (`string`, optional): Main language of the person. Example: en. One of: `en`, `de`, `es`, `fr`, `nl`, `it`, `sv`, `fi`.
- `preferred_name` (`string`, optional): Preferred name of the person, if different from the first name. Example: JJ.

Example input: `{"first_name":"<first_name>","last_name":"<last_name>"}`

### `personio_person_update`

Update Person · Write

Update a person's details in Personio: email, names, gender, language or custom attributes.
Returns an empty response on success (HTTP 204).
Use this to change personal data. Use personio_employment_update for job, supervisor, status or working hours.

Read only: no. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `person_id` (`string`, required): The ID of the person to update. Get it from personio_person_list. Example: 12345.
- `custom_attributes` (`array`, optional): Custom attribute values to set. Each item has the attribute id and a value (a string, or a list of strings for multi-select attributes). Example: [{"id": "dynamic_12345", "value": "Munich"}].
- `email` (`string`, optional): New work email. It must be unique across the company. Example: jane.doe@example.com.
- `first_name` (`string`, optional): New first name. Example: Jane.
- `gender` (`string`, optional): New gender. Example: FEMALE. One of: `MALE`, `FEMALE`, `DIVERSE`, `UNKNOWN`, `UNDEFINED`.
- `language_code` (`string`, optional): New main language. Example: de. One of: `en`, `de`, `es`, `fr`, `nl`, `it`, `sv`, `fi`.
- `last_name` (`string`, optional): New last name. Example: Doe.
- `preferred_name` (`string`, optional): New preferred name. Example: JJ.

Example input: `{"person_id":"<person_id>"}`

### `personio_project_create`

Create Project · Write

Create an attendance project (or sub-project) in Personio that employees can track time on.
Returns the new project's id.
Use this to set up a project for time tracking. Use personio_project_update to change one, and personio_project_member_add to assign people.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `name` (`string`, required): Name of the project. Example: Website Relaunch.
- `status` (`string`, required): Status of the project. Example: ACTIVE. One of: `ACTIVE`, `ARCHIVED`.
- `assigned_to_all` (`boolean`, optional): Set to true to let every employee track time on the project. Projects assigned to all employees cannot have members. Example: false.
- `billable` (`boolean`, optional): Mark the project as billable. Sub-projects always inherit the parent's billable flag. Example: true.
- `client_name` (`string`, optional): Client name for the project. Sub-projects cannot have a client name. Example: ACME Inc.
- `cost_center_id` (`string`, optional): ID of an existing Personio cost center for the project. Sub-projects cannot have a cost center. Get it from personio_cost_center_list. Example: 1234.
- `description` (`string`, optional): Project description. Example: Relaunch of the company website.
- `end_date` (`string`, optional): End date of the project, exclusive (YYYY-MM-DD). Example: 2025-12-31.
- `parent_project_id` (`string`, optional): ID of the parent project, to create a sub-project. Only one level of nesting is allowed. Example: 1234.
- `project_code` (`string`, optional): Project code; must be unique across all projects and sub-projects. Example: PRJ-1234.
- `project_type` (`string`, optional): Free-text project type defined by your company. Sub-projects cannot have a project type. Example: External.
- `start_date` (`string`, optional): First day of the project, inclusive (YYYY-MM-DD). Example: 2025-01-01.

Example input: `{"name":"<name>","status":"ACTIVE"}`

### `personio_project_member_add`

Add Project Members · Write

Assign one or more people to an attendance project in Personio so they can track time on it.
Returns the list of members added. People who are already members are left unchanged.
Use this to give people access to a project. Use personio_project_member_list to see current members.
If the project was assigned to all employees, it becomes a project with members only. Sub-projects cannot have members.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `person_ids` (`array`, required): IDs of the persons to add. If any ID is invalid the whole request fails. Example: ["12345", "67890"].
- `project_id` (`string`, required): The ID of the project. Get it from personio_project_list. Example: 1234.

Example input: `{"person_ids":["12345","67890"],"project_id":"<project_id>"}`

### `personio_project_update`

Update Project · Write

Update an attendance project in Personio: name, status, code, description, cost center, dates, billable flag, client or type.
Returns an empty response on success (HTTP 204).
Use this to rename, archive or edit a project. Use personio_project_create for a new project.

Read only: no. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `project_id` (`string`, required): The ID of the project to update. Get it from personio_project_list. Example: 1234.
- `assigned_to_all` (`boolean`, optional): Set to true to let every employee track time on the project. Projects assigned to all employees cannot have members. Example: false.
- `billable` (`boolean`, optional): Mark the project as billable. Sub-projects always inherit the parent's billable flag. Example: true.
- `client_name` (`string`, optional): Client name for the project. Sub-projects cannot have a client name. Example: ACME Inc.
- `cost_center_id` (`string`, optional): ID of an existing Personio cost center for the project. Sub-projects cannot have a cost center. Get it from personio_cost_center_list. Example: 1234.
- `description` (`string`, optional): Project description. Example: Relaunch of the company website.
- `end_date` (`string`, optional): End date of the project, exclusive (YYYY-MM-DD). Example: 2025-12-31.
- `name` (`string`, optional): New project name. Example: Website Relaunch 2025.
- `project_code` (`string`, optional): Project code; must be unique across all projects and sub-projects. Example: PRJ-1234.
- `project_type` (`string`, optional): Free-text project type defined by your company. Sub-projects cannot have a project type. Example: External.
- `start_date` (`string`, optional): First day of the project, inclusive (YYYY-MM-DD). Example: 2025-01-01.
- `status` (`string`, optional): New status; ARCHIVED hides the project from time tracking. Example: ARCHIVED. One of: `ACTIVE`, `ARCHIVED`.

Example input: `{"project_id":"<project_id>"}`

### `personio_recruiting_application_create`

Submit Recruiting Application · Write

Submit a new job application to Personio Recruiting for a job position.
Returns an empty response on success (HTTP 201).
Use this to pass applicants from a careers site or sourcing tool into Personio. Set dry_run to true to validate without creating.
Get the job position ID from personio_recruiting_job_list. Attaching uploaded documents is not supported by this tool.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `email` (`string`, required): Applicant's email address. Example: john.doe@example.com.
- `first_name` (`string`, required): Applicant's first name. Example: John.
- `job_position_id` (`integer`, required): ID of the job position to apply for. Get it from personio_recruiting_job_list. Example: 495039.
- `last_name` (`string`, required): Applicant's last name. Example: Doe.
- `application_date` (`string`, optional): Date the application was submitted (YYYY-MM-DD). Defaults to today. Example: 2025-03-01.
- `attributes` (`array`, optional): Custom application attributes, each with the attribute id and a string value. Example: [{"id": "custom_attribute_123", "value": "Berlin"}].
- `dry_run` (`boolean`, optional): Set to true to validate the application without creating it. Example: true.
- `external_posting_id` (`string`, optional): Your external ID of the job posting the application came through. Example: careers-site-42.
- `message` (`string`, optional): Message or cover note from the applicant. Example: I am excited to apply for this role.
- `phase` (`object`, optional): Pipeline phase to place the application in; defaults to the job's first phase. Use {"type": "system", "id": "unassigned"} for a system phase (unassigned, rejected, declined, offer or accepted), or {"type": "custom", "id": 123} for a custom phase ID. Example: {"type": "system", "id": "unassigned"}.
- `recruiting_channel_id` (`integer`, optional): ID of the recruiting channel the application came through. Example: 1234.
- `tags` (`array`, optional): Tags to add to the application. Example: ["referral", "senior"].

Example input: `{"email":"<email>","first_name":"<first_name>","job_position_id":495039,"last_name":"<last_name>"}`

## Related

Other Productivity connectors ([all 144](/agentkit/connectors/?category=productivity)):

- [Slack](/agentkit/connectors/slack/): Scalekit connector, OAuth, 96 tools
- [Microsoft 365](/agentkit/connectors/microsoft365/): Scalekit connector, OAuth, 317 tools
- [Notion](/agentkit/connectors/notion/): Scalekit connector, OAuth, 51 tools


---

## More Scalekit documentation

| Resource | What it contains | When to use it |
|----------|-----------------|----------------|
| [/llms.txt](/llms.txt) | Structured index with routing hints per product area | Start here — find which documentation set covers your topic before loading full content |
| [/llms-full.txt](/llms-full.txt) | Complete documentation for all Scalekit products in one file | Use when you need exhaustive context across multiple products or when the topic spans several areas |
| [sitemap-0.xml](https://docs.scalekit.com/sitemap-0.xml) | Full URL list of every documentation page | Use to discover specific page URLs you can fetch for targeted, page-level answers |
