Introduction

 

This page builds up on our API docs in swagger format hosted on github.

 

/auth

 

Credentials can be downloaded in the Personio app at Configure account > Company as text file. The credentials allow you to perform a request against the /auth endpoint to retrieve an initial authentication token.

With each new download of credentials, new keys are generated, whereby the existing keys become invalid.

In every request, the Authorization header has to be set:
Authorization: Bearer YOUR_TOKEN_HERE

After each request a new token is generated and sent back to the user in the Authorization header. You can use this token to make the next request. With every new call the previous token is invalidated.

Retrieved tokens have a lifetime of one day and can be exchanged for new ones in the course of two weeks.

 

post

Request Authentication Token

 
posthttps://api.personio.de/v1/auth

Query Params

client_id
string
required

Client id of the downloaded credentials file

client_secret
string
required

Client secret of the downloaded credentials file

 
curl --request POST \
  --url 'https://api.personio.de/v1/auth?client_id=client_id&client_secret=client_secret'
var request = require("request");

var options = { method: 'POST',
  url: 'https://api.personio.de/v1/auth',
  qs: 
   { client_id: 'client_id',
     client_secret: 'client_secret' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.personio.de/v1/auth?client_id=client_id&client_secret=client_secret")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://api.personio.de/v1/auth?client_id=client_id&client_secret=client_secret");

xhr.send(data);
import requests

url = "https://api.personio.de/v1/auth"

querystring = {"client_id":"client_id","client_secret":"client_secret"}

response = requests.request("POST", url, params=querystring)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "success": true,
  "data": {
    "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vYXBpLmRldi5wZXJzb25pby5kZTozMDAwMS92MS9hdXRoIiwiaWF0IjoxNDg5MDkxMzA2LCJleHAiOjE0ODkxNzc3MDYsIm5iZiI6MTQ4OTA5MTMwNiwianRpIjoiZmU1ZjkxOGY2MDZjOWI4OGMwMzM0ZmJkZjkyYzkwMzgiLCJzdWIiOiJPR014TVdRd1kySmxZbVF6Tm1RNVpqQmxOell6WmpsaSJ9.QZZCdlDjmL-LYdoDx2XLUfhwTdcjDgm9h4t-6JoACiM"
  }
}
 

/company/employees

 
 
 

get

List Employees

 
gethttps://api.personio.de/v1/company/employees

Query Params

query
string

[In development] Query string to perform search on. Returns all employees if not present. Can also be used with custom attributes, e.g. dynamic_9382=abcd

attributes
array of s

[In development] Attributes to be returend for employees found. Returns all available attributes if not present. Pass attributes multiple times of needed.

 
curl --request GET \
  --url https://api.personio.de/v1/company/employees
var request = require("request");

var options = { method: 'GET',
  url: 'https://api.personio.de/v1/company/employees' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.personio.de/v1/company/employees")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://api.personio.de/v1/company/employees");

xhr.send(data);
import requests

