Guide: Producing a Form Envelope for Integrations
This document is intended as a helper to technical teams who are seeking to create Form Submission packages for submitting data to CommCareHQ, generally to update one or more cases in a project space.
Creating these documents is the biggest stumbling block for implementing partners. This guide won't go into detail about individual fields or specifications since those are covered elsewhere, but will provide advice about structuring transactions for submission, and what data is expected.
The best way to get started with a template for integration is to create a CommCare Form in a sample app which completes the actions you want your integration to take, and to review the raw XML in CommCare HQ using the “Raw XML” view / download in the Submit History Report. We strongly, strongly recommend you do that in addition to using these templates.
Note: Forms submitted through the API may only be easy to find with the Raw Forms, Errors & Duplicates report, rather than the Submit History Report.
Base Example Template
The following is a sample template for a Form XML Submission illustrating what data needs to be provided by an integration.
Fields which will need to be provided are written as {{field_name}} for further explanation below, everything else should be submitted as is.
<?xml version="1.0" ?>
<data name="{{form_name}}" version="{{form_version}}" xmlns="{{form_schema_id}}" xmlns:jrm="http://dev.commcarehq.org/jr/xforms">
<n0:meta xmlns:n0="http://openrosa.org/jr/xforms">
<n0:deviceID>{{integration_source_id}}</n0:deviceID>
<n0:timeStart>{{time_start}}</n0:timeStart>
<n0:timeEnd>{{time_end}}</n0:timeEnd>
<n0:username>{{commcare_username}}</n0:username>
<n0:userID>{{commcare_user_id}}</n0:userID>
<n0:instanceID>{{unique_form_guid}}</n0:instanceID>
</n0:meta>
{{form_contents}}
</data>
Field Explanation Guide
form_name - A human readable description of what this form does. Will appear in reports
Specific to: Your Integration
Suggested Use - A terse describe the function of your submission
Example: Automatic Patient Updater
form_version - A numeric version for the form schema
Specific to: Your Integration
Suggested Use - Once your integration is in production, increment this number in your code any time you change the code that generates these blocks
Example: 1
form_schema_id - A unique ID for the schema of this XML document. Will be used to group form submissions. XMLNS Schemas look like urls by tradition, but do not need to actually be valid urls.
Specific to: Your Integration
Suggested Use - Use a different schema ID for each type of integration you build, each document with the same schema ID should have the same document structure
Example: http://mycompany.com/commcare/patient_updater
integration_source_id - A plaintext description of what engine is generating this form envelope
Specific to: Your Integration
Suggested Use: Terse description of the integration environment that generated the envelope. If a library was used to generate the envelope, this should name the library.
Example: mycompany custom commcare integration
time_start - The time the integration run began as an ISO8601 compliant timestamp
Specific to: One run of the integration
Suggested Use: Initially just set one timestamp for all time events, or set timestamps to generate as they are requested. Further considerations described at the bottom of this page
Example: 2019-09-24T13:55:14.281-04
time_end - The time this envelope was finished as an ISO8601 compliant timestamp
Specific to: One run of the integration
Suggested Use: Initially just set one timestamp for all time events, or set timestamps to generate as they are requested. Further considerations described at the bottom of this page
Example: 2019-09-24T13:55:14.281-04
commcare_username - The login username submitting this data.
Specific to: The project space where the integration is run
Suggested Use: Should be populated with the login username of the user whose credentials will be used to submit this envelope
Example: jdoe@mycompany.com
commcare_user_id - The machine GUID of the Web User submitting this data
Specific to: The project space where the integration is run
Suggested Use: This ID can be identified in a few ways.
Navigating to the CommCareHQ Web Users page, selecting your user, then viewing your GUID in the url bar
From the List Web Users API
Viewing a form submission submitted by your user in the UI
Example: 1e670b9f-7259-41b0-bb2f-b1e2cf824828
unique_form_guid - A unique UUIDv4 machine id which represents this form envelope. This ID is used to ensure idempotency about the transaction while allowing resubmission. If you submit an envelope twice with the same id, HQ will treat them as the same submission.
Specific to: One run of the integration
Suggested Use: Generate a random UUIDv4 id from a library in your platform for each transaction.
Example: 9b107fb4-c993-411b-87de-e2037377264a
form_contents - The remainder of the form is an XML document containing arbitrary elements, including structured CaseXML Transactions as explained below
A resulting envelope:
<?xml version="1.0" ?>
<data name="Automatic Patient Updater" version="1" xmlns="http://mycompany.com/commcare/patient_updater" xmlns:jrm="http://dev.commcarehq.org/jr/xforms">
<n0:meta xmlns:n0="http://openrosa.org/jr/xforms">
<n0:deviceID>mycompany commcare integration tool</n0:deviceID>
<n0:timeStart>2019-09-24T13:55:14.281-04</n0:timeStart>
<n0:timeEnd>2019-09-24T13:55:14.281-04</n0:timeEnd>
<n0:username>jdoe@mycompany.com</n0:username>
<n0:userID>1e670b9f-7259-41b0-bb2f-b1e2cf824828</n0:userID>
<n0:instanceID>9b107fb4-c993-411b-87de-e2037377264a</n0:instanceID>
</n0:meta>
</data>
Case Data
Inside of your form transaction you are probably ultimately intending to inject one or more CaseXML Transactions to change case data. You can read that spec sheet for additional specifics about what transactions can perform.
Two examples of case changes are provided below to illustrate how to encode those transactions. You can include as many casexml transactions as necessary in your envelopes (in the {{form_contents}} section above, but we recommend batching around 50 case transactions per form submission
Some fields are common with those above, new fields are described below the template.
Create a new case
...
<n0:case case_id="{{case_id}}" date_modified="{{time_end}}" user_id="{{commcare_username}}" xmlns:n0="http://commcarehq.org/case/transaction/v2">
<n0:create>
<n0:case_name>{{case_name}}</n0:case_name>
<n0:owner_id>{{owner_id}}</n0:owner_id>
<n0:case_type>{{case_type}}</n0:case_type>
</n0:create>
<n0:update>
<n0:{{case_field}}>{{field_value}}</n0:{{case_field}}>
...
</n0:update>
</n0:case>
...
Field Explanation Guide
case_id - A UUIDv4 machine code that uniquely identifies this case
Suggested Use - In this case, since we are creating a case, this field should be set to a newly generated UUIDv4 value
Example: a1d6916d-3d3c-4b90-bd86-64de292c6ce7
case_name - A human readable description of the entity being kept track of with this case object
Specific to: Your project configuration
Suggested Use - Terse, human readable description
Example: Steve Johnson
owner_id - The UUIDv4 Machine ID of the entity which owns this case. This is either a CommCare User, a Location, or a Group
Specific to: Your project configuration
Suggested Use - Which ID this is set to is highly specific to each project, and may require ingesting data from an appropriate API or reviewing form submissions to find a sample owner_id in use
Example: 313d21e6-ae44-4fe5-899e-6926b43b969c
case_type - The CommCare Case Type for the model that you are creating
Specific to: Your project configuration
Suggested Use: This should be clear from sample form submissions, or from reviewing the Case Module in the app builder for the type id.
Example: patient
The remaining data to be set against the case is configured as a key/value dictionary in the update block, which contains the remaining fields whether a case is being created or updated.
Update an existing case
If a case should be updated rather than created, the structure of the transaction is the same, but only containing the update section. Fields from the create section can be placed in the update section to change them once the case is already created.
Advanced Usage
These are considerations which aren't important for initial integration rollout or testing, but may prove helpful in long term production use cases
Time Start / End / Etc
There's no specific semantic importance to timeStart and timeEnd values for integrations, and for initial rollout it's generally fine to just create one timestamp when you generate the envelope and reuse it in all fields.
Once things are working, though, setting them intentionally can still be helpful for debugging production issues.
We recommend setting timeStart to the time at which the integration run began or finished retrieving the data that will be submitted, and timeEnd to the time when the envelope was sealed, spooled, and ready to submit. This allows the identification of process ordering or time sequencing issues.