---
name: unified-ats-jobboard
description: >-
  Build candidate-sourcing, recruiting, and job-board features against many
  Applicant Tracking Systems (Greenhouse, Lever, Workable, Ashby, Bullhorn, and
  more) through the single Unified.to ATS API. Use when a coding task involves
  reading jobs, creating or updating candidates and applications, tracking
  application status, or attaching documents across one or more ATS platforms.
license: MIT
metadata:
  category: ats
  api_base: https://api.unified.to
  docs: https://docs.unified.to/ats/overview
---

# Build a candidate sourcing or job board app with the Unified.to ATS API

Unified.to normalizes many Applicant Tracking Systems behind one REST API. Build
your recruiting/job-board integration once and it works across every supported
ATS. This skill teaches an agent how to build against the Unified ATS API.

## When to use this skill

Use this skill when the task is to:

- Display open jobs on a careers page or job board
- Source candidates and push them into a customer's ATS
- Create applications and track application status
- Upload resumes/documents or read interview and scorecard data
- Support more than one ATS without platform-specific code

## Prerequisites

1. A Unified.to workspace with an **API key** and **Workspace ID**.
2. An activated ATS integration (e.g. Greenhouse) — start in the Sandbox.
3. A **connection ID** from the embedded Authorization component
   (https://docs.unified.to/concepts/embedded-components).

Keep the API key server-side only.

## Core request pattern

```
https://api.unified.to/ats/{connection_id}/{object}
```

Authenticate every request:

```
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
```

Regional base URLs: `api.unified.to` (NA), `api-eu.unified.to` (EU),
`api-au.unified.to` (AU).

## Data objects

| Object              | Purpose                                          |
| ------------------- | ------------------------------------------------ |
| `job`               | An open position / job posting                   |
| `candidate`         | A candidate / applicant                          |
| `application`       | A candidate's application to a job               |
| `applicationstatus` | The set of application statuses (read-only)      |
| `interview`         | An interview                                     |
| `scorecard`         | Interview feedback / scorecard                   |
| `activity`          | An activity/note on a candidate                  |
| `document`          | A document (e.g. resume) attached to a candidate |
| `company`           | A company/organization                           |

### Supported operations (candidate shown; others follow the same shape)

| Method   | Path                             | Description            |
| -------- | -------------------------------- | ---------------------- |
| `GET`    | `/ats/{cid}/candidate`           | List candidates        |
| `GET`    | `/ats/{cid}/candidate/{id}`      | Get one candidate      |
| `POST`   | `/ats/{cid}/candidate`           | Create a candidate     |
| `PATCH`  | `/ats/{cid}/candidate/{id}`      | Update a candidate     |
| `DELETE` | `/ats/{cid}/candidate/{id}`      | Delete a candidate     |

The same verbs apply to `job`, `application`, `interview`, `scorecard`,
`activity`, `document`, and `company`. `applicationstatus` is read-only.

Not every ATS supports every object or field. Check the **Feature Support** tab
in `app.unified.to`; a `501` response means the operation is unsupported.

## Pagination, filtering & sorting

- `limit` (max 100) and `offset` (zero-based).
- `updated_gte=YYYY-MM-DDTHH:MM:SSZ` for incremental sync.
- `query=` filters by name or email (integration-specific).
- `sort` (`created_at`, `updated_at`, `name`) + `order` (`asc` / `desc`).

## Example: list jobs and submit a candidate (fetch)

```javascript
const BASE = 'https://api.unified.to';
const headers = {
    Authorization: `Bearer ${process.env.UNIFIED_API_KEY}`,
    'Content-Type': 'application/json',
};

// List open jobs for a job board
const jobsRes = await fetch(
    `${BASE}/ats/${connectionId}/job?limit=50&sort=created_at&order=desc`,
    { headers }
);
const jobs = await jobsRes.json();

// Create a candidate, then an application to a job
const candRes = await fetch(`${BASE}/ats/${connectionId}/candidate`, {
    method: 'POST',
    headers,
    body: JSON.stringify({
        name: 'Ada Lovelace',
        emails: [{ email: 'ada@example.com' }],
    }),
});
const candidate = await candRes.json();

await fetch(`${BASE}/ats/${connectionId}/application`, {
    method: 'POST',
    headers,
    body: JSON.stringify({
        candidate_id: candidate.id,
        job_id: 'JOB_ID',
    }),
});
```

## Example: with the official SDK

```bash
npm install @unified-api/typescript-sdk
```

```typescript
import { UnifiedTo } from '@unified-api/typescript-sdk';

const unified = new UnifiedTo({ security: { jwt: process.env.UNIFIED_API_KEY! } });

const { atsJobs } = await unified.ats.listAtsJobs({ connectionId, limit: 50 });
```

SDKs for Python, PHP, Java, Go, C#, and Ruby: https://docs.unified.to/reference/sdks.

## Keeping data in sync (recommended)

- Register **webhooks** for `job`, `candidate`, and `application` events so your
  job board and pipeline stay current without polling.
  See https://docs.unified.to/reference/webhooks.
- Upsert by `id` on each event.

## Error handling

| Code | Meaning & action                                            |
| ---- | ----------------------------------------------------------- |
| 401  | Connection broken — re-authorize the end-user.              |
| 403  | Missing scopes — fix provider app + Unified.to scopes.      |
| 429  | Provider rate limit — back off; prefer webhook sync.        |
| 501  | Operation unsupported by ATS — check Feature Support.       |

## References

- ATS API overview & data model: https://docs.unified.to/ats/overview
- REST basics: https://docs.unified.to/reference/rest
- Pagination & filtering: https://docs.unified.to/reference/pagination
- Source guide: https://docs.unified.to/guides/how_to_build_a_candidate_sourcing_or_job_board_app_with_unified
