List applications

List program applications endpoint

GET /api/v1/admin/programs/<programSlug>/applications

Exports applications to a specific program as JSON.

Parameters

Path parameters

programSlug

  • Parameter: programSlug

  • Format: A string matching a program slug, such as sample-program.

  • Description: Human readable identifier for the program to export. This is defined by the CiviForm admin during program creation. The CiviForm admin can find the slug for a program by examining the deep link URL on the program index page or in the list of allowed programs on the API key index page.

Query parameters

All query parameters are optional, but case-sensitive.

fromDate

  • Parameter: fromDate

  • Format: An ISO-8601 formatted date (i.e. YYYY-MM-DD).

  • Description: Limits results to applications submitted on or after the provided date, in the CiviForm instance's local time.

toDate

  • Parameter: toDate

  • Format: An ISO-8601 formatted date (i.e. YYYY-MM-DD).

  • Description: Limits results to applications submitted before the provided date, in the CiviForm instance's local time.

pageSize

  • Parameter: pageSize

  • Format: A positive integer.

  • Description: Limits the number of results per page. If pageSize is larger than CiviForm's maximum page size then the maximum will be used. The default maximum is 1,000 and is configurable.

nextPageToken

  • Parameter: nextPageToken

  • Format: An opaque token, such as eyJzZXJpYWxpemVkUGF5bG9hfQ==

  • Description: An opaque, alphanumeric identifier for a specific page of results. When included CiviForm will return a page of results corresponding to the token. See Pagination for more.

Responses

400: Bad Request

Returned if any request parameters fail validation.

401: Unauthorized

Returned if the API key is invalid or does not have access to the program. Check the server logs for the specific reason.

200: OK

For valid requests, CiviForm returns a status code 200 with a JSON body of the structure:

{
  "payload": [application object]
  "nextPageToken": string
}

Pagination

If there are more results for the request, nextPageToken will be a string. If there are no more results to fetch it will be null. API consumers should request more pages using the nextPageToken query paramater until it returns null to ensure they have received a complete result set.

If nextPageToken is present the other query parameters are optional. If the other parameters are included, they must match the values provided on the initial request or CiviForm will reject the request as invalid.

Payload

The value of the payload property is an array of objects, each consisting of metadata about an application and the application itself.

Note The order of these properties is not guaranteed, they're displayed alphabetically here for convenience.

For example, one of these objects might look like this:

{
  "applicant_id": 1,
  "application_id": 2,
  "create_time": "2023-05-25T13:46:15-07:00",
  "language": "en-US",
  "program_name": "sample-application",
  "program_version_id": 3,
  "revision_state": "CURRENT",
  "status": "custom status",
  "submit_time": "2023-05-26T13:46:15-07:00",
  "submitter_type": "TRUSTED_INTERMEDIARY",
  "ti_email": "alice@trustedintermediary.org",
  "ti_organization": "TIs Inc.",
  "application": {...}
}

Payload metadata

applicant_id

  • Property: applicant_id

  • JSON Type: number

  • Format: Integer

  • Description: The unique integer ID of the applicant.

application_id

  • Property: application_id

  • JSON Type: number

  • Format: Integer

  • Description: The unique integer ID of this application.

create_time

  • Property: create_time

  • JSON Type: string

  • Format: A datetime formatted in the ISO 8601 extended offset format. For example, 2023-10-26T15:01:56-07:00. Note: See the DateTimeFormatter javadoc for format pattern specifics. This is the ISO_OFFSET_DATE_TIME format.

  • Description: The time the first question in a program was submitted, in the timezone of the CiviForm instance. Note: If a question is shared between programs, a question must be submitted as part of this program to set create_time. Questions submitted as part of another program do not start the clock.

language

  • Property: language

  • JSON Type: string

  • Format: An IETF language tag language tag. US English is en-US.

  • Description: Indicates the applicant's preferred language, as specified by the language dropdown in the header bar.

program_name

  • Property: program_name

  • JSON Type: string

  • Format: All URL-safe characters

  • Description: The immutable admin name of the program. This is also the programSlug used in the API request.

