> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kombo.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Storing application forms

> Pull job postings together with their application forms and keep your own copy up to date.

## Overview

[GET Job Postings Forms](/ai-apply/v1/get-postings-forms) returns all job postings, each with its application form and submission token.

Once you have a candidate's answers, include the submission token in the application request so we know which job posting the application is for.

This flow relies on you to keep your database in sync by polling this endpoint regularly. Whenever our parsing updates a job posting or its form, you need to fetch again to pick up the change.

<Tip>
  Use this flow if you need to store the application form in your product (e.g.
  if you are a service distributing the form to other job boards). If you are a
  job board yourself, use our [inquiry flow](/ai-apply/job-boards/posting-inquiry) for a
  better candidate experience.

  **We generally do not recommend this flow unless you have a hard requirement
  to cache the data**. Job postings change over time. With the
  [inquiry flow](/ai-apply/job-boards/posting-inquiry), you always get the newest version
  of the application form. Owning the sync yourself can quickly become a complex
  infrastructure-heavy operation.
</Tip>

## How it works

```mermaid theme={null}
sequenceDiagram
    participant You
    participant Kombo
    You->>Kombo: GET postings/forms (updated_after)
    Kombo-->>You: Postings with forms and multi-use tokens
    You->>You: Show a stored form, collect answers
    You->>Kombo: POST apply (stored token + answers)
    Kombo-->>You: Application id, status PENDING
    Kombo->>You: Application status updated webhook
```

## Fetching the forms

Each response carries a page of postings and a `next` cursor. Page until `next` is `null`.

```json theme={null}
{
  "results": [
    {
      "id": "9QGNv3B98kL3hyELE1qsZ86s",
      "career_site": { "id": "Chc4dua5asAQ48KUERDVF1bs", "label": "Acme" },
      "url": "https://careers.acme.com/jobs/fullstack-engineer-14102",
      "job_code": "ACME_13",
      "availability": "APPLYABLE",
      "archived_at": null,
      "archived_reason": null,
      "created_at": "2025-01-01T00:00:00.000Z",
      "updated_at": "2025-03-02T23:12:32.000Z",
      "application_form": [],
      "submission_token": "<token>"
    }
  ],
  "next": null
}
```

<Note>
  Pages hold at most five postings, because every applyable one on the page
  carries a full application form. An initial sync of a large catalogue
  therefore takes many requests. Later syncs are small, as long as you filter
  them.
</Note>

The endpoint accepts the following query parameter filters: `career_site_ids` and `job_codes` to narrow the catalogue, and `updated_after` to fetch only what changed.

[Data fetching](/ai-apply/job-distributors/webhooks#data-changed-webhook) describes how to keep your copy current with `updated_after` and the data-changed webhook.

### Posting availability

Job posting results include applyable and non-applyable postings. Only jobs with the `APPLYABLE` availability include the `application_form` and `submission_token`. In every other state, both properties are `null`. The `availability` property tells you why:

| Availability  | What it means                                   |
| ------------- | ----------------------------------------------- |
| `APPLYABLE`   | The form and token are present. You can submit. |
| `PENDING`     | We are still parsing the posting.               |
| `UNAVAILABLE` | Parsing failed.                                 |
| `ARCHIVED`    | The job is gone. Stop displaying it.            |

Clear the form you are storing when a posting stops being `APPLYABLE`, rather than keeping it around in case the job comes back. If it does, the next sync hands you a fresh one.

## Submission token mechanics

Every applyable posting includes a unique `submission_token`. Unlike the short-lived single-use tokens from an [inquiry](/ai-apply/job-boards/posting-inquiry), these are meant to be stored:

* **They do not expire.** A token stays valid for as long as the form it came with is current.
* **They are reusable.** Every accepted submission creates its own application, so one token serves every candidate who applies to that job.
* **They belong to one form.** Store the token and the form together and replace them together. A token paired with the wrong form is rejected.

<Warning>
  Do not hold a token longer than the form it arrived with. When a sync returns
  a posting with a new form, the pair you stored is out of date, and an
  application submitted with it could fail against the live job site.
</Warning>

## Submitting the application

When a candidate has answered a stored form, submit the answers with the token you stored alongside it. See [Submitting applications](/ai-apply/job-distributors/submitting-applications) for preparing the answers, the request, and tracking the result.

## API reference

* [GET Job Postings Forms](/ai-apply/v1/get-postings-forms)
