NAV Navbar
Logo
HTTP

Topics

Teamtailor Job Board API

Example use cases of this API:

If you are interested in integrating with us, check below options and contact us at partnerships@teamtailor.com.

Integration types

Teamtailor offers several ways for your job board to integrate with us:

1. HTTP Webhooks

When a user creates/updates/removes a job ad Teamtailor will send a JSON request that contains the job ad data. Read more here.

2. Always included XML feed

Teamtailor generates a unique XML feed for a single job board containing all job ads from custromers who activated the integration. It’s generated three times a day. The job board will receive a unique url to the XML feed. The feed contains a current state of job ads, that means if the job is unlisted on Teamtailor it will be removed from the XML feed - job board should remove it as well. An example feed is here. Read more here.

3. Premium XML feed

XML feed containing all job ads selected by the user to promote. It works in the same way as described in Always included XML feed, except the XML feed contains only selected job ads. Each job ad node in the XML feed contains a special tag used to identify the company. Read more here.

4. Email with job data

Job board provider receives an email with job ad data when the user selects it to be promoted. Teamtailor sends email when a job ad is created/updated/removed. Read more here.

Webhook signatures

To validate authenticity of webhooks sent by Teamtailor we include a Teamtailor-Signature header in each request. The header contains a HMAC and allows you to validate that the webhook was actually sent by Teamtailor. You can use your job board api key to verify secret token.

Signature structure

The structure of Teamtailor-Signature is a timestamp (to prevent replay attacks) followed by a comma and two or more schemes separated by commans. The current only valid signature scheme is v1 and the latest scheme should always be used to prevent downgrading attacks.

# Example signature
Teamtailor-Signature: t=1539756759,
  v1=2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae,
  v0=fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9

Checking signatures

To validate a signature you may first check that the timestamp is in valid range (eg five minutes). This range is, however, up to you.

After checking the timestamp you can verify the hash by computing it yourself and compare it to the lastest hash included in the request, vX. If it match, Teamtailor sent the webhook.

# Computing the hash
hash = sha256(timestamp + "." + payload, secret_key)

Example implementation (Node)

// Bundled with Node
const crypto = require('crypto');

// External dependencies
const express = require('express');
const bodyParser = require('body-parser');

// Webhook secret as environment variable
const SECRET = process.env.WEBHOOK_SECRET;

app.post('/webhook', bodyParser.raw({type: 'application/json'}), (req, res) => {
  const signaturePattern = /^t=(\d+),v\d=(\w+),.+$/;
  const signature = req.headers['teamtailor-signature'];
  const [_, timestamp, cHmac] = signaturePattern.exec(signature);
  const payload = `${timestamp}.${payload}`;
  const hmac = crypto.createHmac('sha256', SECRET)
    .update(payload, 'utf-8')
    .digest('hex');
  if (cHmac === hmac) {
    // Signature check passed.
    // If you want to prevent replay attacks, check timestamp as well.
    return res.status(200).send();
  }
  return res.status(401).send();
})

HTTP Webhooks

When a user creates, updates or removes a job in Teamtailor, you will receive a webhook JSON request that contains the job ad data.

You will need to configure and handle the following endpoints:

  1. GET ${BASE_URL}/config - provide options for a form rendered to the user
  2. POST ${BASE_URL}/webhook - handle created job ad in Teamtailor
  3. PUT ${BASE_URL}/webhook - handle updated job ad in Teamtailor
  4. DELETE ${BASE_URL}/webhook/:reference_id - handle deleted job ad in Teamtailor

GET Config

When user want to publish a job ad we display a form. Use this endpoint to configure the options visible in the form by returning the configuration object in the response.

GET ${BASE_URL}/config?page=1&job_id=23 HTTP/1.1

Example of expected config response

