Developers

Applications

GET /api/v1/applications returns the applications in your workspace a page at a time, and GET /api/v1/applications/{id} returns one, with every parameter and field.

Overview

GET /api/v1/applications lists the applications in your workspace, and GET /api/v1/applications/{id} returns one of them. You get the applications you can see in the app. A key limited to some teams gets only the applications in those teams, never one someone shared with you from another team. A key with access to every team also gets the applications shared with you.

Both need the Read candidate data permission, which the API names candidates:read. A key can hold it only while a workspace admin has Candidate data in the API turned on in Settings → API. Turning it off takes the permission from every key, and the next call answers 403 with the code insufficient-scope. The Read permission alone gets the same 403.

An application names its candidate by id and nothing else. No name, email, phone number, note, file or score comes back.

Authentication, Errors and Rate limits cover what every operation shares. This page covers the parameters and the fields.

Request

curl "https://attia.app/api/v1/applications?job_id=0192f3a1-6b02-7d4c-8e11-5a9c0b7d3e01" \  -H "Authorization: Bearer $ATTIA_API_KEY"

All six query parameters are optional.

ParameterTypeDefaultMeaning
limitinteger, 1 to 10025How many applications to return
cursorstringnoneThe next_cursor of the previous page
updated_sinceRFC 3339 timestampnoneOnly applications updated at or after this time
include_archivedtrue or falsefalseAlso return archived applications
job_idUUIDnoneOnly applications to this job
current_status_idUUIDnoneOnly applications in this status

A parameter outside this table gets a 400 with the code invalid-request. So does a parameter sent twice, and a job_id or current_status_id that is not a UUID.

Response

The answer holds the applications in data, sorted by updated_at and then id, oldest change first. next_cursor is a string when more applications exist and null on the last page.

{  "data": [    {      "id": "0192f4b7-2c10-7a3e-9d21-6e0f1a2b3c01",      "team_id": "0192f39f-11aa-7c3e-b2d4-9e8f7a6b5c4d",      "job_id": "0192f3a1-6b02-7d4c-8e11-5a9c0b7d3e01",      "workspace_candidate_id": "0192f4b6-8e44-7f10-a3c2-1d2e3f4a5b01",      "current_status_id": "0192f3a0-55c1-7b2d-8f90-0a1b2c3d4e05",      "board_category": "active",      "source_type": "career_page",      "source_label": null,      "source_url": null,      "applied_at": "2026-10-02T08:15:30.482913Z",      "withdrawn_at": null,      "archived_at": null,      "assigned_to_workspace_member_id": "0192f39e-0b7a-7c11-9e3f-2a4b6c8d0e12",      "public_revision": 3,      "updated_at": "2026-10-03T11:20:04.007311Z"    }  ],  "next_cursor": null}
FieldTypeMeaning
idUUIDThe application's id. It never changes
team_idUUIDThe team the application sits in
job_idUUIDThe job applied to. GET /api/v1/jobs/{id} returns it
workspace_candidate_idUUIDThe candidate. A person with three applications has the same id on all three
current_status_idUUIDThe application's status. Each team has its own statuses
board_categoryenumbacklog, new, active, completed or closed. The status category, which follows from the status
source_typeenumcareer_page, linkedin, referral, manual, job_board, outreach, imported or other
source_labelstring or nullThe source's name, when one was recorded
source_urlstring or nullThe source's address, when one was recorded
applied_attimestamp or nullWhen the candidate applied
withdrawn_attimestamp or nullWhen the candidate withdrew
archived_attimestamp or nullWhen the application was archived
assigned_to_workspace_member_idUUID or nullThe workspace member assigned to the application
public_revisionintegerGoes up by one on each change to a field above, and on some changes the API does not show. Order changes to one application by it
updated_attimestampWhen the application last changed

updated_at and public_revision can both move when nothing above changed. updated_at moves on every change to the application. public_revision moves when a field above changes, or one of a few fields the API does not return, such as the review score.

An enum can gain a value in version 1, so handle one you do not know. Timestamps, nulls and enums describes each format.

Page and poll

Paging and polling work as they do for jobs. Send next_cursor back as cursor until it is null, and poll with updated_since set five minutes before the largest updated_at you have stored. Jobs walks through both, and Pagination explains the sort order. The filters stay the same on every page, so send job_id and current_status_id again with each cursor.

The list leaves archived applications out unless you send include_archived=true. When you keep a copy, poll with it, or an application someone archives drops out of your answers and your copy never learns why.

Get one application

GET /api/v1/applications/{id} returns the application with that id. It takes no query parameters, so one gets a 400 with the code invalid-request.

curl "https://attia.app/api/v1/applications/0192f4b7-2c10-7a3e-9d21-6e0f1a2b3c01" \  -H "Authorization: Bearer $ATTIA_API_KEY"

The answer holds the application in data, with the same fields as an application in the list. An archived application comes back too, with a time in archived_at.

A 404 with the code not-found means no application your key can see has that id. It may not exist, or be deleted, or belong to another workspace. It may sit in a team the list leaves out for you, or its candidate may have been erased or hidden from the workspace. Every one of these gets the same answer, so a 404 never tells you whether the application exists. An id that is not a UUID gets the same 404.