program_version_id

  • Property: program_version_id

  • JSON Type: number

  • Format: Integer

  • Description: The unique integer ID of this version of the program. This ID changes every time a program, or question within a program, is updated. If you need a stable identifier for a program, use the program_name.

revision_state

  • Property: revision_state

  • JSON Type: string

  • Value: An enum currently consisting of one of [CURRENT, OBSOLETE]. Note: More values may be added to this enum in the future. Ensure client code can handle additional "unknown" values.

  • Description: Describes the current state of this application. CURRENT indicates this is the most recent version of the application. OBSOLETE indicates this application has been superseded by a newer submission.

status

submit_time

  • Property: submit_time

  • JSON Type: string

  • Value: A datetime formatted in the ISO 8601 extended offset format. For example, 2023-10-26T15:01:56-07:00. Note: See the DateTimeFormatter javadoc for format pattern specifics. This is the ISO_OFFSET_DATE_TIME format.

  • Description: The time the application was submitted, in the timezone of the CiviForm instance.

submitter_type

  • Property: submitter_type

  • JSON Type: string

  • Value: An enum consisting of one of [APPLICANT, TRUSTED_INTERMEDIARY] Note: More values may be added to this enum in the future. Ensure client code can handle additional "unknown" values.

  • Description: The type of user submitting the application. APPLICANT indicates the applicant submitted the application themselves, and TRUSTED_INTERMEDIARY indicates the application was submitted by a TI on behalf of an applicant.

ti_email

  • Property: ti_email

  • JSON Type: string or null

  • Value: All characters, formatted as an email address

  • Description: The email address of the TI that submitted the application on behalf of an applicant. null if the applicant submitted the application themselves.

ti_organization

  • Property: ti_organization

  • JSON Type: string or null

  • Value: All characters.

  • Description: The name of the organization the TI belongs to, as specified in the Intermediaries admin panel. See Manage trusted intermediaries for more.

application

  • Property: application

  • JSON Type: object

  • Value: The applicant's application

  • Description: See the Application object section below.

Application object

The application object contains the applicant's answers to the questions in the program. It's a snapshot of the applicant's answers at the time they clicked submit on their application, and is not updated if they change their answer to a question as part of filling out an application to a different program.

If they update their answers to this program and click submit again, a new application entry is created. See the revision_state metadata field for more.

The application object includes all questions that have ever been in a program, even if the applicant did not answer them or they were skipped due to a visibility condition.

Note The application object includes all questions that have ever been in a program, even if they're not in the most recent version of a program. This is for two reasons:

  1. If a question is removed from the API response, code that consumes the response may still expect the question to be present and break when it's not. Keeping questions in the response, even after they're removed from the program, prevents this failure scenario.

  2. If an applicant submits an application and then a question is removed from the program, the API should still return all the applicant's answers. If the application object only included questions from the most recent version of the program, some of the applicant's answers would be missing.

The application object is organized as a set of key-object pairs that represent each question in the program. The key is generated from the admin name of the question, and the objectcontains the applicant's answer. For example, this is the application object for a program with two questions:

  • "What is your name?", which has a question key of applicant_name.

  • "What is your favorite color?", which has a question key of favorite_color.

{
  "applicant_name": {
    "question_type": "NAME",
    "first_name": "Taylor",
    "middle_name": "Allison",
    "last_name": "Swift",
  },
  "favorite_color": {
    "question_type": "TEXT",
    "text": "purple"
  }
}

Question keys

The question key is generated from the immutable admin name of the question. The immutable admin name of the question is specified by the admin when creating a question, and the question key is visible in the generated API docs page.

The question key is generated by removing non-letter characters and replacing spaces with underscores, so applicant name4? becomes applicant_name.

For enumerator questions, such as "List all the members of your household?" (which might have a question key of household_members), and "What are each of their favorite colors?" (question key of household_member_favorite_color), the repeated question is nested under the enumerator question like this:

{
  "household_members": {
    "question_type": "ENUMERATOR",
    "entities": [
      {
        "entity_name": "Taylor",
        "household_member_favorite_color": {
          "question_type": "TEXT",
          "text": "purple"
        }
      },
      {
        "entity_name": "Sza",
        "household_member_favorite_color": {
          "question_type": "TEXT",
          "text": "purple"
        }
      },
      {
        "entity_name": "Carley Rae",
        "household_member_favorite_color": {
          "question_type": "TEXT",
          "text": "red"
        }
      },
    ]
  },
}