url = "https://api.personio.de/v1/company/employees"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "success": true,
  "data": [
    {
      "type": "Employee",
      "attributes": {
        "id": {
          "label": "id",
          "value": 83752
        },
        "first_name": {
          "label": "First name",
          "value": "Andreas"
        },
        "last_name": {
          "label": "Last name",
          "value": "Anderson"
        },
        "email": {
          "label": "Email",
          "value": "andreas.anderson@demo.com"
        },
        "gender": {
          "label": "Gender",
          "value": "male"
        },
        "status": {
          "label": "Status",
          "value": "active"
        },
        "position": {
          "label": "Position",
          "value": "Online Marketing Specialist"
        },
        "supervisor": {
          "label": "Supervisor",
          "value": {
            "type": "Employee",
            "attributes": {
              "id": {
                "label": "id",
                "value": 423506
              },
              "first_name": {
                "label": "First name",
                "value": "Max"
              },
              "last_name": {
                "label": "Last name",
                "value": "Mustermann"
              },
              "email": {
                "label": "Email",
                "value": "max.mustermann@example.org"
              }
            }
          }
        },
        "employment_type": {
          "label": "Employment type",
          "value": "internal"
        },
        "weekly_working_hours": {
          "label": "Weekly hours",
          "value": "40"
        },
        "hire_date": {
          "label": "Hire date",
          "value": "2012-02-01T00:00:00+0100"
        },
        "contract_end_date": {
          "label": "Contract ends",
          "value": null
        },
        "termination_date": {
          "label": "Termination date",
          "value": null
        },
        "termination_type": {
          "label": "Termination type",
          "value": ""
        },
        "termination_reason": {
          "label": "Termination reason",
          "value": ""
        },
        "probation_period_end": {
          "label": "Probation period end",
          "value": "2012-07-31T00:00:00+0200"
        },
        "created_at": {
          "label": "created_at",
          "value": "2016-10-20T16:15:55+0200"
        },
        "last_modified_at": {
          "label": "Last modified",
          "value": "2016-10-22T16:15:55+0200"
        },
        "office": {
          "label": "Office",
          "value": {
            "type": "Office",
            "attributes": {
              "name": "Munich"
            }
          }
        },
        "department": {
          "label": "Department",
          "value": {
            "type": "Department",
            "attributes": {
              "name": "Marketing"
            }
          }
        },
        "cost_centers": {
          "label": "Cost center",
          "value": [
            {
              "type": "CostCenter",
              "attributes": {
                "name": "Cost Center One",
                "id": 320,
                "percentage": 50
              }
            },
            {
              "type": "CostCenter",
              "attributes": {
                "name": "Cost Center Two",
                "id": 321,
                "percentage": 50
              }
            }
          ]
        },
        "fix_salary": {
          "label": "Fix salary",
          "value": 4000
        },
        "hourly_salary": {
          "label": "Hourly salary",
          "value": 0
        },
        "vacation_day_balance": {
          "label": "Vacation day balance",
          "value": 28.5
        },
        "last_working_day": {
          "label": "Last working day",
          "value": "2017-02-28T00:00:00+0200"
        },
        "dynamic_24407": {
          "label": "Titel",
          "value": "Dr"
        },
        "dynamic_21827": {
          "label": "IBAN",
          "value": "DE98 8989 9898 0000 8989 00"
        }
      }
    }
  ]
}
 

/company/employees/{employee_id}

 
 
 

get

Employee

 
gethttps://api.personio.de/v1/company/employees/employee_id

Path Params

employee_id
int32
required

Numeric id of the employee

 
curl --request GET \
  --url https://api.personio.de/v1/company/employees/employee_id
var request = require("request");

var options = { method: 'GET',
  url: 'https://api.personio.de/v1/company/employees/employee_id' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.personio.de/v1/company/employees/employee_id")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://api.personio.de/v1/company/employees/employee_id");

xhr.send(data);
import requests

url = "https://api.personio.de/v1/company/employees/employee_id"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "success": true,
  "data": {
    "type": "Employee",
    "attributes": {
      "id": {
        "label": "id",
        "value": 83752
      },
      "first_name": {
        "label": "First name",
        "value": "Andreas"
      },
      "last_name": {
        "label": "Last name",
        "value": "Anderson"
      },
      "email": {
        "label": "Email",
        "value": "andreas.anderson@demo.com"
      },
      "gender": {
        "label": "Gender",
        "value": "male"
      },
      "status": {
        "label": "Status",
        "value": "active"
      },
      "position": {
        "label": "Position",
        "value": "Online Marketing Specialist"
      },
      "supervisor": {
        "label": "Supervisor",
        "value": {
          "type": "Employee",
          "attributes": {
            "id": {
              "label": "id",
              "value": 423506
            },
            "first_name": {
              "label": "First name",
              "value": "Max"
            },
            "last_name": {
              "label": "Last name",
              "value": "Mustermann"
            },
            "email": {
              "label": "Email",
              "value": "max.mustermann@example.org"
            }
          }
        }
      },
      "employment_type": {
        "label": "Employment type",
        "value": "internal"
      },
      "weekly_working_hours": {
        "label": "Weekly hours",
        "value": "40"
      },
      "hire_date": {
        "label": "Hire date",
        "value": "2012-02-01T00:00:00+0100"
      },
      "contract_end_date": {
        "label": "Contract ends",
        "value": null
      },
      "termination_date": {
        "label": "Termination date",
        "value": null
      },
      "termination_type": {
        "label": "Termination type",
        "value": ""
      },
      "termination_reason": {
        "label": "Termination reason",
        "value": ""
      },
      "probation_period_end": {
        "label": "Probation period end",
        "value": "2012-07-31T00:00:00+0200"
      },
      "created_at": {
        "label": "created_at",
        "value": "2016-10-20T16:15:55+0200"
      },
      "last_modified_at": {
        "label": "Last modified",
        "value": "2016-10-22T16:15:55+0200"
      },
      "office": {
        "label": "Office",
        "value": {
          "type": "Office",
          "attributes": {
            "name": "Munich"
          }
        }
      },
      "department": {
        "label": "Department",
        "value": {
          "type": "Department",
          "attributes": {
            "name": "Marketing"
          }
        }
      },
      "cost_centers": {
        "label": "Cost center",
        "value": [
          {
            "type": "CostCenter",
            "attributes": {
              "name": "Cost Center One",
              "id": 320,
              "percentage": 50
            }
          },
          {
            "type": "CostCenter",
            "attributes": {
              "name": "Cost Center Two",
              "id": 321,
              "percentage": 50
            }
          }
        ]
      },
      "fix_salary": {
        "label": "Fix salary",
        "value": 4000
      },
      "hourly_salary": {
        "label": "Hourly salary",
        "value": 0
      },
      "vacation_day_balance": {
        "label": "Vacation day balance",
        "value": 28.5
      },
      "last_working_day": {
        "label": "Last working day",
        "value": "2017-02-28T00:00:00+0200"
      },
      "dynamic_24407": {
        "label": "Titel",
        "value": "Dr"
      },
      "dynamic_21827": {
        "label": "IBAN",
        "value": "DE98 8989 9898 0000 8989 00"
      }
    }
  }
}
 

