---
title: "How to Create Candidates and Applications in ATS Systems with"
img: https://s3.us-east-2.amazonaws.com/unified-article-images/how_to_create_candidates_and_applications_in_ats_systems_with-icon.png
date: 2026-02-02T17:20:00.000Z
updated: 2026-10-21T11:22:00.844Z
readingTime: 4
tag: Product
description: "To create candidates and applications in your customers' ATS with Unified.to's ATS API, create the candidate, create an application linking it to a job, attach..."
url: "https://unified.to/blog/how_to_create_candidates_and_applications_in_ats_systems_with"
---

# How to Create Candidates and Applications in ATS Systems with

To create candidates and applications in your customers' ATS with [Unified.to](http://unified.to/)'s [ATS API](/ats), create the candidate, create an application linking it to a job, attach documents, then update the application's status, checking each integration's writable fields first. This guide is for teams writing sourced or referred candidates into an ATS.


Write operations are more complex than reads. Field requirements vary by provider. Writable fields differ across integrations. Some objects are read-only in certain ATSs. There is no global stage-transition model. And Unified.to does not enforce idempotency or duplicate prevention for you.


## What's the write sequence?


Write operations follow this typical flow:

1. **Create a candidate**
2. **Create an application** linking candidate to job
3. (Optional) **Upload documents** (resume, cover letter, etc.)
4. (Optional) **Update application status**
5. Handle errors and retry appropriately

Everything else — deduplication, idempotency, cross-connection identity — belongs in your application layer.


## Step 1: How do you create a candidate?


### Endpoint


```plain text
POST /ats/{connection_id}/candidate
```


SDK:


```typescript
const result = await sdk.ats.createAtsCandidate({
  connectionId,
  atsCandidate: {
    first_name: 'Jane',
    last_name: 'Doe',
    emails: [{ email: 'jane@example.com', type: 'WORK' }],
  },
  fields: '',
  raw: '',
});
```


### Required fields


The **generic ATS create candidate endpoint does not document any required fields** beyond the `connection_id` path parameter.


However, **required fields vary by integration**.


Examples documented:

- **Vincere** requires `emails` and `name` (starred writable fields).
- Other providers (e.g., Greenhouse, Lever) do not mark required candidate fields in documentation.

**In practice:**

You must check the integration's "Writable Fields" section. Starred fields are required for that provider.


If no fields are starred, no required fields are documented.


### Duplicate prevention & idempotency


Unified.to documentation:

- Does **not** document idempotency key support.
- Does **not** document upsert behavior.
- Does **not** document duplicate candidate prevention.
- Does **not** enforce uniqueness of `external_identifier`.

If your system may send the same candidate twice, implement idempotency and dedupe logic in your own application.


## Step 2: How do you create an application?


Applications link candidates to jobs.


### Endpoint


```plain text
POST /ats/{connection_id}/application
```


SDK:


```typescript
const result = await sdk.ats.createAtsApplication({
  connectionId,
  atsApplication: {
    candidate_id: 'candidate123',
    job_id: 'job456',
    status: 'NEW',
  },
  fields: '',
  raw: '',
});
```


## Required fields


The generic documentation does not mark required fields.


However, integration pages show:

- **Vincere**: `candidate_id` and `job_id` are required (starred).
- **Lever**: `candidate_id` and `job_id` are required.
- **Greenhouse**: no required fields marked, but logically `candidate_id` and `job_id` must exist to create a valid application.

**Safe rule:**


Assume `candidate_id` and `job_id` are required unless the integration page explicitly states otherwise.


As of 19 October 2026, Greenhouse, Lever, Workable, Ashby, Bullhorn, iCIMS, SmartRecruiters and Teamtailor create both candidates and applications; Workday (REST) creates candidates only, with no application object.


## Writable fields on create


Writable fields vary by integration.


### Common patterns:


| Field             | Writable? | Notes                                                                                                          |
| ----------------- | --------- | -------------------------------------------------------------------------------------------------------------- |
| `candidate_id`    | Yes       | Usually required                                                                                               |
| `job_id`          | Yes       | Usually required                                                                                               |
| `status`          | Often yes | Writable in many integrations                                                                                  |
| `original_status` | Only some | Writable in some providers (e.g., Greenhouse)                                                                  |
| `applied_at`      | Some      | Writable in some integrations (e.g., Vincere), not others                                                      |
| `offers[]`        | Rarely    | Writable on a few integrations, such as Workday (Legacy) and PCRecruiter; read-only on Greenhouse and Workable |
If a field is not listed under 'Writable Fields' on the integration page, it should be treated as read-only.