In this example, to access the favorite color of the third household member, you'd use this path through the application object:

application.household_members.entities[2].household_member_favorite_color.text

Note Questions can be nested arbitrarily deep, so if a question asked for the hours worked at each job a household member has, a path might look like

application.household_members.entities[2].household_member_jobs.entities[1].household_member_jobs_hours_worked.number

This is the path to the number of hours worked at the 2nd job of the 3rd household member.

See Enumerator questions below for more about enumerator questions.

Question objects

Question objects contain the applicant's answers to a question, as well as some additional metadata. They all contain the same metadata property, as well as additional properties that vary based on the question type.

Warning The order of properties within the a JSON object is not guaranteed.

Question metadata

All question objects have a question_type field.

  • Property: question_type

  • JSON Type: string

  • Format: An enum currently consisting of one of [ADDRESS, MULTI_SELECT, CURRENCY, DATE, SINGLE_SELECT, EMAIL, ENUMERATOR, FILE_UPLOAD, ID, NAME, NUMBER, TEXT, PHONE]. Note: More values may be added to this enum in the future. Ensure client code can handle additional "unknown" values.

  • Description: Specifies the type of question this object represents.

Address questions

"question_type": "ADDRESS"

In addition to the metadata field, address questions have the following properties:

street

  • Property: street

  • JSON Type: string or null

  • Format: A Unicode string of any characters. null if the question was unanswered.

  • Description: The "street" portion of the applicant's address. If any of street, line2, city, state, or zip are provided, then only line2 is optional.

line2

  • Property: line2

  • JSON Type: string or null

  • Format: A Unicode string of any characters. null if the question was unanswered or the field was not filled.

  • Description: The second line of the applicant's address (such as their apartment, suite number, etc). If any of street, line2, city, state, or zip are provided, then only line2 is optional.

city

  • Property: city

  • JSON Type: string or null

  • Format: A Unicode string of any characters. null if the question was unanswered.

  • Description: The "city" portion of the applicant's address. If any of street, line2, city, state, or zip are provided, then only line2 is optional.

state

  • Property: state

  • JSON Type: string or null

  • Format: A two letter state code, capitalized. (e.g. NY). Includes 50 states, DC, and 8 territories. See USPS's Two–Letter State and Possession Abbreviations for the full list. null if the question was unanswered.

  • Description: The "state" portion of the applicant's address. If any of street, line2, city, state, or zip are provided, then only line2 is optional.

zip

  • Property: zip

  • JSON Type: string or null

  • Format: A Unicode string consisting of 5 digits (55555), or 5 digits, a dash, a 4 digits (55555-5555). null if the question was unanswered.

  • Description: The "zip" portion of the applicant's address. If any of street, line2, city, state, or zip are provided, then only line2 is optional.

corrected

  • Property: corrected

  • JSON Type: string or null

  • Format: An enum consisting of [Corrected, Failed, AsEnteredByUser] or null if the question was unanswered or address correction is not enabled.

  • Description: Indicates the result of correcting an address.

latitude

  • Property: latitude

  • JSON Type: string or null

  • Format: A string consistening of a signed Java double. null if the question was unanswered, the address was not corrected, address correction failed, or the user kept the address as they entered it.

  • Description: The latitude of the applicant's corrected address, as specified by the address correction server.

longitude

  • Property: longitude

  • JSON Type: string or null

  • Format: A string consistening of a signed Java double. null if the question was unanswered, the address was not corrected, address correction failed, or the user kept the address as they entered it.

  • Description: The longitude of the applicant's corrected address, as specified by the address correction server.

well_known_id

  • Property: well_known_id

  • JSON Type: string or null

  • Format: A Well Known ID for a spacial reference system. null if the question was unanswered, the address was not corrected, address correction failed, or the user kept the address as they entered it.

  • Description: The Well Known ID for the spacial reference system used by the latitude and longitude properties.

