openapi: 3.0.0
info:
version: '1.0'
title: Recruiting
description: '
The Recruiting API allows you to GET open job positions, and POST applications to Personio. Other methods are currently not supported.
Note: Some URLs in this document depend on your personio hostname. They are represented via the placeholder "{YOUR_COMPANY}".
'
paths:
/xml:
parameters:
- $ref: "#/components/parameters/XPersonioPartnerID"
- $ref: "#/components/parameters/XPersonioAppID"
- $ref: "#/components/parameters/XCompanyID"
get:
servers:
- url: 'https://{YOUR_COMPANY}.jobs.personio.de'
description: Career Site URL
variables:
YOUR_COMPANY:
default: personio
description: Company hostname.
tags:
- XML
summary: Retrieve open positions
parameters:
- in: query
name: language
schema:
type: string
enum:
- de
- en
- fr
- es
- nl
- it
- pt
required: true
description: 'Language code. One of: de, en, fr, es, nl, it, pt.'
description: 'This is the job positions XML feed from the Company Career Site.
The XML feed can be accessed in multiple languages, depending on the languages available for the Career Site. To URL of the XML feed in English is: https://{YOUR_COMPANY}.jobs.personio.de/xml?language=en
This is the complete list of available languages and URLs:
- https://{YOUR_COMPANY}.jobs.personio.de/xml?language=de - German
- https://{YOUR_COMPANY}.jobs.personio.de/xml?language=en - English
- https://{YOUR_COMPANY}.jobs.personio.de/xml?language=fr - French
- https://{YOUR_COMPANY}.jobs.personio.de/xml?language=es - Spanish
- https://{YOUR_COMPANY}.jobs.personio.de/xml?language=nl - Dutch
- https://{YOUR_COMPANY}.jobs.personio.de/xml?language=it - Italian
- https://{YOUR_COMPANY}.jobs.personio.de/xml?language=pt - Portuguese
'
responses:
'200':
description: 'An example response looks like this:'
content:
application/xml:
schema:
$ref: '#/components/schemas/XmlResponse'
/v1/recruiting/applications:
servers:
- url: 'https://api.personio.de'
parameters:
- $ref: "#/components/parameters/XPersonioPartnerID"
- $ref: "#/components/parameters/XPersonioAppID"
- $ref: "#/components/parameters/XCompanyID"
post:
tags:
- Application
security:
- bearerAuth: []
summary: Creating applications in Personio
description: Allows you to create applications in Personio.
responses:
'201':
description: Created - Application was created successfully.
'400':
description: Bad Request - The application could not be created because some properties of the request did notch match their expectation. Check body for details.
content:
application/json:
schema:
$ref: '#/components/schemas/error_response'
'401':
description: 'Unauthorized - The API token and/or company id was not recognized. Please provide a valid API token in as value of an `Authorization` header, like `Bearer api-token-value`.'
'403':
description: Forbidden - Your company does not have access to one of the features used in this request.
content:
application/json:
schema:
$ref: '#/components/schemas/error_response'
'429':
description: Too Many Requests - You have exceeded the rate-limit for your API call.
'500':
description: Internal Server Error - An unexpected error occurred. Check body for details.
content:
application/json:
schema:
$ref: '#/components/schemas/error_response'
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/submit_application'
/v1/recruiting/applications/documents:
servers:
- url: 'https://api.personio.de'
parameters:
- $ref: "#/components/parameters/XPersonioPartnerID"
- $ref: "#/components/parameters/XPersonioAppID"
- $ref: "#/components/parameters/XCompanyID"
post:
tags:
- Application Documents
security:
- bearerAuth: []
summary: Upload documents to be attached to applications
description: Uploading files to this endpoint enables you to attach them to an application later. Please keep in mind that the auto-generated code on the right-hand side when adding a file from this tool should only be considered as a guide, and might not work when copy-pasting in your code directly. Please refer to the documentation for the language/library you are using on how to upload a multipart-form-data file.
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/uploaded_document'
'401':
description: 'Unauthorized - The API token and/or company id was not recognized. Please provide a valid API token in as value of an `Authorization` header, like `Bearer api-token-value`.'
'403':
description: Forbidden - Your company does not have access to one of the features used in this request.
'413':
description: Payload Too Large - Your document exceeded the size limit. Check body for details.
content:
application/json:
schema:
$ref: '#/components/schemas/error_response'
'422':
description: Unprocessable Entity - The document you provided could not be processed. Check body for details.
content:
application/json:
schema:
$ref: '#/components/schemas/error_response'
'429':
description: Too Many Requests - You have exceeded the rate-limit for your API call.
'500':
description: Internal Server Error - An unexpected error occurred. Check body for details.
content:
application/json:
schema:
$ref: '#/components/schemas/error_response'
requestBody:
content:
multipart/form-data:
schema:
type: object
properties:
file:
type: string
format: binary
description: |
The file to be uploaded.
Maximum file size: 20MB
Must be one of the supported types: pdf, pptx, xlsx, docx, doc, xls, ppt, ods, odt, 7z, gz, rar, zip, bmp, gif, jpg, png, tif, csv, txt, rtf, mp4, 3gp, mov, avi, wmv
required:
- file
/recruiting/applicant:
servers:
- url: 'https://api.personio.de'
parameters:
- $ref: "#/components/parameters/XPersonioPartnerID"
- $ref: "#/components/parameters/XPersonioAppID"
- $ref: "#/components/parameters/XCompanyID"
post:
tags:
- "[DEPRECATED] Applicant"
summary: Passing applications to Personio
description: |-
DEPRECATED: This method of passing application to Personio is deprecated and will only receive bugfixes. New implementations should interact with the /v1/recruiting/applications endpoints above, existing implementators are advised to migrate to them.
---
A note on categorised documents
Categorised documents are represented as a multidimensional array.
Each object has two fields: 'file' and 'category'. The 'file' field contains an upload stream. The 'category field' contains the category name, the allowed category names are listed in the table above. An example in pseudo code would be:
val request = HttpRequest()
// Example of a CV file
$data['categorised_documents[0][file]'] = new CURLFile('/path/to/cv.pdf','application/pdf');
$data['categorised_documents[0][category]'] = 'cv';
// Example of a cover letter file
$data['categorised_documents[0][file]'] = new CURLFile('/path/to/cover-letter.pdf','application/pdf');
$data['categorised_documents[0][category]'] = 'cover-letter';
// ... fill in all the required params ...
// configure the CURL request
$request = curl_init('https://api.personio.de/recruiting/applicant');
curl_setopt($request, CURLOPT_POST, 1);
curl_setopt($request, CURLOPT_POSTFIELDS, $data);
// Execute it
curl_exec($request);
A note on documents
Documents need to be submitted as an upload stream not just with a plain file path. An example in PHP code would be:
$data['document1'] = 'path-to-file' // this will not work!
$data['document1'] = new CURLFile('path-to-file') // Correct
A note on spamming
Please be aware that the access_token in company with your company_id allows the creation of applications in your account. When building your own career page, we would recommend that you call our endpoints from a backend service, rather than from your frontend directly, in order to avoid making the token publicly accessible. In addition to this, we recommend the inclusion of a captcha or similar into your own career page to avoid bot applications.
Rate limiting
Our applicant API is a rate limit of 100 applications in 60 seconds per IP address. After submitting this amount of applications, you will need to wait 60 seconds before you can submit more applications.
requestBody:
content:
multipart/form-data:
schema:
$ref: '#/components/schemas/Applicant'
description: Applicant data
required: true
responses:
'200':
description: Everything went well and the application was created in Personio.
content:
application/json:
examples:
Success:
value:
success: true
data:
message: Applicant successfully applied to the job position.
'400':
description: 'Something went wrong and the application was not created in Personio. Specifically, the following cases can lead to an error 400:'
content:
application/json:
examples:
File too large:
value:
success: false
error:
message: Unsupported extension or file greater than 20Mb.
Unsupported file extension:
value:
success: false
error:
message: Unsupported extension or file greater than 20Mb.
'Required field empty (e.g. name, email)':
value:
success: false
error:
message: 'The {field_name} field is required.'
Invalid custom attribute (custom attribute ID does not exist):
value:
success: false
error:
message: 'Parameter {parameter_name} does not exist.'
Invalid job position:
value:
success: false
error:
message: Could not find the job position.
Applicant already applied:
value:
success: false
error:
message: Applicant already applied to this position.
'403':
description: 'Something went wrong and the application was not created in Personio. In this case, the API access token provided doesn''t match the company ID.'
content:
application/json:
examples:
Not Authorized:
value:
success: false
error:
message: This action is unauthorized.
'422':
description: Something is wrong with the request body or the attachments.
content:
application/json:
examples:
Unprocessable Entity 1:
value:
success: false
error:
message: There was a problem while processing attachments. Try again later
Unprocessable Entity 2:
value:
success: false
error:
message: Job position not published
'500':
description: 'Something went wrong and the application was not created in Personio. This particular case the transaction failed due to an issue on Personio''s end, e.g. server error.'
content:
application/json:
examples:
Internal Server Error:
value:
success: false
error:
message: 'Something went wrong, please try again later!'
'503':
description: 'The server is currently unable to handle the request due to a temporary overload or scheduled maintenance, which will likely be alleviated after some delay.'
content:
application/json:
examples:
Service Unavailable:
value:
success: false
error:
message: Service Unavailable
deprecated: true
servers:
- url: 'https://api.personio.de'
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
description: |-
Found under `Settings > API > Access Data > Recruiting API Access Token`
This token allows creation of applications in your account. When building your own career page, we recommend that you call our endpoints from a backend service, rather than from your frontend directly to not expose this token.
Example Header: `Authorization: Bearer our-token`
parameters:
XCompanyID:
name: X-Company-ID
in: header
required: true
description: Your company's Personio Id
schema:
type: string
XPersonioPartnerID:
name: X-Personio-Partner-ID
in: header
required: false
description: The partner identifier
schema:
type: string
XPersonioAppID:
name: X-Personio-App-ID
in: header
required: false
description: The application identifier
schema:
type: string
schemas:
submit_application:
type: object
properties:
first_name:
type: string
description: First name(s) of the applicant. Must not be empty or only whitespaces
minLength: 1
last_name:
type: string
description: Last name(s) of the applicant. Must not be empty or only whitespaces.
minLength: 1
email:
type: string
description: Email address of the applicant.
format: email
job_position_id:
type: integer
description: The personio internal id of the job this application should belong to.
recruiting_channel_id:
type: integer
description: |-
The recruiting channel this application was sourced from.
See https://{YOUR_COMPANY}.personio.de/configuration/recruiting/channels
external_posting_id:
type: string
description: |-
The external id of the job posting (E.g. the external id forwarded by Gohiring).
message:
type: string
description: The applicant supplied free-text message.
application_date:
type: string
description: The application date (yyyy-mm-dd). It cannot be a date in the future.
format: date
phase:
type: object
description: |-
This can be a system or a custom application phase. When not provided, the application will be created with the initial phase according to the configuration for this job position's category (https://{YOUR_COMPANY}.personio.de/configuration/recruiting/categories).
When an invalid phase is provided (e.g. a non-existent custom phase or one that is not configured for this job position's category), the application will be created with the phase `unassigned`.
properties:
type:
type: string
enum:
- system
- custom
description: The type of application phase.
id:
oneOf:
- type: string
- type: integer
description: |-
For custom phases this is an integer. The IDs for your custom phases can be found under your personio settings (https://{YOUR_COMPANY}.personio.de/configuration/recruiting/phases).
For system phases this is a string and must be one of:
- unassigned
- rejected
- withdrawn
- offer
- accepted
required:
- type
- id
tags:
type: array
description: |-
Tags to be associated with this application. Non-existing tags will be created.
See https://{YOUR_COMPANY}.personio.de/configuration/recruiting/tags
items:
type: string
files:
description: |-
References to previously uploaded files. These will be attached to the new application.
Each file item consists of a `uuid`, an `original_filename` and a `category` (To see exact description, click on "ADD OBJECT").
type: array
items:
type: object
properties:
uuid:
type: string
format: uuid
description: Reference to a previously uploaded file. Use the `uuid` value returned from the documents endpoint here.
original_filename:
type: string
category:
type: string
enum:
- cv
- cover-letter
- employment-reference
- certificate
- work-sample
- other
description: Category of referenced document.
required:
- uuid
- original_filename
- category
attributes:
type: array
description: |-
Attributes for this applicant.
Each attribute item consists of an `id` and a `value` (To see exact description, click on "ADD OBJECT").
items:
type: object
properties:
id:
type: string
description: |-
Ids for custom attributes have the form `custom_attribute_123` and can be found can be found in your personio settings as `API name` when expanding the details of each attribute (https://{YOUR_COMPANY}.personio.de/configuration/recruiting/attributes).
Ids for supported system attributes are:
- birthday (YYYY-MM-DD)
- gender (male / female / diverse / undefined)
- location
- phone
- available_from
- salary_expectations
value:
type: string
description: |-
Value of the attribute.
For OPTION attributes, this must be one of the predefined options.
For DATE attributes, this needs to follow ISO 8601 Local date, i.e. `2021-04-30`
required:
- id
- value
required:
- first_name
- last_name
- email
- job_position_id
uploaded_document:
type: object
properties:
uuid:
type: string
format: uuid
description: The UUID of this file. Can be attached to an application by including this uuid in the application creation request.
size:
type: integer
description: Uploaded file size in bytes.
mimetype:
type: string
description: Detected Mime Type of this file.
original_filename:
type: string
extension:
type: string
enum:
- pdf
- pptx
- xlsx
- docx
- doc
- xls
- ptt
- ods
- odt
- 7z
- gz
- rar
- zip
- bmp
- gif
- jpg
- png
- tif
- csv
- txt
- rtf
- mp4
- 3gp
- mov
- avi
- wmv
required:
- uuid
- size
- mimetype
- original_filename
- extension
error_response:
title: Error Response
type: object
description: |-
Includes details about errors when submitting an application.
Possible Error codes:
| code | Meaning |
|:---------------------------------------------------: |:---------------------------------------------------------------------------:|
| errors.attribute-validation.unknown | The supplied attribute was not found in our system. |
| errors.attribute-validation.required-attribute | A required attribute was missing, null or blank. |
| errors.attribute-validation.invalid-date-format | The supplied date attribute did not match the "ISO-8601 Local Date" format. |
| errors.attribute-validation.invalid-email-format | The supplied email seems not to be valid. |
| errors.attribute-validation.invalid-type | The supplied attribute type is not supported. |
| errors.attribute-validation.unknown-attribute-option | The attribute value is not in the provided options. |
| errors.date-validation.date-in-the-future | Invalid application date. |
| errors.phase-validation.invalid-system-phase | The supplied application phase is not supported. |
| errors.file-validation.file-not-exists | The supplied reference could not be resolved. |
| errors.file-validation.unknown-file-category | The supplied document category is not supported. |
| errors.invalid-file-type | The supplied file is of an unsupported format. |
| errors.file-too-big | The file size exceeded the configured limit |
| errors.applicant-already-exists | We could not verify that this email has not yet applied to this position. |
| errors.posting-validation.posting-not-found | The job posting could not be found or did not match the supplied channel. |
| errors.posting-validation.channel-not-found | The recruiting channel could not be found. |
| errors.job-position.not-published | Job position for which the application is created is not published. |
| feature.recruiting.disabled | Your company does not have access to Personio's recruiting features. |
| feature.public-api.disabled | Your company does not have access to Personio's recruiting API. |
properties:
errors:
type: array
description: ''
items:
oneOf:
- properties:
field:
type: string
description: Indicates location of the error. Values are guaranteed to be unique in the `errors` array.
errors:
type: array
description: All errors of this field.
items:
type: object
properties:
reason:
type: string
description: An error code. See description.
context:
type: object
description: Optional context on the error code.
required:
- reason
required:
- field
- errors
- properties:
id:
type: string
format: uuid
description: Internal error reference.
status:
type: string
description: HTTP status code
title:
type: string
description: HTTP Status reason
detail:
type: string
required:
- id
- status
- title
type: object
required:
- errors
Response:
title: Default response object
type: object
properties:
success:
type: boolean
data:
type: object
required:
- success
- data
XmlResponse:
title: XmlResponse
type: object
properties:
posting:
type: array
items:
$ref: '#/components/schemas/JobPosting'
xml:
name: workzag-jobs
JobPosting:
title: Job Posting
type: object
properties:
id:
type: integer
example: 4103
subcompany:
type: string
example: ''
office:
type: string
example: Munich
department:
type: string
example: Management
recruitingCategory:
example: Various
name:
example: Office- und Feelgood Manager (m/w)
jobDescriptions:
title: Job Descriptions
type: object
properties:
jobDescription:
type: array
items:
$ref: '#/components/schemas/jobDescriptionItem'
employmentType:
type: string
enum:
- permanent
- intern
- trainee
- freelance
example: permanent
seniority:
type: string
enum:
- entry-level
- experienced
- executive
- student
example: entry-level
schedule:
type: string
enum:
- full-time
- part-time
example: full-time
yearsOfExperience:
type: string
enum:
- lt-1
- 1-2
- 2-5
- 5-7
- 7-10
- 10-15
- gt-15
example: lt-1
keywords:
type: string
example: 'office manager,project management,büro,assistenz,organisation,part time,Teilzeit'
occupation:
example: office_management
occupationCategory:
example: administrative_and_clerical
createdAt:
example: '2016-05-31T12:14:07+0200'
xml:
name: position
jobDescriptionItem:
type: array
items:
allOf:
- $ref: '#/components/schemas/JobDescription'
example:
- name: Beschreibung
value: '
Deine Aufgaben:
- Ansprechpartner in Sachen Büro, Ausstattung und anderer “Wohlfühl”-Themen, die unseren Mitarbeiter/innen auf dem Herzen liegen
- Bearbeitung von generellen Anfragen, Post und Eingangsrechnungen
- Kommunikation und Organisation unserer Servicedienstleister und Zulieferer
- Selbstständige Entwicklung & Umsetzung neuer Ideen, Aktionen und Events für unsere Mitarbeiter
- Unterstützung unseres Management-Teams bei organisatorischen Aufgaben
- Management unserer Unu-Elektroroller-Flotte (ja, du bekommst auch einen, wenn du möchtest)
]]>'
- name: Dein Profil
value: 'Du bist herzlich, offen und kommunikativDu bist ein Organisationstalent und magst den Umgang mit ZahlenDu bist gewissenhaft, sorgfältig und strukturiertDu zeigst Eigeninitiative und Kreativität bei der Planung neuer AktionenDu sprichst Deutsch auf muttersprachlichem Niveau und hast gute EnglischkenntnisseDu hast Spaß an vielfältigen Aufgaben und unterstützt gerne dort, wo Hilfe gebraucht wird ]]>'
- name: Warum Personio
value: 'Chance in einem schnell wachsenden Unternehmen an vielfältigen Aufgaben zu wachsen und zu lernenKreatives Arbeitsumfeld und kurze EntscheidungswegeVon Anfang an volle Verantwortung in Deinem BereichRegelmäßige Team-Events, Tischtennis und Ausflüge ins Münchner NachtlebenBüro im Herzen von München (nahe Gärtnerplatz)Blitzschneller Elektroroller deiner Wahl als “Geschäftswagen” ]]>'
JobDescription:
title: Job Description
type: object
properties:
jobDescription:
type: object
properties:
name:
type: string
value:
type: string
Applicant:
title: Applicant
type: object
properties:
company_id:
description: Your company ID (see endpoint description)
type: integer
access_token:
description: API Access token for your company account (see endpoint description)
type: string
job_position_id:
description: ID of the published job position that this application is for (from XML feed)
type: integer
first_name:
description: First name of the applicant
type: string
maxLength: 255
last_name:
description: Last name of the applicant
type: string
maxLength: 255
email:
description: Email address of the applicant
type: string
maxLength: 255
gender:
description: Gender of the applicant
type: string
enum:
- male
- female
- diverse
- undefined
recruiting_channel_id:
description: ID of the recruiting channel that this applicant applied through recruiting_channel_id has to match the id of a channel you created in Personio
type: integer
external_posting_id:
description: 'When using multiposting, this is the `pid` forwarded (usually as a query param) by the external job board site'
type: string
maxLength: 255
phone:
description: Phone number of the applicant
type: string
maxLength: 255
location:
description: Current location of the applicant
type: string
maxLength: 255
salary_expectations:
description: 'Salary expectations of the applicant (Will not be parsed, so you can transfer values like "minimum 50k")'
type: string
maxLength: 255
available_from:
description: Date from which this applicant is available from
type: string
maxLength: 100
'categorised_documents[n][file]':
description: 'Nth document
The file should be an upload stream.
You can check a request example in the "A note on categorised documents" section.
[array of files]
allowed extensions are ''pdf'', ''docx'', ''doc'', ''jpg'', ''png'', ''txt'', ''jpeg'', ''odt'', ''ods'',''xlsx'', ''rtf'', ''xls'', ''pptx'', ''ppt'', ''gif'', ''tif'', ''tiff'', ''bmp'', ''csv'', ''rar'', ''gz'', ''zip'', ''7z'';
filesize per document < 20M;
total post size < 64M;
'
type: string
format: binary
'categorised_documents[n][category]':
description: 'Nth document''s category
Category of the Nth file.
You can check a request example in the "A note on categorised documents" section.
allowed values are ''cv'', ''cover-letter'', ''employment-reference'', ''certificate'', ''work-sample'' or ''other''
'
type: string
'documents[n]':
description: 'Nth document
The file should be an upload stream.
allowed extensions are ''pdf'', ''docx'', ''doc'', ''jpg'', ''png'', ''txt'', ''jpeg'', ''odt'', ''ods'',''xlsx'', ''rtf'', ''xls'', ''pptx'', ''ppt'', ''gif'', ''tif'', ''tiff'', ''bmp'', ''csv'', ''rar'', ''gz'', ''zip'', ''7z'';
filesize per document < 20M;
total post size < 64M;
'
type: string
format: binary
'document{n}':
description: 'Alternatively to an array (see ''documents''), documents can also be transferred individually numbered document1, document2, etc (the numbering starts at 1) with the absolute path to the document in an upload stream.
[file]
allowed extensions are ''pdf'', ''docx'', ''doc'', ''jpg'', ''png'', ''txt'', ''jpeg'', ''odt'', ''ods'',''xlsx'', ''rtf'', ''xls'', ''pptx'', ''ppt'', ''gif'', ''tif'', ''tiff'', ''bmp'', ''csv'', ''rar'', ''gz'', ''zip'', ''7z'';
filesize per document < 20M;
total post size < 64M
'
type: object
allOf:
- $ref: '#/components/schemas/Document'
message:
description: Initial message from the applicant
type: string
tags:
description: 'Existing tags (new ones cannot be created via API)
[array of strings], e.g. [ “tag_1”, “tag_2" ]'
birthday:
description: Birthday of the applicant.
Date according to ISO 8601 format (YYYY-MM-DD)
type: string
format: date
'custom_attribute_{id}':
description: 'Custom applicant attribute.
Custom applicant attributes that were created individually can also be passed.
You can find the unique parameter names of these attributes in your Personio account under: https://{YOUR_COMPANY}.personio.de/configuration/recruiting/applicants
'
type: integer
required:
- company_id
- access_token
- job_position_id
- first_name
- last_name
- email
Document:
title: Document
type: object
properties:
file:
type: string
format: binary
description: 'allowed extensions are ''pdf'', ''docx'', ''doc'', ''jpg'', ''png'', ''txt'', ''jpeg'', ''odt'', ''ods'',''xlsx'', ''rtf'', ''xls'', ''pptx'', ''ppt'', ''gif'', ''tif'', ''tiff'', ''bmp'', ''csv'', ''rar'', ''gz'', ''zip'', ''7z'' filesize per document < 20M total post size < 64M'