{
  "config": {
    "1": [
      {
        "id": "experience-level",
        "label": "Experience level",
        "placeholder": "Experience level",
        "type": "select",
        "options": [
          { "id": 1, "label": "Junior" },
          { "id": 2, "label": "Senior" },
        ]
      }
    ],
    "2": [
      {
        "id": "degree-level",
        "label": "Required degree level",
        "placeholder": "Choose degree level",
        "type": "select",
        "options": [
          { "id": 1, "label": "Bachelor's Degree" },
          { "id": 2, "label": "Master's Degree" },
        ]
      },
    ],
    "page": 1,
    "hasNextPage": true
  }
}

HTTP Request

GET ${BASE_URL}/config

Query parameters

Expected config response

Attribute Type Description
config object Top-level object
page number Indicates current page
hasNextPage boolean Indicates whether there is a next page to be fetched

Field objects

Attribute Type Description
id string Identifier for this field, will be sent in webhook
label string Human readable label
placeholder string Form placeholder
type string Type of form element (see below)
options array Options

Supported field types

Field objects follow the HTML form standard in regards to types, possible options, labels and placeholders. For example, disabled may be provided for the “text” type, step, min and max may be provided for the “number” type and an options array with id/label may be provided for the “select” type.

All of the supported field types:

Pagination

We support multiple pages of the config form (pagination). In order to do that, you have to include more than one config page object, as well as handle a page (current page) and hasNextPage attributes in the response. In order to make the form dependent on the previously selected options, there will be included query string parameters with the selected options (id=value).

Example of paginated config response

{
  "config": {
    "1": [],
    "2": [],
    "3": [],
    "page": 1,
    "hasNextPage": true
  }
}

POST Webhook

When user picks options in the form and submit it, the webhook POST request will be send.

POST ${BASE_URL}/webhook HTTP/1.1

{
  "id": "04798257-51ff-42e4-aa56-61e75632f23b",
  "reference-id": "1",
  "created-at": "2021-03-24T00:00:00+01:00",
  "duration": 30,
  "job-board-id": "job_board",
  "webhook-data": {
    "experience-level": "Junior",
    "degree-level": "Master's Degree"
  },
  "location": {
    "address": "Sankt Paulsgatan 7B",
    "city": "Stockholm",
    "country": "Sweden",
    "country-code": "SE",
    "zip": "118 46"
  },
  "company": {
    "name": "Teamtailor",
    "company-info-about": "Cupio barba articulus.</p><p>Spes deleniti cubicularis.",
    "url": "https://career.teamtailor.localhost",
    "uuid": "ZPXFT2VMtr8",
    "subdomain": "career",
    "logotype": "https://example.com/original.jpg",
    "headquarters": {
      "address": "Sankt Paulsgatan 7B",
      "city": "Stockholm",
      "country": "Sweden",
      "country-code": "SE",
      "zip": "118 46"
    }
  },
  "job": { 
    "title": "Marketing Coordinator",
    "body": "Depereo decumbo defungo. Ubi stipes vel. Cupio barba articulus.",
    "remote-status": "none",
    "employment-type": "none",
    "employment-level": "none",
    "url": "https://career.teamtailor.localhost/jobs/23-marketing-coordinator",
    "apply-url": "https://career.teamtailor.localhost/jobs/23-marketing-coordinator/applications/new?promotion=2-monster-finland",
    "cover-image-url": "https://example.com/original.jpg",
    "pitch": "Coadunatio centum animi. Succedo adversus inventore. Rem est uberrime.",
    "start-date": "2021-03-24T00:00:00+01:00",
    "end-date": "2021-03-31T00:00:00+02:00",
    "created-date": "2021-03-02T19:18:22+01:00",
    "apply-button-text": "Apply now",
    "department": {
      "name": "Business Marketing"
    },
    "role": {
      "name": "Marketer"
    },
    "recruiter": {
      "name": "Hammes Grud",
      "email": "email1@example.com",
      "phone": "123456"
    },
    "locations": [
      {
        "address": "Sankt Paulsgatan 7B",
        "city": "Stockholm",
        "country": "Sweden",
        "country-code": "SE",
        "zip": "118 46"
      },
      {
        "address": "Sankt Paulsgatan 7B",
        "city": "Stockholm",
        "country": "Sweden",
        "country-code": "SE",
        "zip": "118 46"
      }
    ],
    "salary": {
      "min-salary": "500.0",
      "max-salary": "800.0",
      "salary-currency": "EUR",
      "salary-time-unit": "monthly"
    },
    "custom-fields": [
      { id: 3, name: 'Custom date', value: '2023-06-14' },
      { id: 9, name: 'Custom bool', value: true },
      {
        id: 8,
        name: 'Custom multiselect',
        value: [ 'Multiselect option 3', 'Multiselect option 1' ]
      },
      { id: 7, name: 'Custom select', value: [ 'Option 2' ] },
      { id: 6, name: 'Custom number', value: 44 },
      { id: 5, name: 'Custom string', value: 'String' }
    ]
  }
}

