# Edun API | Build your own tools on Edun

URL: https://edun.ai/developers/

Use the Edun API to read candidate, client, vacancy and booking data with OAuth 2.0 and build your own tools on Edun. Request API access.

For developers

## Build on Edun

Use the Edun API to connect your own tools to the candidate, client, vacancy and booking information held in Edun. Access is by request.

[Request API access](mailto:support@helloedun.co.uk?subject=Edun%20API%20access%20request)

The Edun API

### Use Edun as the backend for your own tools

Integrate with Edun recruitment, compliance, booking and business operations. The Edun API uses OAuth 2.0 and OpenID Connect, so your own website, dashboard, reporting or internal system can work with the records your team keeps in Edun.

Access is by request, and we are introducing endpoints in stages. If you have a specific integration or workflow you would like us to support, contact Edun Support so we can prioritise it accordingly.

### Build with your Edun data

#### Candidates

Records and search.

#### Clients

Schools, trusts and contacts.

#### Vacancies

Roles and their booked status.

#### Bookings

Who is working where, and when.

#### Messages

Calls and emails.

#### Company set-up

Users, branches, tags and saved searches.

### Example uses

Short examples of the kind of tools you can build. Each one makes a single request with the documented select, filter, sort and search parameters, and assumes you already have an access token for your API client.

#### Search candidates in plain language

Add a search box to your own tool. The q parameter finds relevant candidates from their details and attached documents, and select returns only the fields you ask for.

Request (cURL):

```
curl -g \
  "https://edun.app/api/v2/candidates?q=maths%20teacher%20Leeds&select=id,forename,surname,occupation,address.city&pageSize=10" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

Request (JavaScript):

```
const response = await fetch(
  'https://edun.app/api/v2/candidates?q=maths%20teacher%20Leeds&select=id,forename,surname,occupation,address.city&pageSize=10',
  { headers: { Authorization: `Bearer ${accessToken}` } },
);
const { data } = await response.json();
```

Request (Python):

```
import requests

response = requests.get(
    'https://edun.app/api/v2/candidates',
    params={
        'q': 'maths teacher Leeds',
        'select': 'id,forename,surname,occupation,address.city',
        'pageSize': 10,
    },
    headers={'Authorization': f'Bearer {access_token}'},
)
data = response.json()['data']
```

Request (PHP):

```
$url = 'https://edun.app/api/v2/candidates?' . http_build_query([
    'q' => 'maths teacher Leeds',
    'select' => 'id,forename,surname,occupation,address.city',
    'pageSize' => 10,
]);

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ["Authorization: Bearer $accessToken"],
]);
$data = json_decode(curl_exec($ch), true)['data'];
```

Request (Ruby):

```
require 'net/http'
require 'json'

uri = URI('https://edun.app/api/v2/candidates')
uri.query = URI.encode_www_form(
  'q' => 'maths teacher Leeds',
  'select' => 'id,forename,surname,occupation,address.city',
  'pageSize' => '10',
)
request = Net::HTTP::Get.new(uri, 'Authorization' => "Bearer #{access_token}")
response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(request) }
data = JSON.parse(response.body)['data']
```

Request (C#):

```
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", accessToken);

var json = await client.GetStringAsync(
    "https://edun.app/api/v2/candidates?q=maths%20teacher%20Leeds&select=id,forename,surname,occupation,address.city&pageSize=10");
```

#### Show current bookings on your own dashboard

Pull active bookings into a wallboard or report. Sort by start date and filter on role to keep the response small.

Request (cURL):

```
curl -g \
  "https://edun.app/api/v2/bookings?select=id,candidateName,clientName,role,status&filter[role]=Maths&sort=start&pageSize=20" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

Request (JavaScript):

```
const response = await fetch(
  'https://edun.app/api/v2/bookings?select=id,candidateName,clientName,role,status&filter[role]=Maths&sort=start&pageSize=20',
  { headers: { Authorization: `Bearer ${accessToken}` } },
);
const { data } = await response.json();
```

Request (Python):

```
import requests

response = requests.get(
    'https://edun.app/api/v2/bookings',
    params={
        'select': 'id,candidateName,clientName,role,status',
        'filter[role]': 'Maths',
        'sort': 'start',
        'pageSize': 20,
    },
    headers={'Authorization': f'Bearer {access_token}'},
)
data = response.json()['data']
```

Request (PHP):

```
$url = 'https://edun.app/api/v2/bookings?' . http_build_query([
    'select' => 'id,candidateName,clientName,role,status',
    'filter[role]' => 'Maths',
    'sort' => 'start',
    'pageSize' => 20,
]);

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ["Authorization: Bearer $accessToken"],
]);
$data = json_decode(curl_exec($ch), true)['data'];
```

Request (Ruby):

```
require 'net/http'
require 'json'

uri = URI('https://edun.app/api/v2/bookings')
uri.query = URI.encode_www_form(
  'select' => 'id,candidateName,clientName,role,status',
  'filter[role]' => 'Maths',
  'sort' => 'start',
  'pageSize' => '20',
)
request = Net::HTTP::Get.new(uri, 'Authorization' => "Bearer #{access_token}")
response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(request) }
data = JSON.parse(response.body)['data']
```

