Skip to main content

Overview

AI Apply enables you to turn job posting URLs into an API surface for creating applications. Our parser converts any application form into a standardized format that can be programmatically rendered and displayed to candidates. Fields are parsed with all necessary metadata required to render a fully fledged application form. Fields are categorized to enable auto-matching of common fields.
Existing Kombo customer?The Unified API variant of AI Apply works with your current integration, with almost no code changes needed.Reach out to us if you have any questions regarding which API to use.

Flows

Creating a Career Site

The career site entity is a collection of job postings. Create a new career site for each customer that you want to send applications to. Creating a career site can be done via the POST Career Sites endpoint, or in the dashboard.

Parsing a Job Posting

Job posting parsing is asynchronous:
  1. Submit job URL: POST Job Postings endpoint (or via dashboard)
  2. Wait for processing: Default concurrency limit of 5 jobs (reach out if you need higher limits)
  3. Receive webhook: Get notified when parsing completes, or poll via GET Job Postings
Learn about AI Apply webhooks:View our dedicated AI Apply Webhooks page for more information on which webhooks are emitted and how to handle them.
During the alpha, always reach out if a job posting fails to parse successfully. We’ll make sure to fix it as soon as possible.

Adding Query Parameters

Query parameters in the job posting URL affect how the application form is generated and should be handled strategically: Best Practice: Include as many query parameters as possible in the original URL during parsing to maintain form consistency. In rare cases query parameters can affect which fields appear in the application form, so keeping them consistent ensures a stable experience for candidates. For example, ?source=linkedin&utm_campaign=q1 in the parsing URL will:
  • Be preserved throughout the application flow
  • Potentially affect form field visibility or requirements
  • Be combined with any additional parameters added during application submission
In addition, you can add application-specific query parameters (like user tracking IDs) during the /apply call. These will be merged with the original URL parameters.

Sending Applications

Application submission is asynchronous:
  1. Get form & token: POST Inquiries returns the live application form and a one-time submission token. The submission token can be used for one application, and is valid for 12 hours
  2. Submit application: POST Apply with candidate answers (consumes the token if successful)
  3. Receive webhook

QA Mode

Applications that fail during the submission process will not immediately emit a failure webhook.Kombo will QA any failed application and ensure the error does not stem from the submission process. If it does, Kombo will manually submit the application and a success webhook will be emitted.Only after manual QA and confirmation that Kombo has no way of submitting the application, will a failure webhook be emitted.During the alpha phase, you can expect the turnaround time of application QA to be less than 24 hours.

Query Parameters in Applications

When submitting applications via the POST Apply endpoint, you can include additional query parameters using the query_params field. These should be application-specific parameters only (such as user IDs or tracking identifiers). Example use cases for application-time query parameters:
  • User tracking IDs (user_id)
  • Session identifiers
  • A/B test variants
  • Application source attribution (if not already in parsing URL)

Candidate answers

Answers sent with the POST Apply endpoint are expected in the following format:
{
  "submission_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "candidate_email": "john.doe@gmail.com",
  "query_params": {
    "user_id": "8e05b4e5-c586-4d42-8606-b45febad3af3"
  },
  "screening_question_answers": [
    {
      "question_id": "A4zHtGQLF823sNmqy4WxoduFH",
      "answer": "John Doe"
    },
    {
      "question_id": "CDEfHvMGSDnM6pq5HECdE2Kg",
      "answer": "EycufwZHfwcVDmE47X7QN8X2"
    },
    {
      "question_id": "3dT5df2PhyVp7Rze76S5NqrW",
      "answer": {
        "name": "john_doe_resume.pdf",
        "content_type": "application/pdf",
        "data": "JVBERi0xLjQKJeLjz9MKMSAwIG9iago8PAovVHlwZSAvQ2F0YWxvZwovT3V0bGluZXMgMiAwIFIKL1BhZ2VzIDMgMCBSCj4+CmVuZG9iag=="
      }
    }
  ]
}
View the below table for an in-depth explanation of each expected input type:
Question typetypeExample
TEXTstring”John Doe”
SINGLE_SELECTstring”BsnL4pAhNQc26uSc4JopTP3P” (Selected option ID)
MULTI_SELECTstring[][“7VMWn39TqeHRT3nW12AXMD9V”, “3Mctc15bypfL44i4KgcVrp6s”] (Selected option IDs)
DATEstring”2021-12-31T23:59:59.000Z” (ISO 8601 date)
NUMBERnumber42
BOOLEANbooleantrue
FILEobject{ "name": "john_doe_resume.pdf", "content_type": "application/pdf", "data": "BASE64..." }

The Application Form

The form uses a block structure with two types:
  • Question Blocks: Individual fields with ID, label, type (TEXT, SINGLE_SELECT, MULTI_SELECT, DATE, NUMBER, BOOLEAN, FILE), and optional conditional display
  • Section Blocks: Containers grouping related questions with a children array

Application Form Example