HTTP Request

POST ${BASE_URL}/webhook

Webhook JSON object

Attribute Value
id Unique identifier of this event
reference-id Unique identifier of job ad in Teamtailor
created-at Date when job ad was created
duration Duration of job ad. In days
job-board-id Unique identifier of job board in Teamtailor
webhook-data Object containg picked options by user
location Location of the job ad. User can optionally select it during purchasing the job ad. Implements location object
company Company that job belongs to. Implements company object
job Job data. Implements job object

Location object

Attribute Value
address Address
city City name
country Country name
country-code Country code
zip Postal code

Company object

Attribute Value
name Company name
company-info-about Description of the company
url URL to the company’s website
uuid Company’s uuid
subdomain Company’s subdomain
logotype URL to the company’s logo
headquarters Company’s headquarters. Implements location object

Job object

Attribute Value
title Job title
body Job description
remote-status Remote status. One of following: none, temporary, hybrid, fully
employment-type Employment type. One of following: none, fully, part, contract, temporary, apprenticeship, internship, volunteer
employment-level Employment level. One of following: none, senior, mid, professionals, technicians, sales, administrative, support, craft, operatives, laborers, service
url URL to the job ad in Teamtailor
apply-url URL to the job apply form in Teamtailor
cover-image-url URL to the job cover image
pitch Pitch text about the job
start-date Date from when the job ad is published
end-date Date when job ad will be unlisted
created-date Date when job ad was created
apply-button-text Text displayed on “apply” button
department.name Name of the job’s department
role.name Name of the job’s role
recruiter Recruiter of the job. Implements recruiter object
locations Locations of the job. Implements many location objects
salary Salary of the job. Implements salary object

Recruiter object

Attribute Value
name Recruiter name
email Recruiter email
phone Recruiter phone

Salary object

Attribute Value
min-salary Minimum salary for the job if range otherwise offered salary amount
max-salary Maximum salary for the job
salary-currency Salary currency
salary-time-unit Salary time unit. One of the following monthly, hourly, yearly, daily

Custom fields object

Attribute Value
id Unique identifier of this custom field
name Field name set up by user
value Can be array of strings, string, number, boolean, date in format YYYY-MM-DD

Example of expected response

{
  "body": {
    "externalId": "044a35ea-0fe1-49d3-a2aa-e67b0e89dd3e"
  }
}

Expected response

We expect successfull response to have a HTTP 200 OK response code. The response must include externalId which should be your internal identifier of the job ad.

Example of expected error response

{
  "body": {
    "externalId": "044a35ea-0fe1-49d3-a2aa-e67b0e89dd3e"
  },
  "errors": ["Job title can't be longer than 80 characters"]
}

Error handling

When something will went wrong on your end (e.g. validation error) we will display the error message to the user. In that case the response code must be other than HTTP 2xx and you have to include an errors attribute, which is array of error messages.

PUT Webhook

When user updates options in the form and submit it, the webhook PUT request will be send. It works in the same way as POST Webhook in terms of a request structure and an expected response.

PUT ${BASE_URL}/webhook HTTP/1.1

HTTP Request

PUT ${BASE_URL}/webhook

DELETE Webhook

When job ad is unlisted in Teamtailor, the webhook DELETE request will be send.

DELETE ${BASE_URL}/webhook/:reference_id HTTP/1.1

HTTP Request

