Epidemiology & Technology

ODK Central API Access using Python

ODK Central provides an API for interacting with the server as described in its docs. Here I will provide some sample code blocks for interacting with the API using pure Python.

Logging in and getting an Access Token

from pprint import pprint
import requests
from requests.exceptions import HTTPError

BASEURL = 'URL/v1/'
EMAIL = "myname@domain.com"
PASSWORD = "mypassword"

try:
    response = requests.post(BASEURL + '/sessions', json={
            "email": EMAIL,
            "password": PASSWORD
    })
    response.raise_for_status()
    jsonResponse = response.json()
    TOKEN = jsonResponse["token"]
    print(TOKEN)
  
except HTTPError as http_err:
    print(f'HTTP error occurred: {http_err}')
except Exception as err:
    print(f'Other error occurred: {err}')



Code language: Python (python)

Logging in and getting an Access Token and using that access token to list your projects

from pprint import pprint
import requests
from requests.exceptions import HTTPError

BASEURL = 'URL/v1/'
EMAIL = "myname@domain.com"
PASSWORD = "mypassword"

# GET TOKEN
try:
    response = requests.post(BASEURL + '/sessions', json={
            "email": EMAIL,
            "password": PASSWORD
    })
    response.raise_for_status()
    jsonResponse = response.json()
    TOKEN = jsonResponse["token"]
    print(TOKEN)
    headers = {
        'Authorization': 'Bearer ' + TOKEN,
    }

    # GET PROJECTS
    try:
        r_projects= requests.get(BASEURL + 'projects', headers=headers)
        print(f' Response Status Code: {r_projects.status_code}')
        json_projects= r_projects.json()
        pprint(json_projects)

    except HTTPError as http_err:
        print(f'HTTP error occurred: {http_err}')
    except Exception as err:
        print(f'Other error occurred: {err}')


except HTTPError as http_err:
    print(f'HTTP error occurred: {http_err}')
except Exception as err:
    print(f'Other error occurred: {err}')

Code language: Python (python)

However, in this approach, we are generating a new token each time the script is run. This may be preferable for automation but not when your are testing out interactions with API. In such scenarios, it would be better to generate a token once and keep using that token to interact with API. Our first script above prints the token in console and that token can be used again and again.

Get all forms across all projects and project wise and total submissions

from pprint import pprint
import requests
from requests.exceptions import HTTPError

TOKEN = 'MToken Received From /sessions POST request in first script'
BASEURL = 'URL/v1/'
 
headers = {
    'Authorization': 'Bearer ' + TOKEN,
}

xheaders = {
    'Authorization': 'Bearer ' + TOKEN,
    'X-Extended-Metadata': 'true',
}

total_submission = 0
try:
    r_projects = requests.get(BASEURL + 'projects', headers=headers)
    json_projects = r_projects.json()
    PROJECTS = len(json_projects)
    print(f'\nTOTAL PROJECTS:  {PROJECTS}')
    for i in range(PROJECTS):
        # print(f'{json_projects[i]}')
        PROJECT = json_projects[i]
        project_id = str(PROJECT['id'])
        print(f"\nID = {project_id}")
        print(f"NAME = {PROJECT['name']}")
        print(f"Archived = {PROJECT['archived']}")
        project_submissions = 0
        try:
            r_forms = requests.get(BASEURL + 'projects/' + project_id + '/forms', headers=xheaders)
            json_forms = r_forms.json()
            FORMS = len(json_forms)

            print(f'TOTAL FORMS: {FORMS}')
            for j in range(FORMS):
                # print(f'{json_forms[j]}')
                form = json_forms[j]
                form_id = str(form['xmlFormId'])
                SUBMISSIONS = form['submissions']
                project_submissions = project_submissions + SUBMISSIONS
                total_submission = total_submission + SUBMISSIONS
                print(f"  SUBMISSIONS: {form['submissions']}  NAME: {form['name']}  STATE: {form['state']} ")

        except HTTPError as http_err:
            print(f'HTTP error occurred: {http_err}')

        finally:
            print(f"PROJECT SUBMISSION:  {project_submissions}")


except HTTPError as http_err:
    print(f'HTTP error occurred: {http_err}')
except Exception as err:
    print(f'Other error occurred: {err}')

finally:
    print(f"TOTAL SUBMISSIONS: {total_submission}")
Code language: Python (python)

Related posts