/company/attendances

 
 
 

get

This endpoint is responsible for fetching attendance data for the company employees. It is possible to paginate results, filter by period and/or specific employees. The result will contain a list of attendance periods, structured as defined here.

 
gethttps://api.personio.de/v1/company/attendances

Query Params

start_date
date
required

First day of the period to be queried. It is inclusive, so the day specified as start_date will also be considered on the results

end_date
date
required

Last day of the period to be queried. It is inclusive, so the day specified as end_date will also be considered on the results.

employees
array of integers

A list of Personio employee identifiers to filter the results. Only those employees specified here will be returned.

limit
integer

Pagination attribute to limit how many attendances will be returned per page

offset
integer

Pagination attribute to identify which page you are requesting, by the form of telling an offset from the first record that would be returned.

 
curl --request GET \
  --url 'https://api.personio.de/v1/company/attendances?start_date=start_date&end_date=end_date'
var request = require("request");

var options = { method: 'GET',
  url: 'https://api.personio.de/v1/company/attendances',
  qs: 
   { start_date: 'start_date',
     end_date: 'end_date' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.personio.de/v1/company/attendances?start_date=start_date&end_date=end_date")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://api.personio.de/v1/company/attendances?start_date=start_date&end_date=end_date");

xhr.send(data);
import requests

url = "https://api.personio.de/v1/company/attendances"

querystring = {"start_date":"start_date","end_date":"end_date"}

response = requests.request("GET", url, params=querystring)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "success": true,
  "offset": 0,
  "limit": 200,
  "data": [
    {
      "id": 1234,
      "type": "AttendancePeriod",
      "attributes": {
        "employee": 325659,
        "date": "2017-01-17",
        "start_time": "9:00",
        "end_time": "18:00",
        "break": 50,
        "comment": "I was productive as hell",
        "is_holiday": false,
        "is_on_time_off": false
      }
    },
    {
      "id": 1235,
      "type": "AttendancePeriod",
      "attributes": {
        "employee": 325660,
        "date": "2017-01-18",
        "start_time": "9:30",
        "end_time": "18:30",
        "break": 60,
        "comment": null,
        "is_holiday": false,
        "is_on_time_off": true
      }
    }
  ]
}
 

post

This endpoint is responsible for adding attendance data for the company employees. It is possible to add attendances for one or many employees at the same time. The payload sent on the request should be a list of attendance periods, in the form of an array containing attendance period objects.

 
posthttps://api.personio.de/v1/company/attendances

Body Params

attendances
array of objects
employee
date
start_time
end_time
break
comment

Post body example:

{
	"attendances": [
		{
			"employee": 12345,
			"date": "2018-09-05",
			"start_time": "08:00",
			"end_time": "11:00",
			"break": 15,
			"comment": "Some comment"
		}, {
			"employee": 12345,
			"date": "2018-09-06",
			"start_time": "09:00",
			"end_time": "18:00",
			"break": 30,
			"comment": "Another comment"
		}
	]
}

Attendance period model description:

attribute
type
description

employee

unsigned integer

the employee id (as returned from the get request)

date

string in format "YYYY-MM-DD"

date of the attendance period

start_time

string in format "HH:MM"

end_time

string in format "HH:MM"

break

unsigned integer