[
  {
    "block_type": "SECTION",
    "label": "Personal Information",
    "children": [
      {
        "block_type": "QUESTION",
        "question_id": "6VrjehyBk685vubNydiR1hSn",
        "label": "First name",
        "description": null,
        "required": true,
        "question_type": "TEXT",
        "unified_key": "FIRST_NAME",
        "options": null,
        "display_when": null
      }
    ]
  },
  {
    "block_type": "QUESTION",
    "question_id": "EKaumKPGjeA97cb8ystMmkCe",
    "label": "What is your desired working location?",
    "description": "Select your preferred work arrangement",
    "required": true,
    "question_type": "SINGLE_SELECT",
    "unified_key": null,
    "options": [
      {
        "id": "BsnL4pAhNQc26uSc4JopTP3P",
        "label": "Remote",
        "unified_key": null
      },
      {
        "id": "8T4fcKgzLxbKFUo4saXaoMTG",
        "label": "On-site",
        "unified_key": null
      },
      {
        "id": "2cJDK3dq4WNjovohSG7dSpfd",
        "label": "Hybrid",
        "unified_key": null
      }
    ],
    "display_when": null
  },
  {
    "block_type": "QUESTION",
    "question_id": "2H26BKTbDn2ygN2GfEcCsUP8",
    "label": "What timezone are you in?",
    "description": "This helps us schedule meetings at convenient times",
    "required": true,
    "question_type": "TEXT",
    "unified_key": null,
    "options": null,
    // This question will only be displayed if the candidate selected "Remote" in the previous question
    "display_when": {
      "question_id": "EKaumKPGjeA97cb8ystMmkCe",
      "answer_equals": "BsnL4pAhNQc26uSc4JopTP3P"
    }
  }
]

Unified Keys

Standardized identifiers for common fields enable automatic data pre-population:
Fields required for creating and managing user accounts, including login credentials and contact information for account access
KeyLabelExpected Type
EMAILEmailTEXT
Fields related to where the candidate currently lives, including full addresses, individual address components, and residence type information
KeyLabelExpected TypeOptions
RESIDENCE_TYPEResidence TypeENUMHOME, WORK, MAILING
RESIDENCE_FULL_STRINGFull ResidenceTEXT
RESIDENCE_COUNTRYCountryENUMAD, AE, AF, AG, AI, AL, AM, AO, AQ, AR, AS, AT, AU, AW, AX, AZ, BA, BB, BD, BE, BF, BG, BH, BI, BJ, BL, BM, BN, BO, BQ, BR, BS, BT, BV, BW, BY, BZ, CA, CC, CD, CF, CG, CH, CI, CK, CL, CM, CN, CO, CR, CU, CV, CW, CX, CY, CZ, DE, DJ, DK, DM, DO, DZ, EC, EE, EG, EH, ER, ES, ET, FI, FJ, FK, FM, FO, FR, GA, GB, GD, GE, GF, GG, GH, GI, GL, GM, GN, GP, GQ, GR, GS, GT, GU, GW, GY, HK, HM, HN, HR, HT, HU, ID, IE, IL, IM, IN, IO, IQ, IR, IS, IT, JE, JM, JO, JP, KE, KG, KH, KI, KM, KN, KP, KR, KW, KY, KZ, LA, LB, LC, LI, LK, LR, LS, LT, LU, LV, LY, MA, MC, MD, ME, MF, MG, MH, MK, ML, MM, MN, MO, MP, MQ, MR, MS, MT, MU, MV, MW, MX, MY, MZ, NA, NC, NE, NF, NG, NI, NL, NO, NP, NR, NU, NZ, OM, PA, PE, PF, PG, PH, PK, PL, PM, PN, PR, PS, PT, PW, PY, QA, RE, RO, RS, RU, RW, SA, SB, SC, SD, SE, SG, SH, SI, SJ, SK, SL, SM, SN, SO, SR, SS, ST, SV, SX, SY, SZ, TC, TD, TF, TG, TH, TJ, TK, TL, TM, TN, TO, TR, TT, TV, TW, TZ, UA, UG, UM, US, UY, UZ, VA, VC, VE, VG, VI, VN, VU, WF, WS, YE, YT, ZA, ZM, ZW
RESIDENCE_CITYCityTEXT
RESIDENCE_STATEState/Province/RegionTEXT
RESIDENCE_LINE_1Residence Line 1TEXT
RESIDENCE_LINE_2Residence Line 2TEXT
RESIDENCE_ZIP_CODEPostal CodeTEXT
Fields containing basic personal details about the candidate, including names, gender, availability, and personal documents like resumes
KeyLabelExpected TypeOptions
FIRST_NAMEFirst NameTEXT
LAST_NAMELast NameTEXT
FULL_NAMEFull NameTEXT
GENDERGenderENUMMALE, FEMALE, NON_BINARY, NOT_SPECIFIED
EXPECTED_START_DATEExpected Start DateDATE
RESUMEResumeFILE
BIRTH_DATEBirth DateDATE
Fields related to phone numbers and telephonic contact information, including phone types, country codes, national numbers, and extensions
KeyLabelExpected TypeOptions
PHONE_NUMBER_TYPEPhone Number TypeENUMMOBILE, LANDLINE, WORK, HOME
FULL_PHONE_NUMBERFull Phone NumberTEXT
PHONE_COUNTRY_CODEPhone Country CodeENUMAD, AE, AF, AG, AI, AL, AM, AO, AQ, AR, AS, AT, AU, AW, AX, AZ, BA, BB, BD, BE, BF, BG, BH, BI, BJ, BL, BM, BN, BO, BQ, BR, BS, BT, BV, BW, BY, BZ, CA, CC, CD, CF, CG, CH, CI, CK, CL, CM, CN, CO, CR, CU, CV, CW, CX, CY, CZ, DE, DJ, DK, DM, DO, DZ, EC, EE, EG, EH, ER, ES, ET, FI, FJ, FK, FM, FO, FR, GA, GB, GD, GE, GF, GG, GH, GI, GL, GM, GN, GP, GQ, GR, GS, GT, GU, GW, GY, HK, HM, HN, HR, HT, HU, ID, IE, IL, IM, IN, IO, IQ, IR, IS, IT, JE, JM, JO, JP, KE, KG, KH, KI, KM, KN, KP, KR, KW, KY, KZ, LA, LB, LC, LI, LK, LR, LS, LT, LU, LV, LY, MA, MC, MD, ME, MF, MG, MH, MK, ML, MM, MN, MO, MP, MQ, MR, MS, MT, MU, MV, MW, MX, MY, MZ, NA, NC, NE, NF, NG, NI, NL, NO, NP, NR, NU, NZ, OM, PA, PE, PF, PG, PH, PK, PL, PM, PN, PR, PS, PT, PW, PY, QA, RE, RO, RS, RU, RW, SA, SB, SC, SD, SE, SG, SH, SI, SJ, SK, SL, SM, SN, SO, SR, SS, ST, SV, SX, SY, SZ, TC, TD, TF, TG, TH, TJ, TK, TL, TM, TN, TO, TR, TT, TV, TW, TZ, UA, UG, UM, US, UY, UZ, VA, VC, VE, VG, VI, VN, VU, WF, WS, YE, YT, ZA, ZM, ZW
PHONE_NATIONAL_NUMBERPhone National NumberTEXT
PHONE_EXTENSIONPhone ExtensionTEXT
Fields that track how candidates discovered the job opportunity, including referral sources, job boards, and additional source details
KeyLabelExpected TypeOptions
SOURCESourceENUMSOURCE_OTHER, SOURCE_OTHER_JOB_BOARD
SOURCE_OTHERSource OtherTEXT