service_area

  • Property: service_area

  • JSON Type: string or null

  • Format: A comma-separated, serialized list of service areas. Each is formatted as {service area name}_{inclusion state}_{unix timestamp}, such as springfield_county_InArea_1709069741. The service area name is defined by the admin, the inclusion state is one of [InArea, NotInArea, Failed], and the unix timestamp is the time when the inclusion check was made. null if the question was unanswered, the address was not corrected, address correction failed, or the user kept the address as they entered it. See Configure GIS Service and ServiceAreaInclusionGroup.java for more.

  • Description: Describes the service areas this address has been validated against, and whether it is in each one.

Note If you would like an easier-to-consume format for address correction related fields, please let the CiviForm maintainer team know so changes can be prioritized.

Altogether, an address question looks like

"applicant_home_address" : {
  "question_type" : "ADDRESS",
  "street" : "23 Cornelia Street",
  "line2" : null,
  "city" : "New York",
  "state" : "NY",
  "zip" : "10014",
  "corrected" : "Corrected",
  "latitude" : "40.73175",
  "longitude" : "-74.00224",
  "well_known_id" : "4326",
  "service_area" : "manhattan_InArea_1709069741,brooklyn_NotInArea_1709069741"
},

Checkbox questions

Checkbox questions are a form of multi-select question. See Multiselect questions below.

Currency questions

"question_type": "CURRENCY"

In addition to the metadata field, currency questions have the following property:

currency_dollars

  • Property: currency_dollars

  • JSON Type: number or null

  • Format: A JSON number. null if unanswered.

  • Description: An amount, in dollars.

A currency question looks like

"applicant_weekly_grocery_cost" : {
  "question_type" : "CURRENCY",
  "currency_dollars" : 123.45
},

Date questions

"question_type": "DATE"

In addition to the metadata field, date questions have the following property:

date

  • Property: date

  • JSON Type: string or null

  • Format: An ISO 8601 formatted date, without the timezone. e.g YYYY-MM-DD. null if unanswered.

  • Description: The applicant's answer to the date question.

A date question looks like

"birth_date" : {
  "question_type" : "DATE",
  "date" : "1989-12-13"
},

Dropdown questions are a form of single-select questions. See Single-select questions below.

Email questions

"question_type": "EMAIL"

In addition to the metadata field, email questions have the following property:

email

  • Property: email

  • JSON Type: string or null

  • Format: A Unicode string containing an email address, as validated by the applicant's browser. null if unanswered. Note: This is only client-side validated, so it should be treated as containing anything. No validation is performed if the applicant's browser doesn't properly validate fields with <input type="email">. See MDN for more.

  • Description: The applicant's answer to the email question.

An email question looks like

"contact_email" : {
  "question_type" : "EMAIL",
  "email" : "tswift1989@gmail.com"
},

Enumerator questions

"question_type": "ENUMERATOR"

Enumerator questions allow you to ask applicants the same question about multiple entities. For example, how many hours do they work at each of their jobs? Or what is the age of each of their household members?

Applicants are asked to list the name of each entity, and then asked each repeated question for each entity they named.

In addition to the metadata field, enumerator questions have the following property:

entities

  • Property: entities

  • JSON Type: [object]

  • Format: An array of JSON objects, each of which represents a repeated entity. Empty [] if unanswered.

  • Description: The list of repeated entities, each of which contains answers to the repeated questions for that entity.

Repeated entity objects

Each repeated entity is an object that follows the same semantics as the application object as a whole. It has an entity_name property, as well as a property for each repeated question.

entity_name

  • Property: entity_name

  • JSON Type: string

  • Format: A Unicode string of any characters.

  • Description: The name the applicant provided for each repeated entity. Used on each repeated screen in the repeated question title, such as "What is $household_member's phone number?"

An enumerator question, with two entities and a repeated household_member_phone_number phone question and a repeated household_member_job text question, looks like

"household_members": {
  "question_type": "ENUMERATOR",
  "entities": [
    {
      "entity_name": "Taylor",
      "household_member_job": {
        "question_type": "TEXT",
        "text": "Pop artist"
      },
      "household_member_phone_number": {
        "question_type": "PHONE",
        "phone_number": "+16156667777"
      }
    },
    {
      "entity_name": "Sza",
      "household_member_job": {
        "question_type": "TEXT",
        "text": "R&B artist"
      },
      "household_member_phone_number": {
        "question_type": "PHONE",
        "phone_number": "+18623334444"
      }
    }
  ]
},