break in minutes

comment

string

optional comment

curl --request POST \
  --url https://api.personio.de/v1/company/attendances
var request = require("request");

var options = { method: 'POST',
  url: 'https://api.personio.de/v1/company/attendances' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.personio.de/v1/company/attendances")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://api.personio.de/v1/company/attendances");

xhr.send(data);
import requests

url = "https://api.personio.de/v1/company/attendances"

response = requests.request("POST", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "success": true,
  "data": {
    "message": "success"
  }
}
{
  "success": true,
  "error": {
    "code": 400,
    "message": "Error when trying to insert Attendances periods rows"
  }
}
 

/company/attendances/{id}

 
 
 

delete

This endpoint is responsible for deleting attendance data for the company employees.

 
deletehttps://api.personio.de/v1/company/attendances/id

Path Params

id
int32
required

ID of the attendance period to delete

 
curl --request DELETE \
  --url https://api.personio.de/v1/company/attendances/id
var request = require("request");

var options = { method: 'DELETE',
  url: 'https://api.personio.de/v1/company/attendances/id' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.personio.de/v1/company/attendances/id")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Delete.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("DELETE", "https://api.personio.de/v1/company/attendances/id");

xhr.send(data);
import requests

url = "https://api.personio.de/v1/company/attendances/id"

response = requests.request("DELETE", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "success": true,
  "data": {
    "message": "The attendance period was deleted."
  }
}
{
  "success": false,
  "error": {
    "code": 404,
    "message": "The attendance period was not found."
  }
}
 

/company/time-offs

 
 
 

get

List All Absence Periods

 
gethttps://api.personio.de/v1/company/time-offs
 
curl --request GET \
  --url https://api.personio.de/v1/company/time-offs
var request = require("request");

var options = { method: 'GET',
  url: 'https://api.personio.de/v1/company/time-offs' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.personio.de/v1/company/time-offs")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://api.personio.de/v1/company/time-offs");

xhr.send(data);
import requests

url = "https://api.personio.de/v1/company/time-offs"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "success": true,
  "data": [
    {
      "type": "TimeOffPeriod",
      "attributes": {
        "status": "approved",
        "start_date": "2017-12-27T00:00:00+0100",
        "end_date": "2017-12-29T00:00:00+0100",
        "days_count": 3,
        "half_day_start": 0,
        "half_day_end": 0,
        "time_off_type": {
          "type": "TimeOffType",
          "attributes": {
            "name": "Vacation"
          }
        },
        "employee": {
          "type": "Employee",
          "attributes": {
            "first_name": {
              "label": "First name",
              "value": "Michael"
            },
            "last_name": {
              "label": "Last name",
              "value": "Miller"
            },
            "email": {
              "label": "Email",
              "value": "michael.miller@demo.com"
            }
          }
        },
        "certificate": {
          "status": "not-required"
        },
        "created_at": "2017-01-17T10:32:18+0100"
      }
    }
  ]
}
 

/company/time-off/{time_off_id}

 
 
 

get

Absence Period

 
gethttps://api.personio.de/v1/company/time-off/time_off_id

Path Params

time_off_id
integer
required

Numeric id of the absence period

 
curl --request GET \
  --url https://api.personio.de/v1/company/time-off/time_off_id
var request = require("request");

var options = { method: 'GET',
  url: 'https://api.personio.de/v1/company/time-off/time_off_id' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.personio.de/v1/company/time-off/time_off_id")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://api.personio.de/v1/company/time-off/time_off_id");

xhr.send(data);
import requests

url = "https://api.personio.de/v1/company/time-off/time_off_id"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "success": true,
  "data": {
    "type": "TimeOffPeriod",
    "attributes": {
      "status": "approved",
      "start_date": "2017-12-27T00:00:00+0100",
      "end_date": "2017-12-29T00:00:00+0100",
      "days_count": 3,
      "half_day_start": 0,
      "half_day_end": 0,
      "time_off_type": {
        "type": "TimeOffType",
        "attributes": {
          "name": "Vacation"
        }
      },
      "employee": {
        "type": "Employee",
        "attributes": {
          "first_name": {
            "label": "First name",
            "value": "Michael"
          },
          "last_name": {
            "label": "Last name",
            "value": "Miller"
          },
          "email": {
            "label": "Email",
            "value": "michael.miller@demo.com"
          }
        }
      },
      "certificate": {
        "status": "not-required"
      },
      "created_at": "2017-01-17T10:32:18+0100"
    }
  }
}