# Overview

Welcome to the Flo HRIS API! This guide explains how customers can programmatically sync candidate and job application data from Flo into their HRIS platforms. It outlines authentication, schema, examples, and the proposed solution design. Customers can use this API to retrieve the data that will be directly imported into their HRIS system.

### GET /v1/job-applications

Filtering via Query Parameters

**job\_application\_status** (string, optional) – filters by pipeline stage (Application Extended, Offer Accepted, etc.)

* This field is a set of custom statuses defined by each customer
* The value needs to be a step in an Active Pipeline Template
* The value is case insensitive
* When included, only Statuses of that value are returned.
* When omitted, all Statuses within the timeframe are returned.
* Use Case Examples
  * Viewing data on job applications in the “Hired” Status
  * Viewing only job applications that have “Offer Rejected”

**job\_application\_status\_bucket** (string, optional) – filters by pipeline status bucket (Applied, Offered, Hired etc.)

* This represents the group of statues steps used by your organization
* The value needs to correspond to a Bucket in the pipelines you use for jobs
* The value is case insensitive (i.e. “HIRED” and “hired” are treated the same)
* When included, all of the statuses with the corresponding “statusBucketName” are included in the response.
* Use Case Examples
  * Viewing all job applications that have been in the “Offered” Status bucket

**This Flo article can help with more concepts around Pipeline Building:** [**https://help.florecruit.com/en/articles/6552344-ats-creating-and-editing-pipeline-templates**](https://help.florecruit.com/en/articles/6552344-ats-creating-and-editing-pipeline-templates)

**job\_application\_status\_start** (datetime with timezone, optional) – Returns job applications that had at least one status change within the specified date range. The jobApplicationStatuses array shows only status changes within that range.

Note: jobApplicationLastStatusUpdate always shows the candidate's most recent status timestamp, which may be outside your query range.

* Default value is 30 days in the past
* Not including a time, will default the start time to midnight of the date provided

**job\_application\_status\_end** (datetime with timezone, optional) – filter candidates by last status update.

* Not including a time will set the date to midnight of the date provided

**Note on Timezones:**

* We store DateTime data in the UTC timezone
* For the parameters above, you have the following options:
  * If you include your local timezone, we will parse that and convert to UTC time.
  * If you include a DateTime with no timezone, we will assume it is UTC time.
  * If you include a Date with no time, we will default to midnight UTC of that date.

Using these query parameters if you wanted all job applications that were in a “Hired” status in October of 2025, you would request like this:

```shellscript
GET 
/v1/job-applications?job_application_status_start=2025-10-01&job_application_status_end=2025-11-01&job_application_status=Hired
```

**Response Data Schema**

#### Candidate Fields

| firstName    | string         | Candidate’s first name                                         |
| ------------ | -------------- | -------------------------------------------------------------- |
| lastName     | string         | Candidate’s last name                                          |
| email        | string \| null | If the user is not created with an email, value will be null   |
| phone        | string \| null | Candidate phone number                                         |
| candidateId  | UUID string    | Unique ID per candidate                                        |
| candidateUrl | string         | Flo URL that navigates to the Candidate's Profile in your ATS. |

#### Job / Job Application Fields

| applicationId                  | UUID string              | Unique ID per job application                                                                                   |
| ------------------------------ | ------------------------ | --------------------------------------------------------------------------------------------------------------- |
| jobTitle                       | string                   | Title of the job                                                                                                |
| jobId                          | UUID string              | Unique ID per job                                                                                               |
| department                     | string                   | Department from job record                                                                                      |
| officeLocation                 | string                   | Office location from job record                                                                                 |
| employmentType                 | string                   | Employment type (Full-time, Intern, etc.)                                                                       |
| hiringType                     | string                   | Hiring type (Lateral, Student Hiring, etc.)                                                                     |
| jobApplicationLastStatusUpdate | datetime                 | Timestamp of the latest job application status change – note that this can be later than your filtered end time |
| position                       | string                   | Job position type                                                                                               |
| requisitionId                  | string \| null           | Job requisition id                                                                                              |
| startDate                      | datetime \| null         | Offer Details Start Date                                                                                        |
| salary                         | int \| null              | Offer Details Salary                                                                                            |
| addressLine1                   | string                   | Candidate address per job app                                                                                   |
| addressLine2                   | string                   | Candidate address per job app                                                                                   |
| city                           | string                   | Candidate address per job app                                                                                   |
| state                          | string                   | Candidate address per job app                                                                                   |
| zip                            | string                   | Candidate address per job app                                                                                   |
| jobApplicationStatuses         | See Below (List of JSON) | List of job application status changes                                                                          |

#### Job Application Status Fields

| statusName       | string   | Name of status                              |
| ---------------- | -------- | ------------------------------------------- |
| statusBucketName | string   | Name of status bucket                       |
| statusUpdatedAt  | datetime | Time the job application entered the status |

#### Job Application Custom Fields

| customFieldTitle  | string                   | The title/question text of the custom field                                                                                                                                                                                                                                                                          |
| ----------------- | ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| customFieldAnswer | array of strings \| null | <p>Array of answer values.</p><ul><li>For single-select, free text, date, numerical, monetary, and boolean questions: contains a single value</li><li>For multi-select questions: contains multiple values</li><li>If no answer exists for the question: <code>null</code> or empty array <code>\[]</code></li></ul> |

#### JSON Format:

<pre class="language-json"><code class="lang-json">[
  {
    "firstName": "Jane",
    "lastName": "Doe",
    "candidateId": "fge25ghn-4mh7-4kli-c9sz-e436ht34jt09",
    "candidateUrl": "https://florecruit.com/app/{org_name}/admin/recruits/125342/",
    "email": "jane.doe@example.com",
    "phone": "+1-555-123-4567",
    "applicationId": "f18fc41a-4357-4520-a9ce-e477ef947b36",
    "jobTitle": "Entry Level Associate",
    "jobId": "d12dvq4p-6234-eo23-a0o3-d41fef91edb12b",
    "department": "Litigation",
    "officeLocation": "New York",
    "employmentType": "Full-time",
    "hiringType": "Student Hiring",
    "position": "Associate",
    "requisitionId": "req-12345",
    "startDate": "2025-10-10",
    "salary": 175000,
    "addressLine1": "1428 Elm Street",
    "addressLine2": "Apartment 101",
    "city": "Springfield",
    "state": "Illinois",
    "zipCode": "62704",
    "jobApplicationStatuses": [
      {
        "statusName": "Application Received",
<strong>        "statusBucketName": "Applied",
</strong>        "statusUpdatedAt": "2025-10-01T22:07:44Z"
      },
      {
        "statusName": "Interviewing",
        "statusBucketName": "Interviewing",
        "statusUpdatedAt": "2025-10-03T12:07:44Z"
      },
      {
        "statusName": "Hired",
        "statusBucketName": "Hired",
        "statusUpdatedAt": "2025-10-06T22:07:44Z"
      }
    ],
    "jobApplicationLastStatusUpdate": "2025-10-06T22:07:44Z",
    "customFields": [
      {
        "customFieldTitle": "Years of Experience",
        "customFieldAnswer": ["5"]
      },
      {
        "customFieldTitle": "Preferred Practice Areas",
        "customFieldAnswer": ["Litigation", "Corporate Law", "Employment Law"]
      },
      {
        "customFieldTitle": "Bar Admission Date",
        "customFieldAnswer": ["2020-06-15"]
      },
      {
        "customFieldTitle": "Additional Notes",
        "customFieldAnswer": null
      }
    ]
  },
]
</code></pre>

### Filtering Examples with Sample Data

If you would like to get the Job Applications that were moved to the “Hired” Status on October 6th, 2025 – you would structure your request like this:

```shellscript
GET 
/v1/job-applications?job_application_status_start=2025-10-06T00:00:00Z&job_application_status_end=2025-10-07T00:00:00Z&job_application_status=Hired
```

\
The result would be the following. For simplicity, assume there is only one result in the response.

```json
[
  {
    "firstName": "Jane",
    "lastName": "Doe",
    "candidateId": "fge25ghn-4mh7-4kli-c9sz-e436ht34jt09",
    "candidateUrl": "https://florecruit.com/app/{org_name}/admin/recruits/125342/",
    "email": "jane.doe@example.com",
    "phone": "+1-555-123-4567",
    "applicationId": "f18fc41a-4357-4520-a9ce-e477ef947b36",
    "jobTitle": "Entry Level Associate",
    "jobId": "d12dvq4p-6234-eo23-a0o3-d41fef91edb12b",
    "department": "Litigation",
    "officeLocation": "New York",
    "employmentType": "Full-time",
    "hiringType": "Student Hiring",
    "position": "Associate",
    "requisitionId": "req-12345",
    "startDate": "2025-10-10",
    "salary": 175000,
    "addressLine1": "1428 Elm Street",
    "addressLine2": "Apartment 101",
    "city": "Springfield",
    "state": "Illinois",
    "zipCode": "62704",
    "jobApplicationStatuses": [
      {
        "statusName": "Hired",
        "statusBucketName": "Hired",
        "statusUpdatedAt": "2025-10-06T22:07:44Z"
      }
    ],
    "jobApplicationLastStatusUpdate": "2025-10-06T22:07:44Z",
    "customFields": [
      {
        "customFieldTitle": "Years of Experience",
        "customFieldAnswer": ["5"]
      },
      {
        "customFieldTitle": "Preferred Practice Areas",
        "customFieldAnswer": ["Litigation", "Corporate Law", "Employment Law"]
      },
      {
      "customFieldTitle": "Bar Admission Date",
      "customFieldAnswer": ["2020-06-15"]
      },
      {
        "customFieldTitle": "Additional Notes",
        "customFieldAnswer": null
      }
    ]
  },
]
```

**The same request with a Status of “Interviewing”**

```shellscript
GET 
/v1/job-applications?job_application_status_start=2025-10-06T00:00:00Z&job_application_status_end=2025-10-07T00:00:00Z&job_application_status=Interviewing
```

**Would return**

```json
[]
```

Because there is no Status Update for “Interviewing” within that time frame.

Filtering by the Status Bucket

```shellscript
GET 
/v1/job-applications?job_application_status_start=2025-10-06T00:00:00Z&job_application_status_end=2025-10-07T00:00:00Z&job_application_status_bucket=Applied
```

Would return only the statuses in that bucket

```json
[
  {
    "firstName": "Jane",
    "lastName": "Doe",
    "candidateId": "fge25ghn-4mh7-4kli-c9sz-e436ht34jt09",
    "candidateUrl": "https://florecruit.com/app/{org_name}/admin/recruits/125342/",
    "email": "jane.doe@example.com",
    "phone": "+1-555-123-4567",
    "applicationId": "f18fc41a-4357-4520-a9ce-e477ef947b36",
    "jobTitle": "Entry Level Associate",
    "jobId": "d12dvq4p-6234-eo23-a0o3-d41fef91edb12b",
    "department": "Litigation",
    "officeLocation": "New York",
    "employmentType": "Full-time",
    "hiringType": "Student Hiring",
    "position": "Associate",
    "requisitionId": "req-12345",
    "startDate": "2025-10-10",
    "salary": 175000,
    "addressLine1": "1428 Elm Street",
    "addressLine2": "Apartment 101",
    "city": "Springfield",
    "state": "Illinois",
    "zipCode": "62704",
    "jobApplicationStatuses": [
      {
        "statusName": "Application Received",
        "statusBucketName": "Applied",
        "statusUpdatedAt": "2025-10-01T22:07:44Z"
      },
    ],
    "jobApplicationLastStatusUpdate": "2025-10-06T22:07:44Z",
    "customFields": [
      {
        "customFieldTitle": "Years of Experience",
        "customFieldAnswer": ["5"]
      },
      {
        "customFieldTitle": "Preferred Practice Areas",
        "customFieldAnswer": ["Litigation", "Corporate Law", "Employment Law"]
      },
      {
        "customFieldTitle": "Bar Admission Date",
        "customFieldAnswer": ["2020-06-15"]
      },
      {
        "customFieldTitle": "Additional Notes",
        "customFieldAnswer": null
      }
    ]
  },
]
```

### Understanding Custom Fields

Custom Fields are custom questions that your organization can configure to collect additional information on job applications. These fields are returned in the custom`Fields` array for each job application.

**Key Points:**

1. **Visibility:** Only custom fields configured with `SHOW_ON_JOB_APPLICATION = TRUE` are included in the API response
   1. If no Custom Fields are configured the customFields field will be not be present in the response.
2. **Answer Types:** Custom fields support various question types:
   * **Free Text:** Text responses
   * **Date:** Date values (returned as string in ISO format)
   * **Numerical:** Numeric values (returned as string)
   * **Monetary**: Currency values (returned as string)
   * **Single-Select:** One option selected from a list
   * **Multi-Select:** Multiple options selected from a list
3. **Answer Format:** All answers are returned as strings in the `customFieldAnswer` array:
   * Single-value questions (free text, date, numerical, monetary, single-select, boolean): array contains one string
   * Multi-select questions: array contains multiple strings
   * Unanswered questions: `null`
4. **Consistency:** All custom fields configured for job applications are returned, even if they have no answer

**Example Scenarios (Responses have been abbreviated to focus on Custom Fields):**

**Scenario 1:** Job Application with Multiple Custom Fields

```json
{
  "applicationId": "f18fc41a-4357-4520-a9ce-e477ef947b36",
  "firstName": "Jane",
  "lastName": "Doe",
  "customFields": [
    {
      "customFieldTitle": "Years of Experience",
      "customFieldAnswer": ["8"]
    },
    {
      "customFieldTitle": "Practice Areas of Interest",
      "customFieldAnswer": ["Litigation", "Corporate Law", "Employment Law"]
    },
    {
      "customFieldTitle": "Bar Admission Date",
      "customFieldAnswer": ["2020-06-15"]
    },
    {
      "customFieldTitle": "Willing to Relocate",
      "customFieldAnswer": ["true"]
    }
  ]
}
```

**Scenario 2:** Job Application with Unanswered Custom Fields

```json
{
  "applicationId": "a1b2c3d4-5678-90ef-ghij-klmnopqrstuv",
  "firstName": "John",
  "lastName": "Smith",
  "customFields": [
    {
      "customFieldTitle": "Years of Experience",
      "customFieldAnswer": ["3"]
    },
    {
      "customFieldTitle": "Additional Notes",
      "customFieldAnswer": null
    },
    {
      "customFieldTitle": "Preferred Start Date",
      "customFieldAnswer": null
    }
  ]
}
```

**Note:** Custom fields are organization-specific. The fields returned will match the custom field questions configured in your Flo organization settings.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.joinflo.com/flo-apis/hris-api/overview.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