## Step 3: How do you upload documents?


### Endpoint


```plain text
POST /ats/{connection_id}/document
```


### Required behavior

- `document_data` must be **base64 encoded** when used.
- Some integrations support only `document_url`.
- Some support both.
- File size and file type limits are **not documented** by Unified.to.
- Attachment target varies by provider.

### Provider-specific attachment behavior


| Provider        | Attach To        | Base64 Support | Notes                                                         |
| --------------- | ---------------- | -------------- | ------------------------------------------------------------- |
| Greenhouse      | application only | No             | Requires `document_url`                                       |
| Lever           | candidate only   | Yes            | Requires `candidate_id`, `filename`                           |
| Workable        | application only | No             | Requires `application_id`, `filename`, `type`, `document_url` |
| SmartRecruiters | candidate or job | No             | URL-based upload                                              |
| CATS            | candidate only   | Yes            | Supports base64                                               |
There are no documented file size or file type restrictions in Unified.to's docs.


## Step 4: How do you update an application?


### Endpoint


```plain text
PUT /ats/{connection_id}/application/{id}
```


SDK:


```typescript
const result = await sdk.ats.updateAtsApplication({
  connectionId,
  id: 'application123',
  atsApplication: {
    status: 'REVIEWING',
  },
  fields: '',
  raw: '',
});
```


## Writable fields on update


Writable fields depend on integration.


### Examples:

- **Vincere**: `candidate_id`, `job_id`, `applied_at`, `status`
- **Greenhouse**: `candidate_id`, `job_id`, `answers`, `metadata`, `status`, `original_status`
- **Lever**: `candidate_id`, `job_id`, `answers`, `status`

`offers[]` is writable on only a few integrations, such as Workday (Legacy) and PCRecruiter.


### Status behavior

- `status` is writable in the reviewed integrations.
- On some integrations, such as Greenhouse, `status` is a [slow field](https://docs.unified.to/reference/slow-fields): it needs an extra vendor call, so reads leave it out unless you request it with `fields`.
- `original_status` is writable only if listed in writable fields.
- No documented stage transition rules exist at the Unified.to level.
- Provider-side constraints may apply but are not documented in Unified.to.

## How do you handle errors and retries?


Unified.to's OpenAPI spec for ATS write endpoints documents only successful `200` responses.


No structured ATS-specific error schema is documented.


### Observations:

- Errors follow standard HTTP status codes.
- `400` for malformed or invalid requests.
- `429` for rate limiting (provider-driven).
- `5XX` for provider outages.
- `501` when the integration doesn't support the operation

The SDK exposes generic error handling objects (e.g., `UnifiedToError`).


### Retry behavior

- Unified.to recommends exponential backoff for [rate limits](https://docs.unified.to/reference/rate_limits).
- Python SDK includes retry/backoff utilities.
- No ATS-specific retry guarantees are documented.

Implement:

- Exponential backoff
- Retry limits
- Logging
- Provider-aware throttling

## What's a safe write architecture?


A safe pattern for writing candidates and applications:

1. Check whether candidate exists in your system.
2. Create candidate in ATS.
3. Create application linking to job.
4. Upload documents if supported.
5. Update status as needed.
6. Implement idempotency in your app layer.
7. Handle retries with exponential backoff.
8. Validate integration-specific writable fields before sending payload.

## Why do ATS writes need more care than reads?


Field support varies. Required fields differ. Status updates differ by ATS. Offers are writable on only a few integrations. Duplicate handling is not enforced. Error contracts are not strongly typed in documentation.


[Unified.to](http://unified.to/)'s ATS API gives each ATS's write capabilities one model. It doesn't hide each ATS's write constraints.


Treat each integration's Writable Fields section as authoritative. From there, writing candidates and applications is predictable across ATS integrations. For the sourcing flow end to end, see [How to Source Candidates Externally](https://unified.to/blog/how_to_source_candidates_externally_and_push_them_into_an_ats_using_unified_ats_api).


→ [Start your 30-day free trial](https://app.unified.to/login)


→ [Book a demo](https://calendly.com/d/cph9-g8n-jzg/connect-with-unified)