Request (C#):

```
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", accessToken);

var json = await client.GetStringAsync(
    "https://edun.app/api/v2/bookings?select=id,candidateName,clientName,role,status&filter[role]=Maths&sort=start&pageSize=20");
```

#### Publish unfilled vacancies on your website

List vacancies that have not been booked, newest first, and include the client name for each.

Request (cURL):

```
curl -g \
  "https://edun.app/api/v2/vacancies?select=id,client.name&filter[booked]=false&sort=-createdAt&pageSize=25" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

Request (JavaScript):

```
const response = await fetch(
  'https://edun.app/api/v2/vacancies?select=id,client.name&filter[booked]=false&sort=-createdAt&pageSize=25',
  { headers: { Authorization: `Bearer ${accessToken}` } },
);
const { data } = await response.json();
```

Request (Python):

```
import requests

response = requests.get(
    'https://edun.app/api/v2/vacancies',
    params={
        'select': 'id,client.name',
        'filter[booked]': 'false',
        'sort': '-createdAt',
        'pageSize': 25,
    },
    headers={'Authorization': f'Bearer {access_token}'},
)
data = response.json()['data']
```

Request (PHP):

```
$url = 'https://edun.app/api/v2/vacancies?' . http_build_query([
    'select' => 'id,client.name',
    'filter[booked]' => 'false',
    'sort' => '-createdAt',
    'pageSize' => 25,
]);

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ["Authorization: Bearer $accessToken"],
]);
$data = json_decode(curl_exec($ch), true)['data'];
```

Request (Ruby):

```
require 'net/http'
require 'json'

uri = URI('https://edun.app/api/v2/vacancies')
uri.query = URI.encode_www_form(
  'select' => 'id,client.name',
  'filter[booked]' => 'false',
  'sort' => '-createdAt',
  'pageSize' => '25',
)
request = Net::HTTP::Get.new(uri, 'Authorization' => "Bearer #{access_token}")
response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(request) }
data = JSON.parse(response.body)['data']
```

Request (C#):

```
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", accessToken);

var json = await client.GetStringAsync(
    "https://edun.app/api/v2/vacancies?select=id,client.name&filter[booked]=false&sort=-createdAt&pageSize=25");
```

#### Keep a trust’s schools in step with another system

Filter clients by Multi-Academy Trust (MAT) and read their names and postcodes to update a finance or CRM tool.

Request (cURL):

```
curl -g \
  "https://edun.app/api/v2/clients?select=id,name,address.postcode&filter[multiAcademyTrust]=Example%20Trust&pageSize=50" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

Request (JavaScript):

```
const response = await fetch(
  'https://edun.app/api/v2/clients?select=id,name,address.postcode&filter[multiAcademyTrust]=Example%20Trust&pageSize=50',
  { headers: { Authorization: `Bearer ${accessToken}` } },
);
const { data } = await response.json();
```

Request (Python):

```
import requests

response = requests.get(
    'https://edun.app/api/v2/clients',
    params={
        'select': 'id,name,address.postcode',
        'filter[multiAcademyTrust]': 'Example Trust',
        'pageSize': 50,
    },
    headers={'Authorization': f'Bearer {access_token}'},
)
data = response.json()['data']
```

Request (PHP):

```
$url = 'https://edun.app/api/v2/clients?' . http_build_query([
    'select' => 'id,name,address.postcode',
    'filter[multiAcademyTrust]' => 'Example Trust',
    'pageSize' => 50,
]);

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ["Authorization: Bearer $accessToken"],
]);
$data = json_decode(curl_exec($ch), true)['data'];
```

Request (Ruby):

```
require 'net/http'
require 'json'

uri = URI('https://edun.app/api/v2/clients')
uri.query = URI.encode_www_form(
  'select' => 'id,name,address.postcode',
  'filter[multiAcademyTrust]' => 'Example Trust',
  'pageSize' => '50',
)
request = Net::HTTP::Get.new(uri, 'Authorization' => "Bearer #{access_token}")
response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(request) }
data = JSON.parse(response.body)['data']
```

Request (C#):

```
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", accessToken);

var json = await client.GetStringAsync(
    "https://edun.app/api/v2/clients?select=id,name,address.postcode&filter[multiAcademyTrust]=Example%20Trust&pageSize=50");
```

#### What comes back

Collections return a data array with total, page and pageSize, so you can page through large results.

JSON:

```
{
  "data": [ ... ],
  "total": 0,
  "page": 1,
  "pageSize": 10
}
```

Default response fields can change, so always use select to ask for exactly the fields you need.

### How access works

- Request access. Email support@helloedun.co.uk to request API access.
- Create an API client. A user with permission to manage API clients adds one in Company, then Developers. Set your exact redirect URLs and store the client secret safely. It is shown only when issued or rotated.
- Sign in with OAuth 2.0. Use the Authorization Code flow with PKCE. The OpenID Connect discovery document lists the endpoints.
- Call the API. Send the access token as a Bearer token. Each endpoint lists the scope it needs, and the user’s role, teams and branch access still apply.
[Request API access](mailto:support@helloedun.co.uk?subject=Edun%20API%20access%20request)

### Frequently asked questions

**What is the Edun API?**

It is a REST API that lets approved applications read information held in Edun, such as candidates, clients, vacancies and bookings, using OAuth 2.0 and OpenID Connect.

**How do I get access?**

Access is by request. Email support@helloedun.co.uk to ask for it. We are introducing endpoints in stages, so if you have a specific integration or workflow you would like us to support, let Edun Support know and we can prioritise it accordingly.

**Which authentication does it use?**

OAuth 2.0 with the Authorization Code flow and PKCE. Each API client belongs to the company that created it, and only that company’s users can sign in through it.

**Does the API bypass Edun permissions?**

No. Scopes give an application access to an area of the API, but results still follow the signed-in user’s role, team assignments and branch access. A valid token can still receive a 403 response.

**Can one API client work across several companies?**

API clients created by a company only let that company’s users sign in. If you need a global client for your integration, contact Edun support.

**Will the fields in a response change?**

Default response fields are not guaranteed to stay the same. Use the select parameter to request exactly the fields your tool needs.