File upload questions

File upload questions are not currently available in the API. See GitHub Issue #5025 for progress on this feature.

ID questions

"question_type": "ID"

In addition to the metadata field, ID questions have the following property:

id

  • Property: id

  • JSON Type: string or null

  • Format: A Unicode string consisting of only digits (^[0-9]*$). If min or max lengths are specified on the question they are also enforced. null if unanswered. Note: Answers from applications from before a min or max constraint is added to a question will not follow that constraint and may be of any length.

  • Description: The applicant's answer to the ID question.

An ID question looks like

"drivers_license_number" : {
  "question_type" : "ID",
  "id" : "011235813"
},

Multi-select questions

"question_type": "MULTI_SELECT"

Multi-select questions allow applicants to select multiple options from a list.

In addition to the metadata field, multi-select questions have the following property:

selections

  • Property: selections

  • JSON Type: [string]

  • Format: An array of Unicode strings, which are the admin IDs of the selected options. An empty array [] if no options were selected or the question was unanswered. With the exception of questions created before March 2024, admin IDs can only contain lowercase letters, numbers, underscores, and dashes. Note: Any option admin ID that has ever been available for applicants to select may be returned. A list of all possible option admin IDs is available in the program-specific API docs in your CiviForm instance.

  • Description: A list of the question options selected by the applicant.

A multi-select question looks like

"kitchen_implements" : {
  "question_type" : "MULTI_SELECT",
  "selections" : ["whisk", "spatula", "garlic_press"]
},

Name questions

"question_type": "NAME"

In addition to the metadata field, name questions have the following properties:

first_name

  • Property: first_name

  • JSON Type: string or null

  • Format: A Unicode string of any characters. null if the question is unanswered.

  • Description: The applicant's first name. If the question is answered, only the middle_name is optional.

middle_name

  • Property: middle_name

  • JSON Type: string or null

  • Format: A Unicode string of any characters. null if unanswered or not provided.

  • Description: The applicant's middle name. If the question is answered, only the middle_name is optional.

last_name

  • Property: last_name

  • JSON Type: string or null

  • Format: A Unicode string of any characters. null if the question is unanswered.

  • Description: The applicant's last name. If the question is answered, only the middle_name is optional.

A name question looks like

"applicant_name" : {
  "question_type" : "NAME",
  "first_name" : "Taylor",
  "middle_name" : "Allison",
  "last_name" : "Swift",
},

Number questions

"question_type": "NUMBER"

In addition to the metadata field, number questions have the following property:

number

  • Property: number

  • JSON Type: number or null

  • Format: An integer number. If min or max values are specified on the question they are also enforced. null if unanswered. Note: Answers from applications from before a min or max constraint is added to a question will not follow that constraint and may be of any value.

  • Description: The applicant's answer to the number question.

A number question looks like

"lucky_number" : {
  "question_type" : "NUMBER",
  "number" : "13"
},

Radio questions

Radio questions are a form of single-select questions. See Single-select questions below.

Single-select questions

"question_type": "SINGLE_SELECT"

Single-select questions allow applicants to select a single option from a list.

In addition to the metadata field, single-select questions have the following property:

selection

  • Property: selection

  • JSON Type: string or null

  • Format: A Unicode string containing the admin ID of the selected option. null if unanswered. With the exception of questions created before March 2024, admin IDs can only contain lowercase letters, numbers, underscores, and dashes. Note: Any option admin ID that has ever been available for applicants to select may be returned. A list of all possible option admin IDs is available in the program-specific API docs in your CiviForm instance.

  • Description: A list of the question options selected by the applicant.

A multi-select question looks like

"kitchen_implements" : {
  "question_type" : "SINGLE_SELECT",
  "selection" : "garlic_press"
},

Static text questions

Static text questions are not presented in the API because there is nothing for the applicant to answer.

Text questions

"question_type": "TEXT"

In addition to the metadata field, text questions have the following property:

