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:

' 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:

]]>' - name: Dein Profil value: '
  • Du bist herzlich, offen und kommunikativ
  • Du bist ein Organisationstalent und magst den Umgang mit Zahlen
  • Du bist gewissenhaft, sorgfältig und strukturiert
  • Du zeigst Eigeninitiative und Kreativität bei der Planung neuer Aktionen
  • Du sprichst Deutsch auf muttersprachlichem Niveau und hast gute Englischkenntnisse
  • Du 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 lernen
  • Kreatives Arbeitsumfeld und kurze Entscheidungswege
  • Von Anfang an volle Verantwortung in Deinem Bereich
  • Regelmäßige Team-Events, Tischtennis und Ausflüge ins Münchner Nachtleben
  • Bü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'