{% extends "project-base.html" %} {% block title %} API: {{project.title}} {% endblock %} {% block head %} {{block.super}} {% endblock %} {% block title_suffix_text %} API {% endblock %} {% block body_content %}

An API is provided for programmatically getting and updating information stored in this {{project.title}} app. The API can be used from command-line tools and programming languages that allow making GET and/or POST HTTP requests.

Getting data from the app using the GET API

Project data can be read from the API using an HTTP GET request to the following URL:

{{project.get_api_url}}

An API key must be passed in the HTTP Authorization header. You can get your API key from the API keys page.

You’ll get the following response from the API:

{{sample|safe}}

The schema of the response object is documented below.

If you are using an operating system with a command line and the curl tool, you can try out the API by running the following command. Replace your-api-key with your API key. (The slash in the command below indicates a continued line.)

curl \
      --header "Authorization: your-api-key" \
      {{SITE_ROOT_URL}}/api/v1/organizations/{{request.organization.subdomain}}/projects/{{project.id}}/answers

Updating answers using a POST request with key-value pairs

There are two types of POST requests that can be used to update app data. In the first type, described in this section, data values are provided as key-value pairs using the regular web browser form submission method. (In the second form, described below, answers are provided using a JSON data structure that is formatted the same as the JSON data structure returned by a GET request, which may be more appropriate when submitting non-textual and non-binary content.)

In each of the key-value pairs submitted in the POST request, the key is a dotted-path question ID. The key always begins with project. and is followed by the property names on the path to the question being updated, according to the JSON data structure, with property names separated by the . character.

The value of each key-value pair is an answer submitted either as plain text or, for file-type questions, as a binary file. If submitted as plain text and the question expects non-text data, such as a number, the value will be converted. When uploading a binary file, the multipart/form-data content type must be used for the POST request.

For example:

{% for key, value in sample_post_keyvalue %}{{key}}={{value}}
{% endfor %}

The fields are documented below.

Updating fields within a module-set-type question creates a single, new answer to the module-set-type question on each POST request.

As with the GET API, an API key must be passed in the HTTP Authorization header. An API key with write permission must be used. You can get an API key from the API keys page.

If you are using an operating system with a command line and the curl tool, you can try out the API using curl. Replace your-api-key in the command below with your full access API key. Then run the following command. (The slash in the command below indicates a continued line.)

curl \
      --header "Authorization: your-api-key" \
      {% for key, value in sample_post_keyvalue %}-F "{{key}}={% if value != "" %}{{value}}{% else %}@filename.ext{% endif %}" \
      {% endfor %}{{SITE_ROOT_URL}}/api/v1/organizations/{{request.organization.subdomain}}/projects/{{project.id}}/answers

(curl’s -d option can be used in place of -F if none of the fields are file uploads.)

Updating data using a POST request with JSON

The second type of POST request uses a request body in JSON format in the same structure as that returned by the GET request.

The POST request body always includes:

{
  "schema": "GovReady Q Project API 1.0",
  "project": {
    ...
  }
}

Inside the project, replace ... just with the data fields you want to change, including any structure nesting.

For example:

{{sample_post_json|safe}}

The fields are documented below.

The Content-Type header in the request must be set to application/json.

As with the GET API, an API key must be passed in the HTTP Authorization header. An API key with write permission must be used. You can get an API key from the API keys page.

If you are using an operating system with a command line and the curl tool, you can try out the API using curl. First copy the sample POST request body or make your own and save it in a file named data.json. Replace your-api-key in the command below with your full access API key. Then run the following command. (The slash in the command below indicates a continued line.)

curl \
      --header "Authorization: your-api-key" \
      -XPOST --data @data.json \
      --header "Content-Type: application/json" \
      {{SITE_ROOT_URL}}/api/v1/organizations/{{request.organization.subdomain}}/projects/{{project.id}}/answers

Data Schema

The fields returned in the GET response and expected by the POST request body inside the project field are as follows:

{% for path, module, question in schema %} {% ifchanged path module %} {% endifchanged %} {% endfor %}
Field Description

{{module.spec.title}}

These fields occur within {% for item in path %} {{item}} {% if not forloop.last %}→{% endif %} {% endfor %}.

{{question.key}}

{{question.spec.title}}

{{question.spec.help}}

{% if question.spec.type == "module" or question.spec.type == "module-set" %}

{% if question.answer_type_module %} This data field is a JSON object which has sub-fields documented in the “{{question.answer_type_module.spec.title}}” section below. {% if question.spec.type == "module-set" %} When updating answers within this key, a new {{question.answer_type_module.spec.title}} is created on each POST request and appended to the existing set of answers. {% endif %} {% else %} An app must be selected manually in Q before schema information for this field can be determined. {% endif %}

{% elif question.spec.type == "text" or question.spec.type == "password" %}

Data type: string (or null).

{% elif question.spec.type == "email-address" %}

Data type: string (or null); if set, must be a valid email address.

{% elif question.spec.type == "url" %}

Data type: string (or null); if set, must be a valid web address (URL.

{% elif question.spec.type == "longtext" %}

Data type: string (or null); if set, uses CommonMark (Markdown) encoding.

{% elif question.spec.type == "date" %}

Data type: string representing a date in YYYY-MM-DD format (or null).

{% elif question.spec.type == "choice" %}

Data type: string, one of {% for item in question.spec.choices %} {{item.key}} ({{item.text}}) {% if not forloop.last %}, {% endif %} {% endfor %}; or null. {% elif question.spec.type == "multiple-choice" %}

Data type: array of strings; each element is one of {% for item in question.spec.choices %} {{item.key}} ({{item.text}}) {% if not forloop.last %}, {% endif %} {% endfor %}; or null. When uploading with the key-value POST method, repeat the key multiple times in the request to set multiple values {% elif question.spec.type == "yesno" %}

Data type: string; either yes or no; or null.

{% elif question.spec.type == "integer" %}

Data type: number (or null).

{% elif question.spec.type == "real" %}

Data type: number (or null).

{% elif question.spec.type == "file" %}

Data type: object containing file metadata and/or content.

In GET requests, the properties of file objects are url (a link to download the file content), type (the MIME type), and size (the size of the file in bytes).

In JSON POST requests, the properties must be type and content, which must hold an array of one or more strings containing Base64-encoded binary data.

{% else %}

Data type: {{question.spec.type}}.

{% endif %} {% if question.spec.impute %}

This field’s value might be imputed from other values and if so is read-only.

{% endif %}
{% endblock %}