text

  • Property: text

  • JSON Type: string or null

  • Format: A Unicode string containing any characters. If min or max lengths are specified on the question they are also enforced. null if unanswered. Note: Answers from applications from before a min or max constraint is added to a question will not follow that constraint and may be of any length.

  • Description: The applicant's answer to the text question.

A text question looks like

"favorite_color" : {
  "question_type" : "TEXT",
  "text" : "My favorite color is purple 💖"
},

Phone number questions

"question_type": "PHONE"

In addition to the metadata field, phone number questions have the following property:

phone_number

  • Property: phone_number

  • JSON Type: string or null

  • Format: A Unicode string consisting of a phone number prefixed with the country-code, in E164 format. For example, +15556667777. null if unanswered. Note: Phone numbers are validated to be in a valid pattern, but are not confirmed to be dialable.

  • Description: The applicant's answer to the number question.

A phone number question looks like

"cell_phone" : {
  "question_type" : "PHONE",
  "phone_number" : "+15556667777"
},

Example endpoint response

Generated program-specific docs

For an example response for one of your programs, go to "API docs" in the admin console, or visit <my civiform url>/api/docs/v1/. You can see the example response for both your active and draft programs.

Tip For an example response for one of your programs, go to "API docs" in the admin console, or visit <my civiform url>/api/docs/v1/.

Generic program example

Below is an example endpoint response for a generic program.

{
  "nextPageToken": "YXR0ZXJuIG9mIHZpb2xhdGlvbiBvZiBjb21tdW5pdHkKc3Rhb",
  "payload": [{
    "applicant_id": 1,
    "application_id": 2,
    "create_time": "2023-05-25T13:46:15-07:00",
    "language": "en-US",
    "program_name": "sample-application",
    "program_version_id": 3,
    "revision_state": "CURRENT",
    "status": "custom status",
    "submit_time": "2023-05-26T13:46:15-07:00",
    "submitter_type": "TRUSTED_INTERMEDIARY",
    "ti_email": "alice@trustedintermediary.org",
    "ti_organization": "TIs Inc.",
    "application": {
      "favorite_color" : {
        "question_type" : "TEXT",
        "text" : "My favorite color is purple 💖"
      },
      "kitchen_implements" : {
        "question_type" : "SINGLE_SELECT",
        "selection" : "garlic_press"
      }
    }
  }, {
    "applicant_id": 3,
    "application_id": 4,
    "create_time": "2023-05-27T02:21:14-07:00",
    "language": "en-US",
    "program_name": "sample-application",
    "program_version_id": 5,
    "revision_state": "CURRENT",
    "status": "custom status",
    "submit_time": "2023-05-27T02:26:45-07:00",
    "submitter_type": "APPLICANT",
    "ti_email": null,
    "ti_organization": null,
    "application": {
      "favorite_color" : {
        "question_type" : "TEXT",
        "text" : "My favorite color is blue!"
      },
      "kitchen_implements" : {
        "question_type" : "SINGLE_SELECT",
        "selection" : "colander"
      }
    }
  }]
}

Example client code: python

Below is a very minimal script demonstrating how to request applications to a program named "Utility discount program" between January 3, 2022 and February 4, 2022, with a page size of 100.

Warning This script is provided as an example only. It does not do things a production script should, such as retry failed requests.

example_request.py
import json
import os
import requests

URL = 'https://civiform.example.gov/api/v1/admin/programs/utility-discount-program/applications'
AUTH_HEADERS = { 'Authorization': 'Basic ' + os.getenv('CIVIFORM_API_KEY') }

params = { 'fromDate': '2022-01-03', 'toDate': '2022-02-04', 'pageSize': 100 }
results = []

while True:
    response = requests.get(URL, params=params, headers=AUTH_HEADERS)

    if response.status_code != 200:
        print("Request failed with status code: " + str(response.status_code))
        exit(1)

    response_json = response.json()
    results.extend(response_json['payload'])

    if response_json['nextPageToken'] is None:
        break

    params['nextPageToken'] = response_json['nextPageToken']

with open('exported_applications.json', 'w', encoding='utf-8') as f:
    json.dump(results, f, ensure_ascii=False)

print(f'Exported {len(results)} applications.')

Last updated