DELETE ${BASE_URL}/webhook/:reference_id

Transferring secrets

Example of Authorization header

POST ${BASE_URL}/webhook HTTP/1.1
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

If you require secrets from user, e.g. API key or password, we will include it in a headers of every request. It is a JWT Bearer token placed in Authorization header, encoded using HS256 signing algorithm.

In order to decode it and get the secrets, you will need a signing key. We will provide it to you if you ask us at integrations@teamtailor.com.

XML feed

If you choose the Always included or Premium XML feed integration, you will receive a unique url to the XML feed.

Example XML feed

<source>
  <publisher>Teamtailor</publisher>
  <publisherurl>https://www.teamtailor.com</publisherurl>
  <lastupdatedat>
    <![CDATA[ 2021-03-23T10:50:08+01:00 ]]>
  </lastupdatedat>
  <job>
    <company>
      <![CDATA[ Test company ]]>
    </company>
    <companydescription>
      <![CDATA[ Cupio barba articulus.</p><p>Spes deleniti cubicularis. ]]>
    </companydescription>
    <companyuuid>
      <![CDATA[ ZPXFT2VMtr8 ]]>
    </companyuuid>
    <logotype>
      <![CDATA[ https://teamtailor-production.s3.eu-west-1.amazonaws.com/image_uploads/cd24c21b-db10-4cf2-aabd-4a6f4ef1cf06/original.png ]]>
    </logotype>
    <headquarters>
      <country>
        <![CDATA[ Sweden ]]>
      </country>
      <city>
        <![CDATA[ Stockholm ]]>
      </city>
       <zip>
        <![CDATA[ 118 46 ]]>
      </zip>
      <address>
        <![CDATA[ Sankt Paulsgatan 7B ]]>
      </address>
      <countrycode>
        <![CDATA[ SE ]]>
      </countrycode>
      <region>
        <![CDATA[ Västra Götaland County ]]>
      </region>
    </headquarters>
    <referencenumber>
      <![CDATA[ teamtailor-23 ]]>
    </referencenumber>
    <title>
      <![CDATA[ Marketing Coordinator ]]>
    </title>
    <description>
      <![CDATA[ Depereo decumbo defungo. Ubi stipes vel. Cupio barba articulus. ]]>
    </description>
    <startdate>
      <![CDATA[ 2021-03-24T00:00:00+01:00 ]]>
    </startdate>
    <enddate>
      <![CDATA[ 2021-03-31T00:00:00+02:00 ]]>
    </enddate>
    <createddate>
      <![CDATA[ 2021-03-02T19:18:22+01:00 ]]>
    </createddate>
    <remotestatus>
      <![CDATA[ none ]]>
    </remotestatus>
    <employmenttype>
      <![CDATA[ none ]]>
    </employmenttype>
    <employmentlevel>
      <![CDATA[ none ]]>
    </employmentlevel>
    <url>
      <![CDATA[ https://career.teamtailor.localhost/jobs/23-marketing-coordinator ]]>
    </url>
    <applyurl>
      <![CDATA[ https://career.teamtailor.localhost/jobs/23-marketing-coordinator/applications/new ]]>
    </applyurl>
    <coverimageurl>
      <![CDATA[ https://teamtailor-production.s3.eu-west-1.amazonaws.com/image_uploads/cd24c21b-db10-4cf2-aabd-4a6f4ef1cf06/original.png ]]>
    </coverimageurl>
    <pitch>
      <![CDATA[ Coadunatio centum animi. Succedo adversus inventore. Rem est uberrime. ]]>
    </pitch>
    <applybuttontext>
      <![CDATA[ Become a developer ]]>
    </applybuttontext>
    <locations>
      <location>
        <country>
          <![CDATA[ Finland ]]>
        </country>
        <city>
          <![CDATA[ Helsinki ]]>
        </city>
        <zip>
          <![CDATA[ 00100 ]]>
        </zip>
        <address>
          <![CDATA[ ]]>
        </address>
        <countrycode>
          <![CDATA[ FI ]]>
        </countrycode>
        <region>
          <![CDATA[ Västra Götaland County ]]>
        </region>
      </location>
      <location>
        <country>
          <![CDATA[ Sweden ]]>
        </country>
        <city>
          <![CDATA[ Stockholm ]]>
        </city>
        <postalcode>
          <![CDATA[ 118 46 ]]>
        </postalcode>
        <address>
          <![CDATA[ Sankt Paulsgatan 7B ]]>
        </address>
        <countrycode>
          <![CDATA[ SE ]]>
        </countrycode>
        <region>
          <![CDATA[ Västra Götaland County ]]>
        </region>
      </location>
    </locations>
    <department>
      <name>
        <![CDATA[ Product Development ]]>
      </name>
    </department>
    <role>
      <name>
        <![CDATA[ Developer ]]>
      </name>
    </role>
    <recruiter>
      <name>
        <![CDATA[ Hammes Grud ]]>
      </name>
      <email>
        <![CDATA[ email1@example.com ]]>
      </email>
      <phone>
        <![CDATA[ 123456 ]]>
      </phone>
    </recruiter>
  </job>
</source>

Feed elements

Attribute Value
publisher Name of publisher of the feed
publisherurl Url to feed publisher’s website
lastupdatedat Timestamp of when the feed was last time updated. It’s updated 3 times a days
job Node containg all the job ad data
company Company name
companydescription Description of the company
companyuuid Company’s uuid
logotype URL to the company’s logo
headquarters Headquarters of the company. Implements location element
referencenumber Unique identifier of job ad in Teamtailor
title Job title
description Job description
startdate Date from when the job ad is published
enddate Date when job ad will be unlisted
createddate Date when job ad was created
remotestatus Remote status. One of following: none, temporary, hybrid, fully
employmenttype Employment type. One of following: none, fully, part, contract, temporary, apprenticeship, internship, volunteer
employmentlevel Employment level. One of following: none, senior, mid, professionals, technicians, sales, administrative, support, craft, operatives, laborers, service
url URL to the job ad in Teamtailor
applyurl URL to the apply form in Teamtailor
coverimageurl URL to the job cover image
pitch Pitch text about the job
applybuttontext Text displayed on “apply” button
locations Locations of the job. Implement many location elements
department.name Name of the job’s department
role.name Name of the job’s role
recruiter Recruiter of the job. Implements recruiter object

Location element

Attribute Value
country Country name
city City name
postalcode Postal code
address Address
countrycode Country code
region Region name

Recruiter element

Attribute Value
name Recruiter name
email Recruiter email
phone Recruiter phone

Email with job data

If you choose the Email integration, you will receive an email every time the job ad is created, updated or removed.

Example email

Channel: Channel name
Reference number: teamtailor-23
Duration: 30
Publish date: 2021-03-24T00:00:00+01:00
End date: 2021-03-31T00:00:00+02:00
Remote status: none
Employment type: none
Employment level: none
Job offer url: https://career.teamtailor.localhost/jobs/407c2b91-f06e-475f-9e51-72a62091abce
Job apply url: https://career.teamtailor.localhost/jobs/407c2b91-f06e-475f-9e51-72a62091abce/applications/new?promotion=abc
Cover image url: https://teamtailor-production.s3.eu-west-1.amazonaws.com/image_uploads/cd24c21b-db10-4cf2-aabd-4a6f4ef1cf06/original.png
Price: 400 EUR

Locations:
    - country: Sweden
    - city: Stockholm
    - postalcode: 118 46
    - address: Sankt Paulsgatan 7B
    - region: Västra Götaland County


Recruiter data
--------------
- name: Hammes Grud
- email: email1@example.com
- phone: 123456

Department data:
--------------
- name: Marketing
- role name: Growth Marketing Manager

Company data
------------

Company name: Test company
Company description: Cupio barba articulus.</p><p>Spes deleniti cubicularis.
Company logotype: https://teamtailor-production.s3.eu-west-1.amazonaws.com/image_uploads/cd24c21b-db10-4cf2-aabd-4a6f4ef1cf06/original.png
Company headquarters:
    - country: Sweden
    - city: Stockholm
    - postalcode: 118 46
    - address: Sankt Paulsgatan 7B
    - countrycode: SE
    - region: Västra Götaland County


Promotion data
--------------

Title: Marketing Coordinator
Description: <p>Depereo decumbo defungo. Ubi stipes vel. Cupio barba articulus.</p><p>Spes deleniti cubicularis. Admitto aut contra. Aspernatur sperno cuppedia.</p><p>Vado concedo ager. 
      Usitas coaegresco autem. Suscipio thorax aurum.</p><p>Vero et veniam. Alioqui cometes apto. Truculenter tollo quos.</p><p>Decimus sunt sollers. Cotidie celo voluntarius. 
      Centum triduana deleo.</p><p>Denego quod dedico. Conservo bos illo. Molestiae valetudo avaritia.</p><h2>Recusandae placeat voluptates modi.</h2><p>Verto et absum. Culpa corroboro atrocitas.
      Clam apud voluptatibus.</p><p>Verbum verto sit. Coadunatio centum animi. Succedo adversus inventore.</p><p>Rem est uberrime. Voluptatem theologus inflammatio. Crastinus tergum civitas.</p><p>Deputo summopere eveniet. 
      Vulgus timidus nisi. Defaeco verto natus.</p><p>Quas colligo cresco. Praesentium colo chirographum. Torqueo celebrer concedo.</p><p>Compono statua vaco. Volo adsum veritatis. Aufero bene sursum.</p><p>Viriliter ratione venia. 
      Uter sit quia. Accommodo varietas socius.</p>

Changelog

2023-08-24

Added signatures to job boards requests

2023-08-01

Update direct apply schema

2023-05-24

Added zip to headquarters object in the xml schema, to correctly implements location object

2021-02-10

Added created-at and duration fields to Webhook JSON object.

2022-02-03

Added new multiselect config field type to supported field types.

2022-01-13

Added cover-image-url field to Webhook JSON object, XML feed and Email.

2021-12-28

Added employment-type and employment-level fields to Webhook JSON object, XML feed and Email.

Added Department data, Job apply url and Price to Email.

2021-10-21

Added new fields to Webhook JSON object and XML feed.

2021-10-08

First release of the Job Board API documentation in beta version.

API Resources

Introduction

The resources in our Job Board API is accessible using the JSON API Specification.

Authentication

PUT https://api.teamtailor.com/channel/v1/promotions/1 HTTP/1.1
Authorization: Token abc123abc123

Authenticate your account by including your secret API key in the request. You can find your API key in the Integrations hub inside Teamtailor App.

Authentication is performed by passing the api key in the Authorization header.

Versioning

PUT https://api.teamtailor.com/channel/v1/promotions/1 HTTP/1.1
X-Api-Version : 20180828

When we make backwards-incompatible changes to the API, we release new, dated versions.

To set the API version on a specific request, send a X-Api-Version header. See the API changelog to see current and old versions.

Successful API requests will have the used API version in the response header X-Api-Version

Promotions

Promotion is an object representing a job ad in Teamtailor.

Promotion object

Example promotion object

{
  "data": {
    "id": "1",
    "type": "promotions",
    "links": {
      "self": "https://api.teamtailor.localhost/channel/v1/promotions/1"
    },
    "attributes": {
      "external-url": "http://www.example.com"
    }
  }
}
Attribute Type Description
external-url string URL to the job ad in your system

Update promotion

Example request

PUT https://api.teamtailor.localhost/channel/v1/promotions/1 HTTP/1.1
Authorization: Token abc123abc123
X-Api-Version: 20180828
Content-Type: application/vnd.api+json

{
  "data": {
    "id": "1",
    "type": "promotions",
    "attributes": {
      "external-url": "http://www.example.com"
    }
  }
}

Example response

{
  "data": {
    "id": "1",
    "type": "promotions",
    "links": {
      "self": "https://api.teamtailor.localhost/channel/v1/promotions/1"
    },
    "attributes": {
      "external-url": "http://www.example.com"
    }
  }
}