Conditional Rendering

Displaying Sections Conditionally

Sections should only be displayed when at least one child question’s display_when condition is met The display_when field on a question explains what condition needs to be true for the question to be displayed. Only displayed questions will be validated and must be answered. When display_when is null, the field is not conditional and should always be displayed.

Supported Question Types

Conditional rendering is only supported by the following question types:
  • BOOLEAN - Shows/hides fields based on true/false values
  • SINGLE_SELECT - Shows/hides fields based on selected option ID
  • MULTI_SELECT - Shows/hides fields when ANY of the specified option IDs are selected
The answer_equals property matches the answer format expected in the POST Apply endpoint:
// BOOLEAN
{
  "block_type": "QUESTION",
  "question_id": "has_degree",
  "label": "Do you have a college degree?",
  "question_type": "BOOLEAN"
},
{
  "block_type": "QUESTION",
  "question_id": "degree_details",
  "label": "What degree do you have?",
  "question_type": "TEXT",
  "display_when": {
    "question_id": "has_degree",
    "answer_equals": true  // Shows when candidate answers "yes"
  }
}

// SINGLE_SELECT
{
  "block_type": "QUESTION",
  "question_id": "work_location",
  "label": "Preferred work location?",
  "question_type": "SINGLE_SELECT",
  "options": [
    { "id": "remote_id", "label": "Remote" },
    { "id": "office_id", "label": "Office" }
  ]
},
{
  "block_type": "QUESTION",
  "question_id": "timezone",
  "label": "Your timezone?",
  "question_type": "TEXT",
  "display_when": {
    "question_id": "work_location",
    "answer_equals": "remote_id"  // Shows only for remote workers
  }
}

// MULTI_SELECT
// For `MULTI_SELECT` questions, the condition is met if the candidate's answer
// includes **ANY** of the option IDs specified in `answer_equals`. For example,
// if `answer_equals: ["A", "B"]` and the candidate selects `["B", "C"]`, the
// condition is satisfied because option "B" is present in both.
{
  "block_type": "QUESTION",
  "question_id": "skills",
  "label": "Your skills?",
  "question_type": "MULTI_SELECT",
  "options": [
    { "id": "python", "label": "Python" },
    { "id": "javascript", "label": "JavaScript" },
    { "id": "rust", "label": "Rust" }
  ]
},
{
  "block_type": "QUESTION",
  "question_id": "web_experience",
  "label": "Web development experience?",
  "question_type": "TEXT",
  "display_when": {
    "question_id": "skills",
    "answer_equals": ["python", "javascript"]  // Shows if either selected
  }
}
I