# Source at https://github.com/getodk/central-backend/blob/master/docs/api.yaml # Copied at release time to https://github.com/getodk/docs/blob/master/docs/_static/api-spec/central.yaml # for publishing at https://docs.getodk.org/central-api/ openapi: 3.0.1 info: title: ODK Central API description: |- [ODK Central Backend](https://github.com/getodk/central-backend) is a RESTful API server that provides key functionality for creating and managing ODK data collection campaigns. It couples with [Central Frontend](https://github.com/getodk/central-frontend), an independent frontend interface, to form [ODK Central](https://github.com/getodk/central), a complete user-installable ODK server solution. While Central Frontend is the primary consumer of the ODK Central API, the API this server provides is fully public and generic: anything that can be done in the user interface can be done directly via the API. You can read on for a brief overview of the main concepts and how they fit together, or jump to one of the sections for a more in-depth description. ## API Overview To use the API to manage your data collection campaigns, you will need to **authenticate** with it, so it knows who you are and what you are allowed to do. We provide multiple methods to authenticate with the API, as well as different models for managing the identities and permissions in your system. Human staff users that manage data collection campaigns are `User`s, and mobile devices are granted access via `App User`s, and each of these account types have their own way of authenticating. But, these concepts both boil down to `Actor`s, which are how the API actually thinks about authentication and permissioning. The `/users` resource can be used to create, manage, and delete **Users**. These are the staff members who have administrative rights on your server, some projects, or both. Additional tasks like resetting a user's password are also available. You could use this API to, for example, synchronize accounts with another system or mass-provision Users. Actors (and thus Users) may be granted rights via Assignments. In short, a Roles API is available which describes the defined Roles within the system, each of which allows some set of verbs. The Assignments APIs, in turn, assign Roles to certain Actors upon certain system objects. More information on these may be found below, under [Accounts and Users](/central-api-accounts-and-users). The rest of system is made up mostly of standard REST resources and subresources, nested under and partitioned by the `/projects` Projects resource. Forms, submissions to those forms, attachments on forms or submissions, and App Users ("App Users" in the management interface), are all subresources within `/projects`. This way, each project is essentially its own sandbox which can be managed and manipulated at will. The `/projects/:id/app-users` subresource can be used to create, manage, and delete **App Users**. The `/projects/:id/forms` resource and its subresource `/projects/:id/forms/…/submissions` provide full access to create, manage, and delete **`Form`s and `Submission`s to those Forms**. Each Form is a single [ODK XForms form](https://getodk.github.io/xforms-spec/), and many Submissions (filled-out forms, also sometimes called `Instance`s) may be attached to each Form. These resources are created by sending XML in the ODK XForms format instead of JSON. One can also retrieve all the multimedia attachments associated with any submission through the `/projects/:id/forms/…/submissions/…/attachments` subresource. Forms and their submissions are also accessible through two **open standards specifications** that we follow: * The [OpenRosa](https://docs.getodk.org/openrosa/) standard allows standard integration with tools like the [ODK Collect](https://docs.getodk.org/collect-intro/) mobile data collection app, or various other compatible tools like [Enketo](https://enketo.org/). It allows them to see the forms available on the server, and to send new submissions to them. * The [OData](http://odata.org/) standard allows data to be shared between platforms for analysis and reporting. Tools like [Microsoft Power BI](https://powerbi.microsoft.com/en-us/) and [Tableau](https://public.tableau.com/en-us/s/) are examples of clients that consume the standard OData format and provide advanced features beyond what we offer. If you are looking for a straightforward JSON output of your data, or you are considering building a visualization or reporting tool, this is your best option. Projects can also contain **[`Entities`](/central-api-entity-management/)**, data objects that can be created by `Submission`s and shared between `Form`s to support workflows with multiple steps. Entities are organized into named Datasets and are managed from the `/projects/:id/datasets` resource. > ⚠️ In this API and in the related [ODK XForms specification](https://getodk.github.io/xforms-spec/entities), collections of `Entities` are referred to as `Datasets`. The term "Entity List" is used for this concept in the Central frontend UI, user documentation, and all other text intended for end users who are not developers. Finally, **system information and configuration** is available via a set of specialized resources. Currently, you may set the Usage Reporting configuration and retrieve Server Audit Logs. ## Changelog Here major and breaking changes to the API are listed by version. ## ODK Central v2024.1 **Added**: - Bulk Entity Creation! * The existing [Entity Create](/central-api-entity-management/#creating-entities) endpoint now also accepts a list of Entities to append to a Dataset. * The `uuid` property is no longer required and Central will generate a UUID for each new Entity if needed. - [Datasets (Entity Lists)](/central-api-dataset-management/#creating-datasets) and [Properties](/central-api-dataset-management/#adding-properties) can now be added via the API instead of only through Forms. - OData Data Document for requests of Submissions and Entities now allow use of `$orderby`. - ETag headers on all Blobs. **Changed**: - The [Entity Create](/central-api-entity-management/#creating-entities) endpoint will now generate a UUID if the `uuid` parameter is not provided. ## ODK Central v2023.5 **Added**: - Central now supports _Entity Updates via Submissions_ as part of our continued work on Entity-Based Data Collection! * Submissions for Entity Updates specify which properties/label to update with new values and an Entity's target `baseVersion`, which is used to track conflicts - Entities accessed via the API have additional information about conflicts (when multiple Submissions update the same Entity) * Each [Entity](/central-api-entity-management/#getting-entity-details) now has a `conflict` field, which is either: * `null`. The Entity does not have conflicting versions. * `soft`. The Entity has a version that was based on a version other than the version immediately prior to it. (The specified `baseVerson` was not the latest version on the server.) * `hard`. The Entity has a version that was based on a version other than the version immediately prior to it. Further, that version updated the same property as another update. * If an Entity has a conflict, it can be marked as resolved. After that, the conflict field will be null until a new conflicting version is received. * Each Entity Version (`currentVersion` or list of versions) has new fields `baseVersion`, `dataReceived`, and `conflictingProperties` - [Datasets](/central-api-dataset-management/#listing-datasets) extended metadata now has a `conflicts` field, which counts number of Entities currently in conflict - Entity conflicts can be resolved using the existing [PATCH](/central-api-entity-management/#updating-an-entity) endpoint, with or without new data - New `relevantToConflict` query parameter on [GET entities/:uuid/versions](/central-api-entity-management/#listing-versions) **Changed**: - Dataset entity list [entities.csv](/central-api-dataset-management/#download-dataset) can now be filtered - Entity Update [PATCH](/central-api-entity-management/#updating-an-entity) endpoint now expects `baseVersion` query parameter or `force` flag ## ODK Central v2023.4 **Added**: - [DELETE /sessions/current](/central-api-authentication/#logging-out-current-session) logs out the current session. **Changed**: - If single sign-on (SSO) with Open ID Connect (OIDC) is enabled then HTTP Basic Authentication and login with `POST /v1/session` are disabled. - [GET /v1/projects](/central-api-project-management/#listing-projects) returns list of Datasets if `?dataset=true` parameter is provided in the request. - Version number of the Entity is added to the response of [GET /projects/{projectId}/datasets/{name}/entities.csv](/central-api-dataset-management/#download-dataset) and [Entity OData feed](/central-api-odata-endpoints/#id3) ## ODK Central v2023.3 **Added**: - New endpoint [PATCH /projects/:id/datasets/:name](/central-api-dataset-management/#update-dataset-metadata) to change whether approval of Submission is required to create an Entity. - New [Entities](/central-api-entity-management) endpoints for richer Entity-Based Data Collection workflows. These endpoints provide ways of accessing Entities, as well as the ability to _create_, _update_ and _soft-delete_ Entities via the API! * New endpoint [GET /projects/:id/datasets/:name/entities](/central-api-entity-management/#entities-metadata) for listing Entities within a Dataset. * New endpoint [GET /projects/:id/datasets/:name/entities/:uuid](/central-api-entity-management/#getting-entity-details) for getting the metadata, or details, about a specific Entity. * New endpoint [GET /projects/:id/datasets/:name/entities/:uuid/versions](/central-api-entity-management/#listing-versions) for listing the versions of an Entity. * New endpoint [GET /projects/:id/datasets/:name/entities/:uuid/diffs](/central-api-entity-management/#getting-changes-between-versions) for getting the changes between versions of an Entity. * New endpoint [GET /projects/:id/datasets/:name/entities/:uuid/audits](/central-api-entity-management/#entity-audit-log) for getting the server audit logs about a specific Entity. * New endpoint [POST /projects/:id/datasets/:name/entities](/central-api-entity-management/#creating-entities) for creating an Entity from JSON. * New endpoint [PATCH /projects/:id/datasets/:name/entities/:uuid](/central-api-entity-management/#updating-an-entity) for updating the data or label of an Entity. * New endpoint [DELETE /projects/:id/datasets/:name/entities/:uuid](/central-api-entity-management/#deleting-an-entity) for soft-deleting an Entity. **Changed**: - ETag support has been added for [Download Dataset](/central-api-dataset-management/#download-dataset) and [Download Form Attachment](/central-api-form-management/#downloading-a-form-attachment). - The format of [Download Dataset](/central-api-dataset-management/#download-dataset) was changed to more closely match the OData Dataset format. - In the [OData Dataset Service](/central-api-odata-endpoints/#odata-dataset-service), `name` was removed because it is a duplication of an `__id` representing an Entity's UUID. - The `properties` returned by the [Dataset Metadata endpoint](/central-api-dataset-management/#dataset-metadata) each now include a field `odataName`, which represents the way the property name will be sanitized and outputted for OData. ## ODK Central v2023.2 **Added**: - New [OData Dataset Service](/central-api-odata-endpoints/#odata-dataset-service) for each `Dataset` that provides a list of `Entities`. **Changed**: - The response of `GET`, `POST`, `PUT` and `PATCH` methods of [Submissions](/central-api-submission-management/#listing-all-submissions-on-a-form) endpoint has been updated to include metadata of the `currentVersion` of the Submission. ## ODK Central v2023.1 **Added**: - New endpoint [GET /projects/:id/datasets/:name](/central-api-dataset-management/#dataset-metadata) to get the metadata of a Dataset **Changed**: - [GET /projects/:id/datasets](/central-api-dataset-management/#listing-datasets) now supports `X-Extended-Metadata` header to retrieve number of Entities in the Dataset and timestamp of the last Entity - `$select` in OData now supports selecting complex type(groups) - [Creating a form](/central-api-form-management/#creating-a-new-form) can now return workflow warnings **Removed**: - Scheduled backups to Google Drive are no longer supported. As a result, backups are no longer configurable. It is no longer possible to get or terminate a backups configuration or to use a backups configuration to GET a Direct Backup. For more information about these changes, please see [this topic](https://forum.getodk.org/t/backups-to-google-drive-from-central-will-stop-working-after-jan-31st/38895) in the ODK Forum. ## ODK Central v2022.3 **Added**: * Introducing [Datasets](/central-api-dataset-management) as the first step of Entity-Based Data Collection! Future versions of Central will build on these new concepts. We consider this functionality experimental and subject to change in the next release. * Forms can now create Datasets in the project, see [Creating a New Form](/central-api-form-management/#creating-a-new-form) and the [ODK XForms specification](https://getodk.github.io/xforms-spec) for details. * New endpoint [GET /projects/:id/datasets](/central-api-dataset-management/#listing-datasets) for listing Datasets of a project. * New endpoint [GET /projects/:id/datasets/:name/entities.csv](/central-api-dataset-management/#download-dataset) to download the Dataset as a CSV file. * New endpoints for [Related Datasets](/central-api-form-management/#related-datasets) to see the Datasets affected by published and unpublished Forms. * New endpoint [PATCH .../attachments/:name](/central-api-form-management/#linking-a-dataset-to-a-draft-form-attachment) to link/unlink a Dataset to a Form Attachment. * OData Data Document requests now allow limited use of `$select`. **Changed**: * The following endpoints have changed with the addition of Datasets: * The [Extended Project](/central-api-project-management/#listing-projects) endpoint now returns the `datasets` count for the Project. * The [Extended Form](/central-api-form-management/#list-all-forms) endpoint now returns the `entityRelated` flag if the form defines a Dataset schema. * [DELETE .../draft/attachments/:name](/central-api-form-management/#clearing-a-draft-form-attachment) will unlink the Dataset if there's a Dataset link to the attachment. * [GET .../draft/attachments/:filename](/central-api-form-management/#downloading-a-form-attachment) will return the Dataset as a CSV file if the attachment is linked to a Dataset. * [GET .../draft/attachments](/central-api-form-management/#listing-expected-draft-form-attachments) returns two additional flags `blobExists` and `datasetExists`. * In the [OpenRosa Form Manifest](/central-api-form-management/#openrosa-form-manifest-api), if a Form Attachment is linked to a Dataset then the value of `hash` is the MD5 of the last updated timestamp or the MD5 of `1970-01-01 00:00:00` if the Dataset is empty. ## ODK Central v1.5.3 **Removed**: * It is no longer possible to initiate a new backups configuration (`POST /v1/config/backups/initiate`) or to verify one (`POST /v1/config/backups/verify`). However, for now, if there is an existing configuration, it is still possible to get it or terminate it. If the existing configuration is terminated, it will not be possible to set up a new configuration. Note that it is still possible to download a [Direct Backup](/central-api-system-endpoints/#direct-backup). For more information about this change, please see [this topic](https://forum.getodk.org/t/backups-to-google-drive-from-central-will-stop-working-after-jan-31st/38895) in the ODK Forum. ## ODK Central v1.5 ODK Central v1.5 adds editable Project descriptions as well as more detailed information about Forms and Submissions when listing Projects. **Added**: * New `description` field returned for each [Project](/central-api-project-management/#projects) that can be set or updated through `POST`/`PATCH`/`PUT` on `/projects/…` * Note that for the `PUT` request, the Project's description must be included in the request. [Read more](/central-api-project-management/#deep-updating-project-and-form-details). * [Form extended metadata](/central-api-form-management/#getting-form-details) now includes a `reviewStates` object of counts of Submissions with specific review states. * e.g. `{"received":12, "hasIssues":2, "edited":3}` * New `?forms=true` option on [Project Listing](/central-api-project-management/#listing-projects) that includes a `formList` field containing a list of extended Forms (and the review state counts described above) associated with that Project. ## ODK Central v1.4 ODK Central v1.4 enables additional CSV export options and creates an API-manageable 30 day permanent purge system for deleted Forms. Previously, deleted Forms were made inaccessible but the data was not purged from the database. **Added**: * New `?groupPaths` and `?splitSelectMultiples` options on [CSV export paths](/central-api-submission-management/#exporting-form-submissions-to-csv) which aim to replicate ODK Briefcase export behavior. One simplifies nested path names and the other breaks select multiple options out into multiple columns. * New `?deletedFields` option on [CSV export](/central-api-submission-management/#exporting-form-submissions-to-csv) which exports all previously known and deleted fields and data on the form. * Deleted Forms (either by API `DELETE` or through the web interface) are now placed in a 30 day hold, after which an automated process will permanently delete all data related to the Form. * You can see Forms in the 30 day wait by [listing Forms with `?deleted=true`](/central-api-form-management/#list-all-forms). You can also see them in the Trash section on the web interface. * `POST /projects/…/forms/…/restore` to restore a Form that hasn't yet been permanently purged. * Additional metadata field 'formVersion' on [CSV export](/central-api-submission-management/#exporting-form-submissions-to-csv), [OData feed](/central-api-odata-endpoints/#data-document), and [extended Submission Version request](/central-api-submission-management/#listing-versions) which reports the version of the Form the Submission was _originally_ created with. * Additional metadata fields `userAgent` and `deviceId` tracked and returned for each [Submission Version](/central-api-submission-management/#listing-versions). * These are collected automatically upon submission through transmitted client metadata information, similar to the existing `deviceId` field returned with each Submission. ## ODK Central v1.3 ODK Central v1.3 adds granular Submission edit history, as well as opt-in usage reporting to the Central team. **Added**: * `GET /projects/…/forms/…/submissions/…/diffs` will return the [changes between each version](/central-api-submission-management/#getting-changes-between-versions) of a Submission. * You can set the [Usage Reporting configuration](/central-api-system-endpoints/#usage-reporting-configuration) to choose whether the server will share anonymous usage data with the Central team. By default, no usage information will be sent at all. * You can also [preview the Usage Report](/central-api-system-endpoints/#usage-report-preview) to see exactly what information would be sent in a Usage Report. **Changed**: * Additional actions are now logged in the [Server Audit Log](/central-api-system-endpoints/#server-audit-logs): * A `user.session.create` action will be logged when a User [logs in using Session Authentication](/central-api-authentication/#logging-in). * A `form.submissions.export` action will be logged when a User exports Form Submissions to CSV. * The Submission update timestamp is now included in OData (as `__system/updatedAt`). Resources that accept the `$filter` query parameter can be filered on `__system/updatedAt`. * All groups are now included in OData, even if they are not relevant. For more information, see [this post](https://forum.getodk.org/t/include-non-relevant-groups-and-fields-in-odk-central-api-responses/33536) in the ODK Forum. * The `Content-Disposition` header now specifies the `filename*` parameter, allowing filenames to contain Unicode. ### ODK Central v1.2 ODK Central v1.2 adds submission editing, review states, and commenting. **Added**: * `POST /projects/…/submission` now accepts ecosystem-compatible submission updates over OpenRosa, using the `deprecatedID`. * REST-friendly submission updates by `PUT`ing XML directly to the submission resource path. * `GET /projects/…/forms/…/submissions/…/edit` will now redirect the authenticated user (after some thought) to an Enketo-powered webform for editing the submission. * There is now a subresource `/projects/…/forms/…/submissions/…/versions` to get all versions of a submission, and details about each one, including submitted media files. * There is now a subresource `/projects/…/forms/…/submissions/…/comments` which allows very simple comment creation (`POST`) and listing (`GET`) on a submission. * Submissions now have a `reviewState` property which can be updated via `PATCH /projects/…/forms/…/submissions`. * You can now provide `X-Action-Notes` on any API request that might generate audit logs, to leave a note on those log entries. * `GET /projects/…/forms/…/submissions/…/audits` will return just audit logs pertaining to that submission. * OData queries may now request `?expand=*` to request all nested data structures inline. Only `*` is accepted. * OData `$filter` queries may now reference the new `__system/reviewState` metadata field. * There is now a [data download path](/central-api-odata-endpoints/#data-download-path) you can direct users to which eases media file access. * Submissions now have an `instanceName` field which reflects the `` tag on the submitted XML. * The REST submission endpoint now accepts optional `?deviceID=` just like the OpenRosa submission endpoint. **Changed**: * Unpublished Forms (Forms that only have a Draft and have never been published) will now appear with full details in `GET /projects/…/forms`. Previously, values like `name` would be `null` for these Forms. You can still identify unpublished Forms as they will have a `publishedAt` value of `null`. * Date and Boolean OData types are now given as date and boolean rather than text. * Broke Forms and Submissions section apart into two below. This may break some links. ## ODK Central v1.1 ODK Central v1.1 adds minor new features to the API. **Added**: * `POST`/`GET /backup`, will immediately perform a backup of the database and return the encrypted backup. * `POST`/`GET /projects/…/forms/…/submissions.csv`, which allows download of the root table (excluding repeat data) as CSV, without a zipfile. * `POST`/`GET /projects/…/forms/…/submissions.csv.zip` now allows `?attachments=false` to exclude attachments. * OData Data Document requests now allow limited use of `$filter`. * The various `submissions.csv.*` endpoints also allow `$filter`, using the same limited OData syntax. * `GET /projects/…/forms/…/submissions/submitters` which returns submitter Actors for a given Form. **Fixed**: * Documented the `deviceId` property of submission, which was added in version 0.4. ## ODK Central v1.0 ODK Central v1.0 adds Public Links to the API, and makes one minor breaking change. **Added**: * The new [Public Link](/central-api-form-management/#public-access-links) resource lets you create Public Access Links, granting anonymous browser-based access to submit to your Forms using Enketo. **Changed**: * The non-extended App User response no longer includes a `createdBy` numeric ID. To retrieve the creator of an App User, request the extended response. * We no longer reject the request if multiple authentication schemes are presented, and instead document the priority order of the different schemes [here](/central-api-authentication). ## ODK Central v0.9 ODK Central v0.9 does not change the API except for one minor breaking change. **Changed**: * The [OpenRosa Form Listing API](/central-api-openrosa-endpoints/#openrosa-form-listing-api) has been modified to always require authentication. If a valid Actor is authenticated at all, a form list will always be returned, filtered by what that Actor is allowed to access. ## ODK Central v0.8 ODK Central v0.8 introduces Draft Forms, publishing, and archived Form versions, which has a significant breaking impact on the existing API. The changes should be straightforward to adapt to, however. If you are currently creating Forms with `POST /projects/…/forms`, you may wish to add `?publish=true` to skip the Draft state and mimic the old behaviour. If you are using the API to push Form Attachments onto Forms, you'll only be able to do so now in draft state, at `/projects/…/forms/…/draft/attachments`. **Added**: * Draft Forms and publishing, and archived Form versions. * This includes [a subresource](/central-api-form-management/#draft-form) at `/projects/…/forms/…/draft`, * and [another](/central-api-form-management/#published-form-versions) at `/projects/…/forms/…/versions`, * and a [new collection of OpenRosa endpoints](/central-api-openrosa-endpoints/#draft-testing-endpoints), under `/test/…/projects/…/forms/…/draft`, for submitting test submissions to the draft version of the form. * `GET /projects/…/forms/…/fields`, which replaces `GET /projects/…/forms/….schema.json`. * App User responses now include the `projectId` they are bound to. **Changed**: * As part of the Draft Forms change, the read/write endpoints for Form Attachments have been moved to the Draft Form state and subresource, at `/projects/…/forms/…/draft/attachments`. **Removed**: * `GET /projects/…/forms/….schema.json` has been removed in favor of `GET /projects/…/forms/…/fields`. **Fixed**: * Documented `GET /projects/…/forms/….xls(x)`, which was added in 0.7. ## ODK Central v0.7 **Added**: * Form-specific [Assignments resource](/central-api-form-management/#form-assignments) at `projects/…/forms/…/assignments`, allowing granular role assignments on a per-Form basis. * Relatedly, the [OpenRosa Form Listing API](/central-api-openrosa-endpoints/#openrosa-form-listing-api) no longer rejects requests outright based on authentication. Rather, it will only return Forms that the authenticated user is allowed to view. * A [new summary API](/central-api-project-management/#seeing-all-form-assignments-within-a-project) `GET /projects/…/assignments/forms` which returns all assignments on all Forms within a Project, so you don't have to request this information separately for each Form. * `PUT /projects/:id`, which while complex allows you to update many Forms' states and assignments with a single transactional request. * `POST /projects/…/forms` now allows upload of `.xls` and `.xlsx` XLSForm files. The correct MIME type must be given. * `GET /users/?q` will now always return user details given an exact match for an email, even for users who cannot `user.list`. The request must still be authenticate as a valid Actor. This allows non-Administrators to choose a user for an action (eg grant rights) without allowing full search. **Changed**: * Newly created App Users are no longer automatically granted download and submission access to all Forms within their Project. You will want to use the [Form Assignments resource](/central-api-form-management/#form-assignments) to explicitly grant `app-user` role access to the Forms they should be allowed to see. **Fixed**: * Correctly documented `keyId` property on Projects. ## ODK Central v0.6 **Added**: * `GET /audits` Server Audit Log retrieval resource. * Project Managed Encryption: * `POST /projects/…/key` to enable project managed encryption. * Both submission intake methods (OpenRosa and REST) now support encrypted submissions. * `GET /projects/…/forms/…/submissions/keys` to get a list of encryption keys needed to decrypt all submitted data. * `?{keyId}={passphrase}` option on `GET /projects/…/forms/…/submissions.csv.zip` to get a decrypted archive given the `passphrase`. * `POST /projects/…/forms/…/submissions.csv.zip` to provide a browser-secure (no querystring) method of accessing the above `GET .csv.zip` resource. * OData and `.csv.zip` data responses now contain an additional `status` system column. * Form resource data now includes `projectId` and 'keyId'. * `?odata=true` option on `GET /projects/…/forms/….schema.json` to sanitize the field names to match the way they will be outputted for OData. **Changed**: * `GET /projects/…/forms/…/attachments` now always returns `updatedAt`. There is no longer a separate Extended Metadata response for this resource. * The Submission response format now provides the submitter ID at `submitterId` rather than `submitter`. This is so that the Extended responses for Submissions can use `submitter` to provide the full Actor subobject rather than replacing it. This brings the response format to be more similar to the other Extended formats. * OData resources now namespace the `__system` schema information under `org.opendatakit.submission` rather than alongside user metadata (`org.opendatakit.user.*`). The actual returned data has not changed; this is purely a metadata document change. **Removed**: * The Extended responses for Forms and Submissions no longer include an `xml` property. To retrieve Form or Submission XML, use the dedicated endpoints for [Form XML](/central-api-form-management/#retrieving-form-xml) and [Submission XML](/central-api-submission-management/#retrieving-submission-xml). ## ODK Central v0.5 **Added**: * Roles and Assignments resources at `/roles`, `/assignments`, and `/projects/…/assignments`. * Optional `?q=` querystring parameter on Users `GET` listing, for searching users. * Extended `GET /users/current`: added `verbs` list of verbs the authenticated Actor may perform server-wide. * Extended Project `GET`: added `appUsers` count of App Users and `verbs` list of verbs the authenticated Actor may perform upon/within the Project. * User `DELETE`. * Projects now have an `archived` flag which may be set to clear a Project out of the way without deleting it. **Changed**: * **Removed** autopromotion of Users to Administrator upon creation (`POST`). Roles must be assigned separately and explicitly. * **Changed** Project Listing (`GET /projects`) to never reject based on authentication; instead it filters the response based on the access of the authenticated Actor. * **Changed** `xmlFormId`/`version` conflict errors on `POST`ing a new Form from a `400` code to a `409` code. * **Changed** all remaining textual references to "Field Keys" to "App Users" in the documentation. **Fixed**: * Corrected Actor documentation to match reality: **removed** `meta` field and added `type` field. * Corrected Extended Form documentation: **added** `createdBy` field. * Corrected Backup Config documentation. It was almost entirely wrong. * Added Submission POST REST documentation. ## ODK Central v0.4 **Added**: * Projects resource at `/projects`. * Submission XML resource fetch at `GET /projects/…/forms/…/submissions/….xml`. * Submission attachment management over REST, at the `/attachments` subresource within Submissions. **Changed**: * **Renamed** all `/field-keys` routes to `/app-users`. * **Moved** all Forms, Submissions, and App User resources under Projects (e.g. `/forms/simple` would now be something like `/projects/1/forms/simple`). * **Changed** `GET` Form to not return Form XML. The Extended Metadata version of those requests will give the XML. * **Changed** both OpenRosa and REST Submission creation processes to create and accept only the attachment filenames that are indicated to exist by the Submission XML. * **Changed** `GET` Submission Attachemnts listing to return an array of objects containing attachment details rather than an array of filename strings. version: "" servers: - url: / tags: - name: Authentication description: |- In ODK Central, the server thinks about identity and permissioning in terms of one core concept: the `Actor`. No matter how you authenticate with the API, you are doing so as an Actor of some kind or another, and when permissions are assigned and checked, they are done against the authenticated Actor. In practice, there are two types of Actors available in the system today: * `User`s are accounts used by the staff members who manage the server and the data collection campaigns. They each have a set of rights assigned to them via Roles and Assignments. They are the only account types that have passwords associated with them. They also always have an email address. Users can authenticate using **Session Bearer Tokens** or using **HTTPS Basic** authentication. * `App User`s are only allowed to access the OpenRosa parts of the API: in essence, they are allowed to list forms, download form definitions, and create new submissions against those forms. They can only authenticate using **App User URL**s. Next, you will find documentation on each of the three authentication methods described above. It is best not to present multiple credentials. If you do, the first _presented_ scheme out of `/key` token, Bearer, Basic, then Cookie will be used for the request. If the multiple schemes are sent at once, and the first matching scheme fails, the request will be immediately rejected. **Note:** If Single Sign-on with Open ID Connect is enabled on the ODK Central, you can neither use HTTP Basic Authentication nor login with `POST /v1/session` endpoint. - name: Accounts and Users description: |- Today, there are two types of accounts: `Users`, which are the administrative accounts held by staff members managing the data collection process, and `App Users`, which are restricted access keys granted per Form within a Project to data collection clients in the field. Although both of these entities are backed by `Actor`s as we explain in the [Authentication section](/central-api-authentication) above, there is not yet any way to directly create or manipulate an Actor. Today, you can only create, manage, and delete Users and App Users. Actors (and thus Users) may be granted rights via Roles. The `/roles` Roles API is open for all to access, which describes all defined roles on the server. Getting information for an individual role from that same API will reveal which verbs are associated with each role: some role might allow only `submission.create` and `submission.update`, for example. Right now, there are four predefined system roles: Administrator (`admin`), Project Manager (`manager`), Data Collector (`formfill`), and App User (`app-user`). Administrators are allowed to perform any action upon the server, while Project Managers are allowed to perform any action upon the projects they are assigned to manage. Data Collectors can see all Forms in a Project and submit to them, but cannot see Submissions and cannot edit Form settings. Similarly, App Users are granted minimal rights: they can read Form data and create new Submissions on those Forms. While Data Collectors can perform these actions directly on the Central administration website by logging in, App Users can only do these things through Collect or a similar data collection client device. The Roles API alone does not, however, tell you which Actors have been assigned with Roles upon which system objects. For that, you will need to consult the various Assignments resources. There are two, one under the API root (`/v1/assignments`), which manages assignments to the entire system, and another nested under each Project (`/v1/projects/…/assignments`) which manage assignments to that Project. - name: Project Management description: Apart from staff users ("Web Users" in the Central management interface) and some site-wide configuration details like Usage Reporting, all of ODK Central's objects (Forms, Submissions, App Users) are partitioned by Project, and available only as subresources below the main Projects resource. - name: Form Management description: |- `Form`s are the heart of ODK. They are created out of XML documents in the [ODK XForms](https://getodk.github.io/xforms-spec/) specification format. The [Intro to Forms](https://docs.getodk.org/form-design-intro/) on the ODK Documentation website is a good resource if you are unsure what this means. Once created, Forms can be retrieved in a variety of ways, their state can be managed, and they can be deleted. These subsections cover only the modern RESTful API resources involving Forms. For documentation on the OpenRosa `formList` endpoint (which can be used to list Forms), see that section below. - name: Submission Management description: |- `Submission`s are filled-out forms (also called `Instance`s in some other ODK documentation). Each is associated with a particular Form (and in many cases with a particular _version_ of a Form), and is also created out of a standard XML format based on the Form itself. Submissions can be sent with many accompanying multimedia attachments, such as photos taken in the course of the survey. Once created, the Submissions themselves as well as their attachments can be retrieved through this API. These subsections cover only the modern RESTful API resources involving Submissions. For documentation on the OpenRosa submission endpoint (which can be used to submit Submissions), or the OData endpoint (which can be used to retrieve and query submission data), see those sections below. > Like Forms, Submissions can have versions. Each Form has an overall `xmlFormId` that represents the Form as a whole, and each version has a `version` that identifies that particular version. Often, when fetching data by the `xmlFormId` alone, information from the latest Form version is included in the response. > Similarly with Submissions, the `instanceId` each Submission is first submitted with will always represent that Submission as a whole. Each version of the Submission, though, has its own `instanceId`. Sometimes, but not very often, when getting information about the Submission by only its overall `instanceId`, information from the latest Submission version is included in the response. - name: Dataset Management description: |- _(introduced: version 2022.3)_ > ⚠️ In this API and in the related [ODK XForms specification](https://getodk.github.io/xforms-spec/entities), collections of `Entities` are referred to as `Datasets`. The term "Entity List" is used for this concept in the Central frontend UI, user documentation, and all other text intended for end users who are not developers. A Dataset is a named collection of [Entities](/central-api-entity-management/) that have the same properties. A Dataset can be linked to Forms as Attachments. This will make it available to clients as an automatically-updating CSV. **Related APIs:** - [Implicit creation of Datasets via Forms](/central-api-form-management/#creating-a-new-form) - [Link a Dataset to a Form Attachment](/central-api-form-management/#linking-a-dataset-to-a-draft-form-attachment) - [Get a Form's Related Datasets](/central-api-form-management/#related-datasets) - name: Entity Management description: |- _(introduced: version 2023.3)_ > ⚠️ In this API and in the related [ODK XForms specification](https://getodk.github.io/xforms-spec/entities), collections of `Entities` are referred to as `Datasets`. The term "Entity List" is used for this concept in the Central frontend UI, user facing documentation, and all other text intended for end users who are not developers. Entities are data objects that can be shared between Forms to support workflows with multiple steps. They can be created either through form design or through this API. A collection of `Entities` is a [Dataset](/central-api-dataset-management/). - name: OpenRosa Endpoints description: |- [OpenRosa](https://bitbucket.org/javarosa/javarosa/wiki/OpenRosaAPI) is an API standard which accompanies the ODK XForms XML standard, allowing compliant servers and clients to use a common protocol to communicate `Form`s and `Submission`s to each other. When survey clients like ODK Collect and Enketo submit Submission data to a Form, this is the API they use. ODK Central is _not_ a fully compliant OpenRosa server. OpenRosa requires compliance with five major components: 1. [**Metadata Schema**](https://bitbucket.org/javarosa/javarosa/wiki/OpenRosaMetaDataSchema), which defines a standard way to include metadata like the survey device ID and survey duration with a Submission. ODK Central will accept and return this data, but does nothing special with anything besides the `instanceId` at this time. 2. [**HTTP Request API**](https://bitbucket.org/javarosa/javarosa/wiki/OpenRosaRequest), which defines a set of requirements every OpenRosa request and response must follow. ODK Central is fully compliant with this component, except that we do _not_ require the `Date` header. 3. [**Form Submission API**](https://bitbucket.org/javarosa/javarosa/wiki/FormSubmissionAPI), which defines how Submissions are submitted to the server. ODK Central is fully compliant with this component. 4. [**Authentication API**](https://bitbucket.org/javarosa/javarosa/wiki/AuthenticationAPI), which defines how users authenticate with the server. ODK Central provides [three authentication methods](/central-api-authentication). One of these is HTTPS Basic Authentication, which is recommended by the OpenRosa specification. However, because [we do not follow the try/retry pattern](/central-api-authentication/#using-basic-authentication) required by the OpenRosa and the RFC specification, ODK Central is _not compliant_ with this component. Our recommendation generally is to use [App User Authentication](/central-api-authentication/#app-user-authentication) when submitting data from survey clients. 5. [**Form Discovery (Listing) API**](https://bitbucket.org/javarosa/javarosa/wiki/FormListAPI), which returns a listing of Forms available for survey clients to download and submit to. At this time, ODK Central is _partially compliant_ with this component: the server will return a correctly formatted `formList` response, but it does not currently handle the optional filter parameters. In practical usage, ODK survey clients like Collect will interact with Central in three places: * The OpenRosa Form Listing API, [documented below](/central-api-openrosa-endpoints/#openrosa-form-listing-api), lists the Forms the client can retrieve. * The [Form XML download](/central-api-form-management/#retrieving-form-xml) endpoint, a part of the standard REST API for Forms, is linked in the Form Listing response and allows clients to then download the ODK XForms XML for each form. * The OpenRosa Submission API, [documented below](/central-api-openrosa-endpoints/#openrosa-form-submission-api), allows survey clients to submit new Submissions to any Form. The Form Listing and Submission APIs are partitioned by Project, and their URLs are nested under the Project in question as a result. When you List or Submit, you will only be able to get forms from and submit submissions to that particular Project at a time. Where the **HTTP Request API** OpenRosa standards specification requires two headers for any request, Central requires only one: * `X-OpenRosa-Version` **must** be set to exactly `1.0` or the request will be rejected. * But Central does not require a `Date` header field. You may set it if you wish, but it will have no effect on Central. - name: OData Endpoints description: |- [OData](http://www.odata.org/) is a standard for sharing data and its schema between web services. It allows for interoperability with tools like Excel, Power BI or Tableau. If you want to use your data in a service that does not support the OData standard but does support JSON data sources, you can use the [data document](/central-api-odata-endpoints/#data-document) directly. ODK Central implements the [4.0 Minimal Conformance level](http://docs.oasis-open.org/odata/odata/v4.01/cs01/part1-protocol/odata-v4.01-cs01-part1-protocol.html#_Toc505771292) of the specification. Our goal is to enable data analysis and reporting through powerful third-party tools, sending them the data over OData, rather than attempt to create our own analysis tools. Our implementation primarily targets [Microsoft Power BI](https://docs.microsoft.com/en-us/power-bi/desktop-connect-odata) and [Tableau](https://onlinehelp.tableau.com/current/pro/desktop/en-us/examples_odata.html), two tools with reasonably robust free offerings that provide versatile analysis and visualization of data. While OData itself supports data of any sort of structure, Power BI and Tableau both think in terms of relational tables. Our current solution for representing ODK's `repeat` structures in OData is to treat every `repeat` in the `Form` definition as its own relational table, and we compute stable join IDs to relate the tables together. In general, the OData standard protocol consists of three API endpoints: * The **Service Document** describes the available resources in the service. We provide one of these for every `Form` in the system. As of version 2023.2, we also provide one for every `Dataset`. * The **Metadata Document** defines the data schema using [an XML-based standard](https://docs.oasis-open.org/odata/odata-csdl-xml/v4.01/odata-csdl-xml-v4.01.html#sec_Introduction). It is linked in every OData response. * The **data documents**, linked from the Service Document, are a simple JSON representation of the Submission or Entity data, conforming to the schema we describe in our Metadata Document. - name: System Endpoints description: There are some resources available for getting or setting system information and configuration. You can set the [Usage Reporting configuration](/central-api-system-endpoints/#usage-reporting-configuration) for the server, retrieve the [Server Audit Logs](/central-api-system-endpoints/#server-audit-logs), or perform a [Direct Backup](/central-api-system-endpoints/#direct-backup). - name: Encryption description: |- ODK Central supports two types of encryption: 1. The [old methodology](https://docs.getodk.org/encrypted-forms/), where you generate an RSA keypair and use it with locally-downloaded encrypted data to decrypt submissions. We refer to these sorts of keys in this documentation as "self-supplied keys." 2. Managed Encryption, where Central will generate and store an RSA keypair for you, secured under a passphrase that Central does not save. The CSV export path can then decrypt all records on the fly given the passphrase. Given the self-supplied key case, Central does not understand how to decrypt records, and the CSV export will export only metadata fields (and no binary attachments) for encrypted records. You may retrieve each data resource over the REST API and decrypt them yourself, or use ODK Briefcase to do this. Managed Encryption is recommended for most people. The data is still encrypted "at rest" on the server, and the private key needed to decrypt the data is itself encrypted by the passphrase. Neither the passphrase nor the decrypted private key are ever stored; they are forgotten as soon as the server has finished the work at hand. The relevant API operations are documented inline above; here we guide you through what exists from a high level. To invoke Project Manage Encryption, you may use the web management interface, or you may [POST /projects/…/key](/central-api-project-management/#enabling-project-managed-encryption). To list all the encryption keys associated with the submissions on a given form, you can [GET /projects/…/forms/…/submissions/keys](/central-api-submission-management/#listing-encryption-keys). This is particularly useful for obtaining the integer numeric ID associated with each key, which will be necessary to decrypt the records, as well as for obtaining reminder hints about each passphrase. To perform decryption, you can [GET or POST /projects/…/forms/…/submissions.csv.zip](/central-api-submission-management/#exporting-form-submissions-to-csv) with extra parameters to provide the necessary passphrases. If you are building a browser-based application, it is recommended that you `POST` rather than `GET`: please see the notes in the linked sections for additional details. Note that the OData JSON API does not (presently) decrypt data. Any encrypted submissions will be returned only with basic metadata, like submission date and user. - name: Session Authentication x-parent-tag: Authentication description: |- This is the authentication method used by the ODK Central Frontend packaged with Central Backend. Only `User`s can authenticate this way. It consists mostly of two steps: 1. **Logging in**: presenting an Email Address and a Password for verification, after which a new `Session` is created. Associated with the Session is an expiration and a bearer token. Sessions expire 24 hours after they are created. 2. **Using the session**: each request to the API needs a header attached to it: `Authorization: Bearer {token}`. This authenticates that particular request as belonging to the Session we created by logging in. You might notice that Step 2 greatly resembles how OAuth 2.0 works. This was an intentional first step towards OAuth support, and should make the forward migration of your code easier down the road. - name: HTTPS Basic Authentication x-parent-tag: Authentication description: |- Standard HTTP Basic Authentication is allowed, but **strongly discouraged**. This is because the server must verify your password with every single request, which is very slow to compute: typically, this will add hundreds of milliseconds to each request. For some one-off tasks and in cases where there is no other choice, it is reasonable to choose Basic authentication, but wherever possible we strongly encourage the use of any other authentication method. In addition, because credentials are sent in plaintext as part of the request, **the server will only accept Basic auth over HTTPS**. If your ODK Central server is set up over plain HTTP, it will not accept Basic auth. - name: App User Authentication x-parent-tag: Authentication description: |- App Users are only allowed to list and download forms, and upload new submissions to those forms. Primarily, this is to allow clients like ODK Collect to use the OpenRosa API (`/formList` and `/submission`), but any action in this API reference falling into those categories will be allowed. Revoking an App User is same as deleting session token. You can do this by calling [DELETE /sessions/{appUser}](/central-api-authentication/#logging-out-current-session). - name: Users x-parent-tag: Accounts and Users description: |- Presently, it is possible to create and list `User`s in the system, as well as to perform password reset operations. In future versions of this API it will be possible to manage existing user information and delete accounts as well. - name: App Users x-parent-tag: Accounts and Users description: |- App Users may only be created, fetched, and manipulated within the nested Projects subresource, as App Users themselves are limited to the Project in which they are created. Through the `App User`s API, you can create, list, and delete the App Users of any given Project. Because they have extremely limited permissions, App Users cannot manage themselves; only `User`s may access this API. For more information about the `/projects` containing resource, please see the following section. - name: Roles x-parent-tag: Accounts and Users description: |- _(introduced: version 0.5)_ The Roles API lists and describes each known Role within the system. Right now, Roles may not be created or customized via the API, but this will likely change in the future. Each Role contains information about the verbs it allows its assignees to perform. Some Roles have a system name associated with them; the Roles may always be referenced by this system name in request URLs, and system Roles are always read-only. - name: Assignments x-parent-tag: Accounts and Users description: |- _(introduced: version 0.5)_ There are multiple Assignments resources. This one, upon the API root (`/v1/assignments`), manages Role assignment to the entire system (e.g. if you are assigned a Role that gives you `form.create`, you may create a form anywhere on the entire server). The [Project Assignments resource](/central-api-project-management/#project-assignments), nested under Projects, manages Role assignment to that Project in particular, and all objects within it. And the [Form Assignments resource](/central-api-form-management/#form-assignments) allows even more granular assignments, to specific Forms within a Project. All of these resources have the same structure and take and return the same data types. Assignments may be created (`POST`) and deleted (`DELETE`) like any other resource in the system. Here, creating an Assignment grants the referenced Actor the verbs associated with the referenced Role upon all system objects. The pathing for creation and deletion is not quite REST-standard: we represent the relationship between Role and Actor directly in the URL rather than as body data: `assignments/{role}/{actor}` represents the assignment of the given Role to the given Actor. - name: Projects x-parent-tag: Project Management description: |- _(introduced: version 0.4)_ You must create a containing Project before you can create any of its subobjects. - name: Project Assignments x-parent-tag: Project Management description: |- _(introduced: version 0.5)_ There are multiple Assignments resources. This one, specific to the Project it is nested within, only governs Role assignments to that Project. Assigning an Actor a Role that grants, for example, a verb `submission.create`, allows that Actor to create a submission anywhere within this Project. It is also possible to assign rights only to specific forms for actions related only to that form and its submissions: see the [Form Assignments resource](/central-api-form-management/#form-assignments) for information about this. The [sitewide Assignments resource](/central-api-accounts-and-users/#assignments), at the API root, manages Role assignments for all objects across the server. Apart from this difference in scope, the introduction to that section contains information useful for understanding the following endpoints. There are only one set of Roles, applicable to either scenario. There are not a separate set of Roles used only upon Projects or Forms. - name: Forms x-parent-tag: Form Management description: |- In this API, `Form`s are distinguished by their [`formId`](https://getodk.github.io/xforms-spec/#primary-instance)s, which are a part of the XForms XML that defines each Form. In fact, as you will see below, many of the properties of a Form are extracted automatically from the XML: `hash`, `name`, `version`, as well as the `formId` itself (which to reduce confusion internally is known as `xmlFormId` in ODK Central). The only other property Forms currently have is `state`, which can be used to control whether Forms show up in mobile clients like ODK Collect for download, as well as whether they accept new `Submission`s or not. It is not yet possible to modify a Form's XML definition once it is created. - name: Individual Form x-parent-tag: Form Management - name: Draft Form x-parent-tag: Form Management description: |- _(introduced: version 0.8)_ Draft Forms allow you to test and fix issues with Forms before they are finalized and presented to data collectors. They make this process easier, as Draft Forms can be created and discarded without consequence: your Drafts will not count against the overall Form schema, nor against the set of unique `version` strings for the Form. You can create or replace the current Draft Form at any time by `POST`ing to the `/draft` subresource on the Form, and you can publish the current Draft by `POST`ing to `/draft/publish`. When a Draft Form is created, a Draft Token is also created for it, which can be found in Draft Form responses at `draftToken`. This token allows you to [submit test Submissions to the Draft Form](/central-api-submission-management/#creating-a-submission) through clients like Collect. If the Draft is published or deleted, the token will be deactivated. But if you replace the Draft without first deleting it, the existing Draft Token will be carried forward, so that you do not have to reconfigure your device. - name: Published Form Versions x-parent-tag: Form Management description: |- All published versions of a Form are available read-only at the `/versions` subresource for reference, including the currently published version. You may read that version and its details, retrieve the Form definition, and any attachments associated with each version. - name: Form Assignments x-parent-tag: Form Management description: |- _(introduced: version 0.7)_ There are multiple Assignments resources. This one, specific to the Form it is nested within, only governs Role assignments to that Form. Assigning an Actor a Role that grants, for example, a verb `submission.create`, allows that Actor to create a submission to this Form alone. It is also possible to assign umbrella rights to a whole Project and therefore all Forms within it: see the [Project Assignments resource](/central-api-project-management/#project-assignments) for information about this. The [sitewide Assignments resource](/central-api-accounts-and-users/#assignments), at the API root, manages Role assignments for all objects across the server. Apart from this difference in scope, the introduction to that section contains information useful for understanding the following endpoints. There are only one set of Roles, applicable to either scenario. There are not a separate set of Roles used only upon Projects or Forms. - name: Public Access Links x-parent-tag: Form Management description: |- _(introduced: version 1.0)_ Anybody in possession of a Public Access Link for a Form can use that link to submit data to that Form. Public Links are useful for collecting direct responses from a broad set of respondents, and can be revoked using the administration website or the API at any time. The API for Public Links is particularly useful, as it can be used to, for example, programmatically create and send individually customized and controlled links for direct distribution. The user-facing link for a Public Link has the following structure: `/-/{enketoId}?st={token}` where `-` is the Enketo root, `enketoId` is the survey ID of this published Form on Enketo and `token` is a session token to identify this Public Link. To revoke the access of any Link, terminate its session `token` by issuing [`DELETE /sessions/:token`](/central-api-authentication/#logging-out-current-session). - name: Related Datasets x-parent-tag: Form Management description: |- _(introduced: version 2022.3)_ Datasets are created and updated through Forms. Dataset-related Forms follow [the entities sub-spec](https://getodk.github.io/xforms-spec/entities) of the ODK XForms specification that allow them to define a Dataset and a mapping of Form Fields to Dataset Properties. Submissions from such a Form can create Entities within the Dataset defined in the Form. Currently, Datasets and Dataset Properties are purely additive. Multiple Forms can add Properties to the same Dataset and multiple Forms can create Entities in the same Dataset. Not all Properties of a Dataset have to be included in a Form for that Dataset. For example, one Form publishing to a Dataset called `trees` could add `location` and `species`, while another could add `species` and `circumference`. The Properties of the Dataset would be the union of Properties from all Forms for that Dataset (`location`, `species`, `circumference`). Note that it is not necessary that a Form will save to all Properties of a Dataset, so the endpoint also returns a `inForm` flag for each property which is true only if the Form affects that Property. The following endpoints return the Dataset(s) that Submissions of that Form will populate. They also return all of the Entity Properties for each Dataset and indicate which ones are mapped to Fields in the specified Form. - name: Submissions x-parent-tag: Submission Management description: |- `Submission`s are available as a subresource under `Form`s. So, for instance, `/v1/projects/1/forms/myForm/submissions` refers only to the Submissions that have been submitted to the Form `myForm`. Once created (which, like with Forms, is done by way of their XML data rather than a JSON description), it is possible to retrieve and export Submissions in a number of ways, as well as to access the multimedia `Attachment`s associated with each Submission. - name: Comments x-parent-tag: Submission Management description: |- _(introduced: version 1.2)_ This API is likely to change in the future. In version 1.2 we have added comments to submissions, so changes and problems with the data can be discussed. It's very likely we will want comments in more places in the future, and at that time a more complete comments API will be introduced, and this current one may be changed or deprecated entirely. Currently, it is not possible to get a specific comment's details, or to edit or delete a comment once it has been made. - name: Attachments x-parent-tag: Submission Management description: |- When a `Submission` is created, either over the OpenRosa or the REST interface, its XML data is analyzed to determine which file attachments it references: these may be photos or video taken as part of the survey, or an audit/timing log, among other things. Each reference is an expected attachment, and these expectations are recorded permanently alongside the Submission. With this subresource, you can list the expected attachments, see whether the server actually has a copy or not, and download, upload, re-upload, or clear binary data for any particular attachment. - name: Submission Versions x-parent-tag: Submission Management description: |- _(introduced: version 1.2)_ The `instanceId` that is submitted with the initial version of the submission is used permanently to reference that submission logically, which is to say the initial submission and all its subsequent versions. Each subsequent version will also provide its own `instanceId`. This `instanceId` becomes that particular version's identifier. So if you submit a submission with `one` and then update it, deprecating `one` for version `two`, then the full route for version `one` is `/v1/projects/…/forms/…/submissions/one/versions/one`, and for `two` it is `/v1/projects/…/forms/…/submissions/one/versions/two`. As of version 1.4, a `deviceId` and `userAgent` will also be returned with each submission. For each submission of a version, the submitting client device may transmit these extra metadata. If it does, those fields will be recognized and returned here for reference. - name: Draft Submissions x-parent-tag: Submission Management description: |- All [Draft Forms](/central-api-form-management/#draft-form) feature a `/submissions` subresource (`/draft/submissions`), which is identical to the same subresource on the form itself. These submissions exist only as long as the Draft Form does: they are removed if the Draft Form is published, and they are abandoned if the Draft Form is deleted or overwritten. Here we list all those resources again just for completeness. - name: Draft Testing Endpoints x-parent-tag: OpenRosa Endpoints description: |- _(introduced: version 0.8)_ To facilitate testing, there is an alternative collection of OpenRosa endpoints that will give access to the draft version of a form and allow submitting test submissions to it. If you are using User or App User authentication, you can use the following resources without the `/test/{token}` prefix with your existing authentication. Otherwise, and in particular if you plan to test your form in Collect or another OpenRosa-compliant client, you will likely want to use the `/test` Draft Token prefix. It functions similarly to the standard OpenRosa support, with App User authentication, but instead of a `/key` route prefix they feature a `/test` route prefix, and they point directly at each form (example: `/test/lSpA…EjR7/projects/1/forms/myform/draft`). You can get the appropriate Draft Token for any given draft by [requesting the Draft Form](/central-api-form-management/#getting-draft-form-details). The `/test` tokens are not actual App Users, and Central does not keep track of user identity when they are used. With the `/test` prefix, the following resources are available: - name: OData Form Service x-parent-tag: OData Endpoints description: |- ODK Central presents one OData service for every `Form` it knows about. To access the OData service, add `.svc` to the resource URL for the given Form. - name: OData Dataset Service x-parent-tag: OData Endpoints description: |- ODK Central presents one OData service for every `Dataset` as a way to get an OData feed of `Entities`. To access the OData service, add `.svc` to the resource URL for the given Dataset. - name: Draft Testing x-parent-tag: OData Endpoints description: |- _(introduced: version 0.8)_ To facilitate testing, there is an alternative collection of OData endpoints that will give access to the submissions uploaded to a Draft Form. This can be useful for ensuring that changes to your form do not break downstream dashboards or applications. They are all identical to the non-Draft OData endpoints, but they will only return the Draft Form schema and Submissions. - name: Usage Reporting Configuration x-parent-tag: System Endpoints description: |- _(introduced: version 1.3)_ - name: Usage Report Preview x-parent-tag: System Endpoints description: |- _(introduced: version 1.3)_ An Administrator of Central may opt in to sending periodic reports summarizing usage. Configuration of this reporting is described [here](/central-api-system-endpoints/#usage-reporting-configuration). For added transparency, the API provides a preview of the reported metrics. - name: Server Audit Logs x-parent-tag: System Endpoints description: |- _(introduced: version 0.6)_ Many actions on ODK Central will automatically log an event to the Server Audit Log. Creating a new Form, for instance, will log a `form.create` event, with information about the Actor who performed the action, and sometimes some additional details specific to the event. Any time an audit action is logged, the request headers are checked. If `X-Action-Notes` are provided anywhere, those notes will be logged into the audit entries as well. Note that some requests generate multiple audit entries; in these cases, the `note` will be attached to every entry logged. Server Audit Logs entries are created for the following `action`s: * `user.create` when a new User is created. * `user.update` when User information is updated, like email or password. * `user.assignment.create` when a User is assigned to a Server Role. * `user.assignment.delete` when a User is unassigned from a Server Role. * `user.session.create` when a User logs in. * `user.delete` when a User is deleted. * `project.create` when a new Project is created. * `project.update` when top-level Project information is updated, like its name. * `project.delete` when a Project is deleted. * `form.create` when a new Form is created. * `form.update` when top-level Form information is updated, like its name or state. * `form.update.draft.set` when a Draft Form definition is set. * `form.update.draft.delete` when a Draft Form definition is deleted. * `form.update.publish` when a Draft Form is published to the Form. * `form.attachment.update` when a Form Attachment binary is set or cleared. * `form.submissions.export` when a Form's Submissions are exported to CSV. * `form.delete` when a Form is deleted. * `form.restore` when a Form that was deleted is restored. * `form.purge` when a Form is permanently purged. * `field_key.create` when a new App User is created. * `field_key.assignment.create` when an App User is assigned to a Server Role. * `field_key.assignment.delete` when an App User is unassigned from a Server Role. * `field_key.session.end` when an App User's access is revoked. * `field_key.delete` when an App User is deleted. * `public_link.create` when a new Public Link is created. * `public_link.assignment.create` when a Public Link is assigned to a Server Role. * `public_link.assignment.delete` when a Public Link is unassigned from a Server Role. * `public_link.session.end` when a Public Link's access is revoked. * `public_link.delete` when a Public Link is deleted. * `submission.create` when a new Submission is created. * `submission.update` when a Submission's metadata is updated. * `submission.update.version` when a Submission XML data is updated. * `submission.attachment.update` when a Submission Attachment binary is set or cleared, but _only via the REST API_. Attachments created alongside the submission over the OpenRosa `/submission` API (including submissions from Collect) do not generate audit log entries. * `dataset.create` when a Dataset is created. * `dataset.update` when a Dataset is updated. * `dataset.update.publish` when a Dataset is published. * `entity.create` when an Entity is created. * `entity.error` when there is an error processing a Submission to create or update an Entity. * `entity.update.version` when an Entity is updated. * `entity.update.resolve` when an Entity conflict is resolved. * `entity.delete` when an Entity is deleted. * `config.set` when a system configuration is set. * `analytics` when a Usage Report is attempted. * Deprecated: `backup` when a backup operation is attempted for Google Drive backups. - name: Direct Backup x-parent-tag: System Endpoints description: |- _(introduced: version 1.1)_ ODK Central offers an HTTP endpoint that will immediately perform a backup on the system database and send that encrypted backup as the response. To use it, `POST` with an encryption passphrase. Note that performing the backup takes a great deal of time, during which the request will be held open. As a result, the endpoint will trickle junk data every five seconds while that processing is occurring to prevent the request from timing out. Depending on how much data you have, it can take many minutes for the data stream to speed up to a full transfer rate. paths: /v1/sessions: post: tags: - Session Authentication summary: Logging in description: |- In order to log a `User` in to a new `Session`, you must provide their credentials, in JSON format. For security reasons, the only possible results are success or failure. No detail is provided upon failure. Successful responses will come with an HTTP-Only, Secure-Only cookie. This cookie is primarily meant for use by the Central frontend, and we do not recommend relying upon it. It will only work on `GET` requests, and it will only work over HTTPS. operationId: Logging in requestBody: content: 'application/json': schema: required: - email - password type: object properties: email: type: string description: The `User`'s full email address. example: my.email.address@getodk.org password: type: string description: The `User`'s password. example: my.super.secure.password required: false responses: 200: description: OK content: application/json: schema: required: - createdAt - expiresAt - token type: object properties: createdAt: type: string description: ISO date format expiresAt: type: string description: ISO date format token: type: string description: The bearer token associated with the session. It consists only of URL-safe characters, so it should never need any escaping. example: createdAt: 2018-04-18T03:04:51.695Z expiresAt: 2018-04-19T03:04:51.695Z token: lSpAIeksRu1CNZs7!qjAot2T17dPzkrw9B4iTtpj7OoIJBmXvnHM8z8Ka4QPEjR7 401: description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error401' /v1/example1: get: tags: - Session Authentication summary: Using the session description: |- Once you have logged in, to use your session token to authenticate with any action, supply it in a request header `Authorization` with a value of `Bearer {token}`, as seen here. _(There is not really anything at `/v1/example1`; this section only demonstrates how generally to use Session Bearer Token Authentication.)_ operationId: Session Authentication parameters: - name: Authorization in: header description: Bearer encoding of the credentials required: true schema: type: string example: Bearer lSpAIeksRu1CNZs7!qjAot2T17dPzkrw9B4iTtpj7OoIJBmXvnHM8z8Ka4QPEjR7 responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Success' /v1/example2: get: tags: - HTTPS Basic Authentication summary: Using Basic Authentication description: |- To use HTTPS Basic Authentication, attach an `Authorization` header formatted so: `Authorization: Basic bXkuZW1haWwuYWRkcmVzc0BvcGVuZGF0YWtpdC5vcmc6bXkucGFzc3dvcmQ=` As given by [the standard](https://en.wikipedia.org/wiki/Basic_access_authentication), the text following the `Basic` marker here is a base64 encoding of the credentials, provided in the form `email:password` (in this example `my.email.address@getodk.org:my.password`). Unlike the standard, we do not require the client to first send an unauthenticated request and retry the request only after receiving a `WWW-Authenticate` response, and in fact we will never send the `WWW-Authenticate` header. This is mostly because, as noted above, we generally discourage the use of this authentication method, and would rather not advertise its use openly. As a result, if you wish to use Basic Authentication, directly supply the header on any request that needs it. _(There is not really anything at `/v1/example2`; this section only demonstrates how generally to use Basic Authentication.)_ operationId: Using Basic Authentication parameters: - name: Authorization in: header description: Base64 encoding of the credentials required: true schema: type: string example: Basic bXkuZW1haWwuYWRkcmVzc0BvcGVuZGF0YWtpdC5vcmc6bXkucGFzc3dvcmQ= responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Success' /v1/key/{appUser}/example3: get: tags: - App User Authentication summary: Using App User Authentication description: |- To use App User Authentication, first obtain a App User, typically by using the configuration panel in the user interface, or else by using the [App User API Resource](/central-api-accounts-and-users/#app-users). Once you have the token, you can apply it to any eligible action by prefixing the URL with `/key/{appUser}` as follows: `/v1/key/!Ms7V3$Zdnd63j5HFacIPFEvFAuwNqTUZW$AsVOmaQFf$vIC!F8dJjdgiDnJXXOt/example/request/path` _(There is not really anything at `/v1/example3`; this section only demonstrates how generally to use App User Authentication.)_ operationId: Using App User Authentication parameters: - name: appUser in: path description: The App User token. As with Session Bearer tokens, these tokens only contain URL-safe characters, so no escaping is required. required: true schema: type: string example: '!Ms7V3$Zdnd63j5HFacIPFEvFAuwNqTUZW$AsVOmaQFf$vIC!F8dJjdgiDnJXXOt' responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Success' /v1/sessions/{token}: delete: tags: - Session Authentication summary: Logging out / Revoking an App User description: |- Logging out is not strictly necessary for Web Users; all sessions expire 24 hours after they are created. But it can be a good idea, in case someone else manages to steal your token. It is also the way Public Link and App User access are revoked. To do so, issue a `DELETE` request to that token resource. **Revoking an App User** The token associated with a App User is actually just its Session Token. As a result, although a App User Token can uniquely be used as a URL prefix as described here, the session associated with it can be revoked in exactly the same way a session is logged out, by issuing a `DELETE` request to its Session resource. Note, however, that a App User cannot revoke itself; a `User` must perform this action. operationId: Revoking an App User parameters: - name: token in: path description: The session bearer token, obtained at login time. required: true schema: type: string example: lSpAIeksRu1CNZs7!qjAot2T17dPzkrw9B4iTtpj7OoIJBmXvnHM8z8Ka4QPEjR7 responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Success' 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/sessions/current: delete: tags: - Session Authentication summary: Logging out current session description: |- This endpoint causes the current session to log itself out. Logging out is not strictly necessary for Web Users; all sessions expire 24 hours after they are created. But it can be a good idea, in case someone else manages to steal your token. Only the session that was used to authenticate the request is logged out. If the Actor associated with the session has other sessions as well, those are not logged out. operationId: Logging out current session responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Success' 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/users: get: tags: - Users summary: Listing all Users description: |- Currently, there are no paging or filtering options, so listing `User`s will get you every User in the system, every time. Optionally, a `q` querystring parameter may be provided to filter the returned users by any given string. The search is performed via a [trigram similarity index](https://www.postgresql.org/docs/14/pgtrgm.html) over both the Email and Display Name fields, and results are ordered by match score, best matches first. Note that short search terms (less than 4 or 5 characters) may not return any results. Try a longer search if nothing is appearing. If a `q` parameter is given, and it exactly matches an email address that exists in the system, that user's details will always be returned, even for actors who cannot `user.list`. The request must still authenticate as a valid Actor. This allows non-Administrators to choose a user for an action (eg grant rights) without allowing full search. Actors who cannot `user.list` will always receive `[]` with a `200 OK` response. operationId: Listing all Users parameters: - name: q in: query description: An optional search parameter. schema: type: string example: alice responses: 200: description: OK content: application/json: schema: type: array items: $ref: '#/components/schemas/User' example: - createdAt: 2018-04-18T23:19:14.802Z displayName: My Display Name id: 115 type: user updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z email: my.email.address@getodk.org 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' post: tags: - Users summary: Creating a new User description: |- All that is required to create a new user is an email address. That email address will receive a message instructing the new user on how to claim their new account and set a password. Optionally, a password may also be supplied as a part of this request. If it is, the account is immediately usable with the given credentials. However, an email will still be dispatched with claim instructions as above. Users are not able to do anything upon creation besides log in and change their own profile information. To allow Users to perform useful actions, you will need to [assign them one or more Roles](/central-api-accounts-and-users/#assignments). operationId: Creating a new User requestBody: content: '*/*': schema: required: - email type: object properties: email: type: string description: The email address of the User account to be created. password: type: string description: If provided, the User account will be created with this password. Otherwise, the user will still be able set their own password later. example: email: my.email.address@getodk.org required: false responses: 200: description: OK content: application/json: schema: required: - createdAt - displayName - email - id - type type: object properties: createdAt: type: string description: ISO date format displayName: type: string description: All `Actor`s, regardless of type, have a display name id: type: number type: type: string description: the Type of this Actor; typically this will be `user`. enum: - user - field_key - public_link - singleUse updatedAt: type: string description: ISO date format deletedAt: type: string description: ISO date format email: type: string description: Only `User`s have email addresses associated with them example: createdAt: 2018-04-18T23:19:14.802Z displayName: My Display Name id: 115 type: user updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z email: my.email.address@getodk.org 400: description: Bad Request content: application/json: schema: required: - code type: object properties: code: type: string details: type: object properties: {} description: a subobject that contains programmatically readable details about this error message: type: string example: code: "400" message: Could not parse the given data (2 chars) as json. 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' x-codegen-request-body-name: body /v1/users/{actorId}: get: tags: - Users summary: Getting User details description: |- Typically, you supply the integer ID to get information about the user associated with that id. It is also possible to supply the text `current` instead of an integer ID; please see the following endpoint for documentation about this. operationId: Getting User details parameters: - name: actorId in: path description: Typically the integer ID of the `User`. For getting user details, you can also supply the text `current`, which will tell you about the currently authenticated user. required: true schema: type: string example: "42" responses: 200: description: OK content: application/json: schema: required: - createdAt - displayName - email - id - type type: object properties: createdAt: type: string description: ISO date format displayName: type: string description: All `Actor`s, regardless of type, have a display name id: type: number type: type: string description: the Type of this Actor; typically this will be `user`. enum: - user - field_key - public_link - singleUse updatedAt: type: string description: ISO date format deletedAt: type: string description: ISO date format email: type: string description: Only `User`s have email addresses associated with them example: createdAt: 2018-04-18T23:19:14.802Z displayName: My Display Name id: 115 type: user updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z email: my.email.address@getodk.org 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' delete: tags: - Users summary: Deleting a User description: |- Upon User deletion: * The account will be removed, * the user will be logged out of all existing sessions, * and should the user attempt to reset their password, they will receive an email informing them that their account has been removed. The User record will remain on file within the database, so that when for example information about the creator of a Form or Submission is requested, basic details are still available on file. A new User account may be created with the same email address as any deleted accounts. operationId: Deleting a User parameters: - name: actorId in: path description: Typically the integer ID of the `User`. For getting user details, you can also supply the text `current`, which will tell you about the currently authenticated user. required: true schema: type: string example: "42" responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Success' 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' patch: tags: - Users summary: Modifying a User description: |- You can `PATCH` JSON data to update User details. Not all user information is modifiable; right now, the following fields may be updated: * `displayName` sets the friendly display name the web interface uses to refer to the user. * `email` sets the email address associated with the account. When user details are updated, the `updatedAt` field will be automatically updated. operationId: Modifying a User parameters: - name: actorId in: path description: The integer ID of the `User`. required: true schema: type: string example: "42" requestBody: content: '*/*': schema: type: object properties: displayName: type: string description: The friendly display name that should be associated with this User. email: type: string description: The email address that should be associated with this User. example: displayName: New Name email: new.email.address@getodk.org required: false responses: 200: description: OK content: application/json: schema: required: - createdAt - displayName - email - id - type type: object properties: createdAt: type: string description: ISO date format displayName: type: string description: All `Actor`s, regardless of type, have a display name id: type: number type: type: string description: the Type of this Actor; typically this will be `user`. enum: - user - field_key - public_link - singleUse updatedAt: type: string description: ISO date format deletedAt: type: string description: ISO date format email: type: string description: Only `User`s have email addresses associated with them example: createdAt: 2018-04-18T23:19:14.802Z displayName: My Display Name id: 115 type: user updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z email: my.email.address@getodk.org 400: description: Bad Request content: application/json: schema: required: - code type: object properties: code: type: string details: type: object properties: {} description: a subobject that contains programmatically readable details about this error message: type: string example: code: "400" message: Could not parse the given data (2 chars) as json. 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' x-codegen-request-body-name: body /v1/users/current: get: tags: - Users summary: Getting authenticated User details description: |- Typically, you would get User details by the User's numeric Actor ID. However, if you only have a Bearer token, for example, you don't have any information about the user attached to that session, including even the ID with which to get more information. So you can instead supply the text `current` to get the user information associated with the authenticated session. If you _do_ use `current`, you may request extended metadata. Supply an `X-Extended-Metadata` header value of `true` to additionally retrieve an array of strings of the `verbs` the authenticated User/Actor is allowed to perform server-wide. operationId: Getting authenticated User details responses: 200: description: 'This is the Extended Metadata response, if requested via the appropriate header:' content: application/json: schema: type: object properties: createdAt: type: string description: ISO date format displayName: type: string description: All `Actor`s, regardless of type, have a display name id: type: number type: type: string description: the Type of this Actor; typically this will be `user`. enum: - user - field_key - public_link - singleUse updatedAt: type: string description: ISO date format deletedAt: type: string description: ISO date format email: type: string description: Only `User`s have email addresses associated with them example: createdAt: 2018-04-18T23:19:14.802Z displayName: My Display Name id: 115 type: user updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z email: my.email.address@getodk.org application/json; extended: schema: required: - createdAt - displayName - email - id - type - verbs type: object properties: createdAt: type: string description: ISO date format displayName: type: string description: All `Actor`s, regardless of type, have a display name id: type: number type: type: string description: the Type of this Actor; typically this will be `user`. enum: - user - field_key - public_link - singleUse updatedAt: type: string description: ISO date format deletedAt: type: string description: ISO date format email: type: string description: Only `User`s have email addresses associated with them verbs: type: array description: The verbs the authenticated Actor is allowed to perform server-wide. items: type: object example: createdAt: 2018-04-18T23:19:14.802Z displayName: My Display Name id: 115 type: user updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z email: my.email.address@getodk.org verbs: - project.create - project.update 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/users/{actorId}/password: put: tags: - Users summary: Directly updating a user password description: To directly update a user password, you will need to reprove the user's intention by supplying the `old` password alongside the `new`. If you simply want to initiate an email-based password reset process, see the following endpoint. operationId: Directly updating a user password parameters: - name: actorId in: path description: The integer ID of the `User`. required: true schema: type: string example: "42" requestBody: content: '*/*': schema: required: - new - old type: object properties: old: type: string description: The user's current password. new: type: string description: The new password that the user wishes to set. example: old: old.password new: new.password required: false responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Success' 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' x-codegen-request-body-name: body /v1/users/reset/initiate: post: tags: - Users summary: Initating a password reset description: |- Anybody can initate a reset of any user's password. An email will be sent with instructions on how to complete the password reset; it contains a token that is required to complete the process. The optional query parameter `invalidate` may be set to `true` to immediately invalidate the user's current password, regardless of whether they complete the reset process. This can be done if, for example, their password has been compromised. In order to do this, though, the request must be performed as an authenticated user with permission to do this. If invalidation is attempted without the proper permissions, the entire request will fail. If the email address provided does not match any user in the system, that address will still be sent an email informing them of the attempt and that no account was found. operationId: Initating a password reset parameters: - name: invalidate in: query description: Specify `true` in order to immediately invalidate the user's present password. schema: type: boolean example: "true" requestBody: content: '*/*': schema: required: - email type: object properties: email: type: string description: The email address of the User account whose password is to be reset. example: email: my.email.address@getodk.org required: false responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Success' 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' x-codegen-request-body-name: body /v1/projects/{projectId}/app-users: get: tags: - App Users summary: Listing all App Users description: |- Currently, there are no paging or filtering options, so listing `App User`s will get you every App User in the system, every time. This endpoint supports retrieving extended metadata; provide a header `X-Extended-Metadata: true` to additionally retrieve the `lastUsed` timestamp of each App User, as well as to retrieve the details of the `Actor` the App User was `createdBy`. operationId: Listing all App Users parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "7" responses: 200: description: 'This is the Extended Metadata response, if requested via the appropriate header:' content: application/json: schema: type: array items: $ref: '#/components/schemas/AppUser' example: - createdAt: 2018-04-18T23:19:14.802Z displayName: My Display Name id: 115 type: user updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z token: d1!E2GVHgpr4h9bpxxtqUJ7EVJ1Q$Dusm2RBXg8XyVJMCBCbvyE8cGacxUx3bcUT projectId: 1 lastUsed: 2018-04-14T08:34:21.633Z application/json; extended: schema: type: array description: Extended App Users items: $ref: '#/components/schemas/ExtendedAppUser' example: - createdAt: 2018-04-18T23:19:14.802Z displayName: My Display Name id: 115 type: user updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z token: d1!E2GVHgpr4h9bpxxtqUJ7EVJ1Q$Dusm2RBXg8XyVJMCBCbvyE8cGacxUx3bcUT projectId: 1 createdBy: createdAt: 2018-04-18T23:19:14.802Z displayName: My Display Name id: 115 type: user updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z lastUsed: 2018-04-14T08:34:21.633Z 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' post: tags: - App Users summary: Creating a new App User description: |- The only information required to create a new `App User` is its `displayName` (this is called "Nickname" in the administrative panel). When an App User is created, they are assigned no rights. They will be able to authenticate and list forms on a mobile client, but the form list will be empty, as the list only includes Forms that the App User has read access to. Once an App User is created, you'll likely wish to use the [Form Assignments resource](/central-api-form-management/#form-assignments) to actually assign the `app-user` role to them for the Forms you wish. operationId: Creating a new App User parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "7" requestBody: content: '*/*': schema: required: - displayName type: object properties: displayName: type: string description: The friendly nickname of the `App User` to be created. example: displayName: My Display Name required: false responses: 200: description: OK content: application/json: schema: required: - createdAt - displayName - id - projectId - type type: object properties: createdAt: type: string description: ISO date format displayName: type: string description: All `Actor`s, regardless of type, have a display name id: type: number type: type: string description: the Type of this Actor; typically this will be `user`. enum: - user - field_key - public_link - singleUse updatedAt: type: string description: ISO date format deletedAt: type: string description: ISO date format token: type: string description: If present, this is the Token that can be used to authenticate a request as this `App User`. If not present, this `App User`'s access has been revoked. projectId: type: number description: The ID of the `Project` that this `App User` is bound to. example: createdAt: 2018-04-18T23:19:14.802Z displayName: My Display Name id: 115 type: user updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z token: d1!E2GVHgpr4h9bpxxtqUJ7EVJ1Q$Dusm2RBXg8XyVJMCBCbvyE8cGacxUx3bcUT projectId: 1 400: description: Bad Request content: application/json: schema: required: - code type: object properties: code: type: string details: type: object properties: {} description: a subobject that contains programmatically readable details about this error message: type: string example: code: "400" message: Could not parse the given data (2 chars) as json. 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' x-codegen-request-body-name: body /v1/projects/{projectId}/app-users/{id}: delete: tags: - App Users summary: Deleting a App User description: |- You don't have to delete a `App User` in order to cut off its access. Using a `User`'s credentials you can simply [log the App User's session out](/central-api-authentication/#logging-out-current-session) using its token. This will end its session without actually deleting the App User, which allows you to still see it in the configuration panel and inspect its history. This is what the administrative panel does when you choose to "Revoke" the App User. That said, if you do wish to delete the App User altogether, you can do so by issuing a `DELETE` request to its resource path. App Users cannot delete themselves. operationId: Deleting a App User parameters: - name: id in: path description: The numeric ID of the App User required: true schema: type: number example: "16" - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "7" responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Success' 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/roles: get: tags: - Roles summary: Listing all Roles description: 'Currently, there are no paging or filtering options, so listing `Role`s will get you every Role in the system, every time. There are no authorization restrictions upon this endpoint: anybody is allowed to list all Role information at any time.' operationId: Listing all Roles responses: 200: description: OK content: application/json: schema: type: array items: $ref: '#/components/schemas/Role' example: - id: 4 name: Project Manager system: manager verbs: - project.update - project.delete createdAt: 2018-01-19T23:58:03.395Z updatedAt: 2018-03-21T12:45:02.312Z /v1/roles/{id}: get: tags: - Roles summary: Getting Role Details description: |- Getting an individual Role does not reveal any additional information over listing all Roles. It is, however, useful for direct lookup of a specific role: The `id` parameter for Roles here and elsewhere will accept the numeric ID associated with that Role, _or_ a `system` name if there is one associated with the Role. Thus, you may request `/v1/roles/admin` on any ODK Central server and receive information about the Administrator role. As with Role listing, there are no authorization restrictions upon this endpoint: anybody is allowed to get information about any Role at any time. operationId: Getting Role Details parameters: - name: id in: path description: Typically the integer ID of the `Role`. You may also supply the Role `system` name if it has one. required: true schema: type: string example: "1" responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Role' example: id: 4 name: Project Manager system: manager verbs: - project.update - project.delete createdAt: 2018-01-19T23:58:03.395Z updatedAt: 2018-03-21T12:45:02.312Z /v1/assignments: get: tags: - Assignments summary: Listing all Assignments description: |- This will list every server-wide assignment, in the form of `actorId`/`roleId` pairs. It will _not_ list Project-specific Assignments. To find those, you will need the [Assignments subresource](/central-api-project-management/#project-assignments) within Projects. This endpoint supports retrieving extended metadata; provide a header `X-Extended-Metadata: true` to expand the `actorId` into a full `actor` objects. The Role reference remains a numeric ID. operationId: Listing all Assignments responses: 200: description: 'This is the Extended Metadata response, if requested via the appropriate header:' content: application/json: schema: type: array items: $ref: '#/components/schemas/Assignment' example: - actorId: 115 roleId: 4 application/json; extended: schema: type: array description: Extended Assignment items: $ref: '#/components/schemas/ExtendedAssignment' example: - actor: createdAt: 2018-04-18T23:19:14.802Z displayName: My Display Name id: 115 type: user updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z roleId: 4 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/assignments/{roleId}: get: tags: - Assignments summary: Listing all Actors assigned some Role description: Given a `roleId`, which may be a numeric ID or a string role `system` name, this endpoint lists all `Actors` that have been assigned that Role on a server-wide basis. operationId: Listing all Actors assigned some Role parameters: - name: roleId in: path description: Typically the integer ID of the `Role`. You may also supply the Role `system` name if it has one. required: true schema: type: string example: admin responses: 200: description: OK content: application/json: schema: type: array items: $ref: '#/components/schemas/Actor' example: - createdAt: 2018-04-18T23:19:14.802Z displayName: My Display Name id: 115 type: user updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/assignments/{roleId}/{actorId}: post: tags: - Assignments summary: Assigning an Actor to a server-wide Role description: |- Given a `roleId`, which may be a numeric ID or a string role `system` name, and a numeric `actorId`, assigns that Role to that Actor across the entire server. No `POST` body data is required, and if provided it will be ignored. operationId: Assigning an Actor to a server-wide Role parameters: - name: roleId in: path description: Typically the integer ID of the `Role`. You may also supply the Role `system` name if it has one. required: true schema: type: string example: admin - name: actorId in: path description: The integer ID of the `Actor`. required: true schema: type: number example: "14" responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Success' 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' delete: tags: - Assignments summary: Stripping an Role Assignment from an Actor description: Given a `roleId`, which may be a numeric ID or a string role `system` name, and a numeric `actorId`, unassigns that Role from that Actor across the entire server. operationId: Stripping an Role Assignment from an Actor parameters: - name: roleId in: path description: Typically the integer ID of the `Role`. You may also supply the Role `system` name if it has one. required: true schema: type: string example: admin - name: actorId in: path description: The integer ID of the `Actor`. required: true schema: type: number example: "14" responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Success' 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects: get: tags: - Projects summary: Listing Projects description: |- The Projects listing endpoint is somewhat unique in that it is freely accessible to anybody, even unauthenticated clients. Rather than reject the user with a `403` or similar error, the Projects listing will only return Projects that the authenticated Actor is allowed to see. In most cases, this means that unauthenticated requests will receive `[]` in reply. Currently, there are no paging or filtering options, so listing `Project`s will get you every Project you have access to. This endpoint supports retrieving extended metadata; provide a header `X-Extended-Metadata: true` to additionally retrieve the `appUsers` count of App Users and `forms` count of Forms within the Project, as well as the `lastSubmission` timestamp of the latest submission to any for in the project, if any. operationId: Listing Projects parameters: - name: forms in: query description: |- _(introduced: Version 1.5)_ If set to true then endpoint also returns the Forms that the authenticated Actor is allowed to see, with those Forms nested within their corresponding Project under a new parameter `formList`. The returned Forms will match structure of Forms requested with extended metadata (including additional `lastSubmission` timestamp and `submissions` and `reviewStates` counts) schema: type: boolean example: "true" - name: datasets in: query description: |- _(introduced: Version 2023.4)_ If set to true then endpoint also returns the Datasets that the authenticated Actor is allowed to see, with those Datasets nested within their corresponding Project under a new parameter `datasetList`. The returned Datasets will match structure of Datasets requested with extended metadata (including additional `lastEntity` timestamp and `entities`) schema: type: boolean example: "true" responses: 200: description: OK content: application/json: schema: type: array description: Standard Response items: $ref: '#/components/schemas/Project' example: - id: 1 name: Default Project description: Description of this Project to show on Central. keyId: 3 archived: false application/json; extended: schema: type: array description: Extended Response items: $ref: '#/components/schemas/ExtendedProject' example: - id: 1 name: Default Project description: Description of this Project to show on Central. keyId: 3 archived: false appUsers: 4 forms: 7 lastSubmission: 2018-04-18T03:04:51.695Z datasets: 2 lastEntity: 2023-04-18T03:04:51.695Z post: tags: - Projects summary: Creating a Project description: To create a Project, the only information you must supply (via POST body) is the desired name of the Project. operationId: Creating a Project requestBody: content: '*/*': schema: required: - name type: object properties: name: type: string description: The desired name of the Project. example: name: Project Name required: false responses: 200: description: OK content: application/json: schema: required: - name type: object properties: id: type: number description: The numerical ID of the Project. name: type: string description: The name of the Project. description: type: string description: The description of the Project, which is rendered as Markdown on Frontend. keyId: type: number description: If managed encryption is enabled on the project, the numeric ID of the encryption key as tracked by Central is given here. archived: type: boolean description: Whether the Project is archived or not. `null` is equivalent to `false`. All this does is sort the Project to the bottom of the list and disable management features in the web management application. example: id: 1 name: Default Project description: Description of this Project to show on Central. keyId: 3 archived: false 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' x-codegen-request-body-name: body /v1/projects/{id}: get: tags: - Projects summary: Getting Project Details description: |- To get just the details of a single Project, `GET` its single resource route by its numeric ID. This endpoint supports retrieving extended metadata; provide a header `X-Extended-Metadata: true` to additionally retrieve the `appUsers` count of App Users and `forms` count of forms within the Project, as well as the `lastSubmission` timestamp of the latest submission to any for in the project, if any. In addition, the extended metadata version of this endpoint (but not the overall Project listing) returns an array of the `verbs` the authenticated Actor is able to perform on/within the Project. operationId: Getting Project Details parameters: - name: id in: path description: The numeric ID of the Project required: true schema: type: number example: "16" responses: 200: description: 'This is the Extended Metadata response, if requested via the appropriate header:' content: application/json: schema: type: object description: Standard Response $ref: '#/components/schemas/Project' example: id: 1 name: Default Project description: Description of this Project to show on Central. keyId: 3 archived: false application/json; extended: schema: type: object description: Extended Response $ref: '#/components/schemas/ExtendedProjectWithVerbs' example: id: 1 name: Default Project description: Description of this Project to show on Central. keyId: 3 archived: false appUsers: 4 forms: 7 lastSubmission: 2018-04-18T03:04:51.695Z datasets: 2 lastEntity: 2023-04-18T03:04:51.695Z verbs: - "form.create" - "form.delete" 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' put: tags: - Projects summary: Deep Updating Project and Form Details description: |- _(introduced: version 0.7)_ When managing a large deployment, it can be necessary to make sweeping changes to all Form States and Assignments within it at once—when rolling out a new Form, for example, or replacing a deprecated version with a new revision. For this purpose, we offer this `PUT` resource, which allows a deep update of Project metadata, Form metadata, and Form Assignment metadata at once and transactionally using a nested data format. One important mechanic to note immediately here is that we follow true `PUT` semantics, meaning that the data you provide is not merged with existing data to form an update. With our usual `PATCH` endpoints, we do this kind of merging and so data that you don't explicitly pass us is left alone. Because we allow the deletion of Form Assignments by way of omission with this API, we treat _all_ omissions as an explicit specification to null the omitted field. This means that, for example, you must always re-specify the Project name, the Project description, and archival flag with every `PUT`. This adherence to `PUT` semantics would normally imply that Forms could be created or deleted by way of this request, but such an operation could become incredibly complex. We currently return a `501 Not Implemented` error if you supply nested Form information but you do not give us exactly the entire set of extant Forms. You can inspect the Request format for this endpoint to see the exact nested data structure this endpoint accepts. Each level of increased granularity is optional: you may `PUT` just Project metadata, with no `forms` array, and you may `PUT` Project and Form metadata but omit `assignments` from any Form, in which case the omitted detail will be left as-is. operationId: Deep Updating Project and Form Details parameters: - name: id in: path description: The numeric ID of the Project required: true schema: type: number example: "16" requestBody: content: '*/*': schema: required: - name type: object properties: name: type: string description: The desired name of the Project. description: type: string description: The desired description of the Project. archived: type: boolean description: Archives the Project. forms: type: array description: If given, the Form metadata to update. items: { type: object } example: name: New Project Name description: New Project Description archived: false forms: - xmlFormId: simple state: open assignments: - roleId: 2 actorId: 14 - roleId: 2 actorId: 21 - xmlFormId: test state: closed required: false responses: 200: description: OK content: application/json: schema: required: - name type: object properties: id: type: number description: The numerical ID of the Project. name: type: string description: The name of the Project. description: type: string description: The description of the Project, which is rendered as Markdown on Frontend. keyId: type: number description: If managed encryption is enabled on the project, the numeric ID of the encryption key as tracked by Central is given here. archived: type: boolean description: Whether the Project is archived or not. `null` is equivalent to `false`. All this does is sort the Project to the bottom of the list and disable management features in the web management application. example: id: 1 name: Default Project description: Description of this Project to show on Central. keyId: 3 archived: false 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' 501: description: Not Implemented content: application/json: schema: required: - code type: object properties: code: type: string message: type: string example: code: "501.1" message: The requested feature $unsupported is not supported by this server. x-codegen-request-body-name: body delete: tags: - Projects summary: Deleting a Project description: Deleting a Project will remove it from the management interface and make it permanently inaccessible. Do not do this unless you are certain you will never need any of its data again. For now, deleting a Project will not purge its Forms. (We will change that in a future release.) operationId: Deleting a Project parameters: - name: id in: path description: The numeric ID of the Project required: true schema: type: number example: "16" responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Success' 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' patch: tags: - Projects summary: Updating Project Details description: |- The Project name may be updated, as well as the Project description and the `archived` flag. By default, `archived` is not set, which is equivalent to `false`. If `archived` is set to `true`, the Project will be sorted to the bottom of the list, and in the web management application the Project will become effectively read-only. API write access will not be affected. operationId: Updating Project Details parameters: - name: id in: path description: The numeric ID of the Project required: true schema: type: number example: "16" requestBody: content: '*/*': schema: required: - name type: object properties: name: type: string description: The desired name of the Project. description: type: string description: The description of the Project. archived: type: boolean description: Archives the Project. example: name: New Project Name description: Description of this Project to show on Central. archived: true required: false responses: 200: description: OK content: application/json: schema: required: - name type: object properties: id: type: number description: The numerical ID of the Project. name: type: string description: The name of the Project. description: type: string description: The description of the Project, which is rendered as Markdown on Frontend. keyId: type: number description: If managed encryption is enabled on the project, the numeric ID of the encryption key as tracked by Central is given here. archived: type: boolean description: Whether the Project is archived or not. `null` is equivalent to `false`. All this does is sort the Project to the bottom of the list and disable management features in the web management application. example: id: 1 name: Default Project description: Description of this Project to show on Central. keyId: 3 archived: false 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' x-codegen-request-body-name: body /v1/projects/{id}/key: post: tags: - Projects summary: Enabling Project Managed Encryption description: |- _(introduced: version 0.6)_ [Project Managed Encryption](/central-api-encryption) can be enabled via the API. To do this, `POST` with the `passphrase` and optionally a reminder `hint` about the passphrase. If managed encryption is already enabled, a `409` error response will be returned. Enabling managed encryption will modify all unencrypted forms in the project, and as a result the `version` of all forms within the project will also be modified. It is therefore best to enable managed encryption before devices are in the field. Any forms in the project that already have self-supplied encryption keys will be left alone. operationId: Enabling Project Managed Encryption parameters: - name: id in: path description: The numeric ID of the Project required: true schema: type: number example: "16" requestBody: content: '*/*': schema: required: - passphrase type: object properties: passphrase: type: string description: The encryption passphrase. If this passphrase is lost, the data will be irrecoverable. hint: type: string description: A reminder about the passphrase. This is primarily useful when multiple encryption keys and passphrases are being used, to tell them apart. example: passphrase: super duper secret hint: it was a secret required: false responses: 200: description: OK content: application/json: schema: required: - name type: object properties: id: type: number description: The numerical ID of the Project. name: type: string description: The name of the Project. description: type: string description: The description of the Project, which is rendered as Markdown on Frontend. keyId: type: number description: If managed encryption is enabled on the project, the numeric ID of the encryption key as tracked by Central is given here. archived: type: boolean description: Whether the Project is archived or not. `null` is equivalent to `false`. All this does is sort the Project to the bottom of the list and disable management features in the web management application. example: id: 1 name: Default Project description: Description of this Project to show on Central. keyId: 3 archived: false 400: description: Bad Request content: application/json: schema: required: - code type: object properties: code: type: string details: type: object properties: {} description: a subobject that contains programmatically readable details about this error message: type: string example: code: "400" message: Could not parse the given data (2 chars) as json. 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' 409: description: Conflict content: application/json: schema: required: - code type: object properties: code: type: string message: type: string example: code: "409.1" message: A resource already exists with id value(s) of 1. x-codegen-request-body-name: body /v1/projects/{projectId}/assignments: get: tags: - Project Assignments summary: Listing all Project Assignments description: |- This will list every assignment upon this Project, in the form of `actorId`/`roleId` pairs. This endpoint supports retrieving extended metadata; provide a header `X-Extended-Metadata: true` to expand the `actorId` into a full `actor` objects. The Role reference remains a numeric ID. operationId: Listing all Project Assignments parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "2" responses: 200: description: 'This is the Extended Metadata response, if requested via the appropriate header:' content: application/json: schema: type: array items: $ref: '#/components/schemas/Assignment' example: - actorId: 115 roleId: 4 application/json; extended: schema: type: array items: $ref: '#/components/schemas/ExtendedAssignment' example: - actor: createdAt: 2018-04-18T23:19:14.802Z displayName: My Display Name id: 115 type: user updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z roleId: 4 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/assignments/{roleId}: get: tags: - Project Assignments summary: Listing all Actors assigned some Project Role description: Given a `roleId`, which may be a numeric ID or a string role `system` name, this endpoint lists all `Actors` that have been assigned that Role upon this particular Project. operationId: Listing all Actors assigned some Project Role parameters: - name: roleId in: path description: Typically the integer ID of the `Role`. You may also supply the Role `system` name if it has one. required: true schema: type: string example: manager - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" responses: 200: description: OK content: application/json: schema: type: array items: $ref: '#/components/schemas/Actor' example: - createdAt: 2018-04-18T23:19:14.802Z displayName: My Display Name id: 115 type: user updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/assignments/{roleId}/{actorId}: post: tags: - Project Assignments summary: Assigning an Actor to a Project Role description: |- Given a `roleId`, which may be a numeric ID or a string role `system` name, and a numeric `actorId`, assigns that Role to that Actor for this particular Project. No `POST` body data is required, and if provided it will be ignored. operationId: Assigning an Actor to a Project Role parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: roleId in: path description: Typically the integer ID of the `Role`. You may also supply the Role `system` name if it has one. required: true schema: type: string example: manager - name: actorId in: path description: The integer ID of the `Actor`. required: true schema: type: number example: "14" responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Success' 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' delete: tags: - Project Assignments summary: Revoking a Project Role Assignment from an Actor description: Given a `roleId`, which may be a numeric ID or a string role `system` name, and a numeric `actorId`, unassigns that Role from that Actor for this particular Project. operationId: Revoking a Project Role Assignment from an Actor parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: roleId in: path description: Typically the integer ID of the `Role`. You may also supply the Role `system` name if it has one. required: true schema: type: string example: manager - name: actorId in: path description: The integer ID of the `Actor`. required: true schema: type: number example: "14" responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Success' 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/assignments/forms: get: tags: - Project Assignments summary: Seeing all Form Assignments within a Project description: |- Returns a summary of all _Form-specific_ Assignments within this Project. This endpoint is meant to simplify the task of summarizing all Form permissions within a Project at a glance and in one transactional request. Because it is necessary to specify which Form each Assignment is attached to, returned results form this endpoint include an `xmlFormId` field. This endpoint supports retrieving extended metadata; provide a header `X-Extended-Metadata: true` to expand the `actorId` into a full `actor` objects. The Role reference remains a numeric ID and the Form reference remains a string ID. operationId: Seeing all Form Assignments within a Project parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" responses: 200: description: OK content: application/json: schema: type: array items: $ref: '#/components/schemas/FormSummaryAssignment' example: - actorId: 115 xmlFormId: simple roleId: 4 application/json; extended: schema: type: array items: $ref: '#/components/schemas/ExtendedFormSummaryAssignment' example: - actor: createdAt: 2018-04-18T23:19:14.802Z displayName: My Display Name id: 115 type: user updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z xmlFormId: simple roleId: 4 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/assignments/forms/{roleId}: get: tags: - Project Assignments summary: Seeing Role-specific Form Assignments within a Project description: |- Like the [Form Assignments summary API](/central-api-form-management/#listing-all-form-assignments), but filtered by some `roleId`. This endpoint supports retrieving extended metadata; provide a header `X-Extended-Metadata: true` to expand the `actorId` into a full `actor` objects. The Role reference remains a numeric ID and the Form reference remains a string ID. operationId: Seeing Role-specific Form Assignments within a Project parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: roleId in: path description: The numeric ID of the Role required: true schema: type: number example: "16" responses: 200: description: OK content: application/json: schema: type: array items: $ref: '#/components/schemas/FormSummaryAssignment' example: - actorId: 115 xmlFormId: simple roleId: 4 application/json; extended: schema: type: array items: $ref: '#/components/schemas/ExtendedFormSummaryAssignment' example: - actor: createdAt: 2018-04-18T23:19:14.802Z displayName: My Display Name id: 115 type: user updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z xmlFormId: simple roleId: 4 403: description: Forbidden content: application/json; extended: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms: get: tags: - Forms summary: List all Forms description: |- Currently, there are no paging or filtering options, so listing `Form`s will get you every Form you are allowed to access, every time. As of version 1.2, Forms that are unpublished (that only carry a draft and have never been published) will appear with full metadata detail. Previously, certain details like `name` were omitted. You can determine that a Form is unpublished by checking the `publishedAt` value: it will be `null` for unpublished forms. This endpoint supports retrieving extended metadata; provide a header `X-Extended-Metadata: true` to additionally retrieve the `submissions` count of the number of Submissions that each Form has, the `reviewStates` object of counts of Submissions with specific review states, the `lastSubmission` most recent submission timestamp, as well as the Actor the Form was `createdBy`. operationId: List all Forms parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" responses: 200: description: OK content: application/json: schema: type: array items: $ref: '#/components/schemas/Form' example: - projectId: 1 xmlFormId: simple name: Simple version: "2.1" enketoId: abcdef hash: 51a93eab3a1974dbffc4c7913fa5a16a keyId: 3 state: open publishedAt: 2018-01-21T00:04:11.153Z createdAt: 2018-01-19T23:58:03.395Z updatedAt: 2018-03-21T12:45:02.312Z application/json; extended: schema: type: array items: $ref: '#/components/schemas/ExtendedForm' example: - projectId: 1 xmlFormId: simple name: Simple version: "2.1" enketoId: abcdef hash: 51a93eab3a1974dbffc4c7913fa5a16a keyId: 3 state: open publishedAt: 2018-01-21T00:04:11.153Z createdAt: 2018-01-19T23:58:03.395Z updatedAt: 2018-03-21T12:45:02.312Z submissions: 10 reviewStates: received: 3 hasIssues: 2 edited: 1 lastSubmission: 2018-04-18T03:04:51.695Z createdBy: createdAt: 2018-04-18T23:19:14.802Z displayName: My Display Name id: 115 type: user updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z entityRelated: false 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' post: tags: - Forms summary: Creating a new Form description: |- When creating a `Form`, the only required data is the actual XForms XML or XLSForm itself. Use it as the `POST` body with a `Content-Type` header of `application/xml` (`text/xml` works too), and the Form will be created. As of Version 0.8, Forms will by default be created in Draft state, accessible under `/projects/…/forms/…/draft`. The Form itself will not have a public XML definition, and will not appear for download onto mobile devices. You will need to [publish the form](/central-api-form-management/#publishing-a-draft-form) to finalize it for data collection. To disable this behaviour, and force the new Form to be immediately ready, you can pass the querystring option `?publish=true`. For XLSForm upload, either `.xls` or `.xlsx` are accepted. You must provide the `Content-Type` request header corresponding to the file type: `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet` for `.xlsx` files, and `application/vnd.ms-excel` for `.xls` files. You must also provide an `X-XlsForm-FormId-Fallback` request header with the `formId` you want the resulting form to have, if the spreadsheet does not already specify. This header field accepts percent-encoded values to support Unicode characters and other non-ASCII values. By default, any XLSForm conversion Warnings will fail this request and return the warnings rather than use the converted XML to create a form. To override this behaviour, provide a querystring flag `?ignoreWarnings=true`. Conversion Errors will always fail this request. The API will currently check the XML's structure in order to extract the information we need about it, but ODK Central does _not_ run comprehensive validation on the full contents of the XML to ensure compliance with the ODK specification. Future versions will likely do this, but in the meantime you will have to use a tool like [ODK Validate](https://getodk.org/use/validate/) to be sure your Forms are correct. You will get following workflow warnings while creating a new form or uploading a new version of an existing form: - Structural Change: Returned when the uploaded definition of the form removes, renames or moves a field to a different group/repeat. [Learn more](https://docs.getodk.org/central-forms/#central-forms-updates) - Deleted Form: Returned when there is a form with the same ID in the Trash. [Learn more](https://docs.getodk.org/central-forms/#deleting-a-form) **Creating Datasets with Forms** Starting from Version 2022.3, a Form can also create a Dataset by defining a Dataset schema in the Form definition (XForms XML or XLSForm). When a Form with a Dataset schema is uploaded, a Dataset and its Properties are created. The state of the Dataset is dependent on the state of the Form; you will need to publish the Form to publish the Dataset. Datasets in the Draft state are not returned in [Dataset APIs](/central-api-dataset-management), however the [Related Datasets](/central-api-form-management/#draft-form-dataset-diff) API for the Form can be called to get the Dataset and its Properties. It is possible to define the schema of a Dataset in multiple Forms. Such Forms can be created and published in any order. Publishing any of the Forms will also publish the Dataset and will generate a `dataset.create` event; `dataset.update` events are generated in Audit logs when a Form adds a new property in the Dataset. The state of a Property of a Dataset is also dependent on the state of the Form that FIRST defines that Property, which means if a Form is in the Draft state then the Properties defined by that Form will not appear in the [.csv file](/central-api-dataset-management/#download-dataset) of the Dataset. operationId: Creating a new Form parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: ignoreWarnings in: query description: Defaults to `false`. Set to `true` if you want the Form to be created even if the XLSForm conversion results in warnings. schema: type: boolean example: "false" - name: publish in: query description: Defaults to `false`. Set to `true` if you want the Form to skip the Draft state to Published. schema: type: boolean example: "false" - name: X-XlsForm-FormId-Fallback in: header description: e.g. filename.xlsx schema: type: string example: filename.xlsx responses: 200: description: OK content: application/json: schema: required: - createdAt - hash - projectId - state - version - xmlFormId type: object properties: projectId: type: number description: The `id` of the project this form belongs to. xmlFormId: type: string description: The `id` of this form as given in its XForms XML definition name: type: string description: The friendly name of this form. It is given by the `` in the XForms XML definition. version: type: string description: The `version` of this form as given in its XForms XML definition. If no `version` was specified in the Form, a blank string will be given. enketoId: type: string description: If it exists, this is the survey ID of this Form on Enketo at `/-`. This will be the ID of the published version if it exists, otherwise it will be the draft ID. Only a cookie-authenticated user may access the preview through Enketo. hash: type: string description: An MD5 sum automatically computed based on the XForms XML definition. This is required for OpenRosa compliance. keyId: type: number description: If a public encryption key is present on the form, its numeric ID as tracked by Central is given here. state: type: string description: The present lifecycle status of this form. Controls whether it is available for download on survey clients or accepts new submissions. enum: - open - closing - closed publishedAt: type: string description: Indicates when a draft has most recently been published for this Form. If this value is `null`, this Form has never been published yet, and contains only a draft. createdAt: type: string description: ISO date format updatedAt: type: string description: ISO date format example: projectId: 1 xmlFormId: simple name: Simple version: "2.1" enketoId: abcdef hash: 51a93eab3a1974dbffc4c7913fa5a16a keyId: 3 state: open publishedAt: 2018-01-21T00:04:11.153Z createdAt: 2018-01-19T23:58:03.395Z updatedAt: 2018-03-21T12:45:02.312Z 400: description: Bad Request content: application/json: schema: required: - code type: object properties: code: type: string details: type: object properties: {} description: a subobject that contains programmatically readable details about this error message: type: string example: code: "400" message: Could not parse the given data (2 chars) as json. 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' 409: description: Conflict content: application/json: schema: required: - code type: object properties: code: type: string message: type: string example: code: "409.1" message: A resource already exists with id value(s) of 1. /v1/projects/{projectId}/forms/{xmlFormId}: get: tags: - Individual Form summary: Getting Form Details description: 'This endpoint supports retrieving extended metadata; provide a header `X-Extended-Metadata: true` to additionally retrieve the `submissions` count of the number of `Submission`s that this Form has, as well as the `lastSubmission` most recent submission timestamp.' operationId: Getting Form Details parameters: - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" responses: 200: description: 'This is the Extended Metadata response, if requested via the appropriate header:' content: application/json: schema: $ref: '#/components/schemas/Form' example: - projectId: 1 xmlFormId: simple name: Simple version: "2.1" enketoId: abcdef hash: 51a93eab3a1974dbffc4c7913fa5a16a keyId: 3 state: open publishedAt: 2018-01-21T00:04:11.153Z createdAt: 2018-01-19T23:58:03.395Z updatedAt: 2018-03-21T12:45:02.312Z application/json; extended: schema: $ref: '#/components/schemas/ExtendedForm' example: projectId: 1 xmlFormId: simple name: Simple version: "2.1" enketoId: abcdef hash: 51a93eab3a1974dbffc4c7913fa5a16a keyId: 3 state: open publishedAt: 2018-01-21T00:04:11.153Z createdAt: 2018-01-19T23:58:03.395Z updatedAt: 2018-03-21T12:45:02.312Z submissions: 10 reviewStates: received: 3 hasIssues: 2 edited: 1 lastSubmission: 2018-04-18T03:04:51.695Z createdBy: createdAt: 2018-04-18T23:19:14.802Z displayName: My Display Name id: 115 type: user updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z entityRelated: false 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' delete: tags: - Individual Form summary: Deleting a Form description: When a Form is deleted, it goes into the Trash section, but it can now be restored from the Trash. After 30 days in the Trash, the Form and all of its resources and submissions will be automatically purged. If your goal is to prevent it from showing up on survey clients like ODK Collect, consider setting its `state` to `closing` or `closed` instead (see [Modifying a Form](/central-api-form-management/#modifying-a-form) just above for more details). operationId: Deleting a Form parameters: - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Success' 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' patch: tags: - Individual Form summary: Modifying a Form description: |- It is currently possible to modify only one thing about a `Form`: its `state`, which governs whether it is available for download onto survey clients and whether it accepts new `Submission`s. See the `state` Attribute in the Request documentation to the right to see the possible values and their meanings. We use `PATCH` rather than `PUT` to represent the update operation, so that you only have to supply the properties you wish to change. Anything you do not supply will remain untouched. operationId: Modifying a Form parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple requestBody: content: '*/*': schema: type: object properties: state: type: string description: If supplied, the Form lifecycle state will move to this value. enum: - open - closing - closed example: state: open required: false responses: 200: description: OK content: application/json: schema: required: - createdAt - hash - projectId - state - version - xmlFormId type: object properties: projectId: type: number description: The `id` of the project this form belongs to. xmlFormId: type: string description: The `id` of this form as given in its XForms XML definition name: type: string description: The friendly name of this form. It is given by the `<title>` in the XForms XML definition. version: type: string description: The `version` of this form as given in its XForms XML definition. If no `version` was specified in the Form, a blank string will be given. enketoId: type: string description: If it exists, this is the survey ID of this Form on Enketo at `/-`. This will be the ID of the published version if it exists, otherwise it will be the draft ID. Only a cookie-authenticated user may access the preview through Enketo. hash: type: string description: An MD5 sum automatically computed based on the XForms XML definition. This is required for OpenRosa compliance. keyId: type: number description: If a public encryption key is present on the form, its numeric ID as tracked by Central is given here. state: type: string description: The present lifecycle status of this form. Controls whether it is available for download on survey clients or accepts new submissions. enum: - open - closing - closed publishedAt: type: string description: Indicates when a draft has most recently been published for this Form. If this value is `null`, this Form has never been published yet, and contains only a draft. createdAt: type: string description: ISO date format updatedAt: type: string description: ISO date format example: projectId: 1 xmlFormId: simple name: Simple version: "2.1" enketoId: abcdef hash: 51a93eab3a1974dbffc4c7913fa5a16a keyId: 3 state: open publishedAt: 2018-01-21T00:04:11.153Z createdAt: 2018-01-19T23:58:03.395Z updatedAt: 2018-03-21T12:45:02.312Z 400: description: Bad Request content: application/json: schema: required: - code type: object properties: code: type: string details: type: object properties: {} description: a subobject that contains programmatically readable details about this error message: type: string example: code: "400" message: Could not parse the given data (2 chars) as json. 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' x-codegen-request-body-name: body /v1/projects/{projectId}/forms/{xmlFormId}.xml: get: tags: - Individual Form summary: Retrieving Form XML description: To get the XML of the `Form`, add `.xml` to the end of the request URL. operationId: Retrieving Form XML parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple responses: 200: description: OK content: application/xml: example: | <h:html xmlns="http://www.w3.org/2002/xforms" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:jr="http://openrosa.org/javarosa"> <h:head> <h:title>Simple</h:title> <model> <instance> <data id="simple" version="2.1"> <meta> <instanceID/> </meta> <name/> <age/> </data> </instance> <bind nodeset="/data/meta/instanceID" type="string" readonly="true()" calculate="concat('uuid:', uuid())"/> <bind nodeset="/data/name" type="string"/> <bind nodeset="/data/age" type="int"/> </model> </h:head> </h:body> <input ref="/data/name"> <label>What is your name?</label> </input> <input ref="/data/age"> <label>What is your age?</label> </input> </h:body> </h:html> 403: description: Forbidden content: application/xml: schema: required: - code type: object properties: code: type: string message: type: string application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}.xlsx: get: tags: - Individual Form summary: Retrieving Form XLS(X) description: If a Form was created with an Excel file (`.xls` or `.xlsx`), you can get that file back by adding `.xls` or `.xlsx` as appropriate to the Form resource path. operationId: Retrieving Form XLS(X) parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple responses: 200: description: OK content: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet: example: | (binary data) 403: description: Forbidden content: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet: schema: required: - code type: object properties: code: type: string message: type: string application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/attachments: get: tags: - Individual Form summary: Listing Form Attachments description: This endpoint allows you to fetch the list of expected attachment files, and will tell you whether the server is in possession of each file or not. To modify an attachment, you'll need to create a Draft. operationId: Listing Form Attachments parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple responses: 200: description: OK content: application/json: schema: type: array items: $ref: '#/components/schemas/FormAttachment' example: - name: myfile.mp3 type: image exists: true blobExists: true datasetExists: true updatedAt: 2018-03-21T12:45:02.312Z 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/attachments/{filename}: get: tags: - Individual Form summary: Downloading a Form Attachment description: |- To download a single file, use this endpoint. The appropriate `Content-Disposition` (attachment with a filename) and `Content-Type` (based on the type supplied at upload time) will be given. This endpoint supports `ETag`, which can be used to avoid downloading the same content more than once. When an API consumer calls this endpoint, it returns a value in `ETag` header, you can pass this value in the header `If-None-Match` of subsequent requests. If the file has not been changed since the previous request, you will receive `304 Not Modified` response otherwise you'll get the latest file. operationId: Downloading a Form Attachment parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: filename in: path description: The name of the file to download. required: true schema: type: string example: simple responses: 200: description: OK headers: Content-Disposition: schema: type: string ETag: schema: type: string description: content version identifier content: "{the MIME type of the attachment file itself}": schema: type: object example: (binary data) 304: description: Not Modified 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/fields: get: tags: - Individual Form summary: Getting Form Schema Fields description: |- _(introduced: version 0.8)_ For applications that do not rely on JavaRosa, it can be challenging to parse XForms XML into a simple schema structure. Because Central Backend already implements and performs such an operation for its own internal purposes, we also expose this utility for any downstream consumers which wish to make use of it. While this may eventually overlap with the new OData JSON CSDL specification, we are likely to maintain this API as it more closely mirrors the original XForms data types and structure. Central internally processes the XForms schema tree into a flat list of fields, and this is how the data is returned over this endpoint as well. It will always return fields in a _depth-first traversal order_ of the original `<instance>` XML block in the XForm. You may optionally add the querystring parameter `?odata=true` to sanitize the field names and paths to match the way they will be outputted for OData. While the original field names as given in the XForms definition may be used as-is for CSV output, OData has some restrictions related to the domain-qualified identifier syntax it uses. operationId: Getting Form Schema Fields parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: odata in: query description: If set to `true`, will sanitize field names. schema: type: boolean example: "false" responses: 200: description: OK content: application/json: schema: type: array example: - name: meta path: /meta type: structure - name: instanceID path: /meta/instanceID type: string - name: name path: /name type: string - name: age path: /age type: int - name: photo path: /photo type: binary binary: true items: required: - name - path - type type: object properties: name: type: string path: type: string type: type: string binary: type: boolean example: - name: meta path: /meta type: structure - name: instanceID path: /meta/instanceID type: string - name: name path: /name type: string - name: age path: /age type: int - name: photo path: /photo type: binary binary: true 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{id}/restore: post: tags: - Individual Form summary: Restoring a Form description: |- _(introduced: version 1.4)_ Deleted forms can now be restored (as long as they have been in the Trash less than 30 days and have not been purged). However, a deleted Form with the same `xmlFormId` as an active Form cannot be restored while that other Form is active. This `/restore` URL uses the numeric ID of the Form (now returned by the `/forms` endpoint) rather than the `xmlFormId` to unambigously restore. operationId: Restoring a Form parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: id in: path description: The ID (not xmlFormId) of the Form required: true schema: type: string example: simple responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Success' 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/draft: get: tags: - Draft Form summary: Getting Draft Form Details description: The response here will include standard overall Form metadata, like `xmlFormId`, in addition to the Draft-specific information. operationId: Getting Draft Form Details parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/DraftForm' 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' post: tags: - Draft Form summary: Creating a Draft Form description: |- `POST`ing here will create a new Draft Form on the given Form. For the most part, it takes the same parameters as the [Create Form request](/central-api-form-management/#creating-a-new-form): you can submit XML or Excel files, you can provide `ignoreWarnings` if you'd like. Additionally, however, you may `POST` with no `Content-Type` and an empty body to create a Draft Form with a copy of the definition (XML, XLS, etc) that is already published, if there is one. This can be useful if you don't wish to update the Form definition itself, but rather one or more Form Attachments. If your Draft form schema contains any field path which overlaps with a field path of a previous version of the Form, but with a different data type, your request will be rejected. You can rename the conflicting field, or correct it to have the same data type as it did previously. When a Draft is created, the expected Form Attachments are computed and slots are created, as with a new Form. Any attachments that match existing ones on the published Form, if it exists, will be copied over to the new Draft. Even if a Draft exists, you can always replace it by `POST`ing here again. In that case, the attachments that exist on the Draft will similarly be copied over to the new Draft. If you wish to copy from the published version instead, you can do so by first `DELETE`ing the extant Draft. Draft `version` conflicts are allowed with prior versions of a Form while in Draft state. If you attempt to [publish the Form](/central-api-form-management/#publishing-a-draft-form) without correcting the conflict, the publish operation will fail. You can request that Central update the version string on your behalf as part of the publish operation to avoid this: see that endpoint for more information. The `xmlFormId`, however, must exactly match that of the Form overall, or the request will be rejected. Starting from Version 2022.3, a Draft Form can also create or update a Dataset by defining a Dataset schema in the Form definition. The state of the Dataset and its Properties is dependent on the state of the Form, see [Creating a new form](/central-api-form-management/#creating-a-new-form) for more details. operationId: Creating a Draft Form parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: ignoreWarnings in: query description: Defaults to `false`. Set to `true` if you want the form to be created even if the XLSForm conversion results in warnings. schema: type: boolean example: "false" - name: X-XlsForm-FormId-Fallback in: header description: e.g. filename.xlsx schema: type: string example: filename.xlsx responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Success' 400: description: Bad Request content: application/json: schema: required: - code type: object properties: code: type: string details: type: object properties: {} description: a subobject that contains programmatically readable details about this error message: type: string example: code: "400" message: Could not parse the given data (2 chars) as json. 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' delete: tags: - Draft Form summary: Deleting a Draft Form description: |- Once a Draft Form is deleted, its definition and any Form Attachments associated with it will be removed. You will not be able to delete the draft if there is no published version of the form. operationId: Deleting a Draft Form parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Success' 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/draft.xml: get: tags: - Draft Form summary: Retrieving Draft Form XML description: To get the XML of the Draft Form, add `.xml` to the end of the request URL. operationId: Retrieving Draft Form XML parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple responses: 200: description: OK content: application/xml: example: | <h:html xmlns="http://www.w3.org/2002/xforms" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:jr="http://openrosa.org/javarosa"> <h:head> <h:title>Simple</h:title> <model> <instance> <data id="simple" version="2.1"> <meta> <instanceID/> </meta> <name/> <age/> </data> </instance> <bind nodeset="/data/meta/instanceID" type="string" readonly="true()" calculate="concat('uuid:', uuid())"/> <bind nodeset="/data/name" type="string"/> <bind nodeset="/data/age" type="int"/> </model> </h:head> <h:body> <input ref="/data/name"> <label>What is your name?</label> </input> <input ref="/data/age"> <label>What is your age?</label> </input> </h:body> </h:html> 403: description: Forbidden content: application/xml: schema: required: - code type: object properties: code: type: string message: type: string application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/draft.xlsx: get: tags: - Draft Form summary: Retrieving Draft Form XLS(X) description: If a Draft Form was created with an Excel file (`.xls` or `.xlsx`), you can get that file back by adding `.xls` or `.xlsx` as appropriate to the Draft Form resource path. This endpoint supports `ETag`, which can be used to avoid downloading the same content more than once. When an API consumer calls this endpoint, it returns a value in `ETag` header, you can pass this value in the header `If-None-Match` of subsequent requests. If the file has not been changed since the previous request, you will receive `304 Not Modified` response otherwise you'll get the latest file. operationId: Retrieving Draft Form XLS(X) parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple responses: 200: description: OK headers: ETag: schema: type: string description: content version identifier content: application/xml: example: | (binary data) 403: description: Forbidden content: application/xml: schema: required: - code type: object properties: code: type: string message: type: string application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/draft/attachments: get: tags: - Draft Form summary: Listing expected Draft Form Attachments description: Form Attachments for each form are automatically determined when the form is first created, by scanning the XForms definition for references to media or data files. Because of this, it is not possible to directly modify the list of form attachments; that list is fully determined by the given XForm. Instead, the focus of this API subresource is around communicating that expected list of files, and uploading binaries into those file slots. operationId: Listing expected Draft Form Attachments parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple responses: 200: description: OK content: application/json: schema: type: array items: $ref: '#/components/schemas/FormAttachment' example: - name: myfile.mp3 type: image exists: true blobExists: true datasetExists: true updatedAt: 2018-03-21T12:45:02.312Z 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/draft/attachments/{filename}: get: tags: - Draft Form summary: Downloading a Draft Form Attachment description: To download a single file, use this endpoint. The appropriate `Content-Disposition` (attachment with a filename or Dataset name) and `Content-Type` (based on the type supplied at upload time or `text/csv` in the case of a linked Dataset) will be given. This endpoint supports `ETag`, which can be used to avoid downloading the same content more than once. When an API consumer calls this endpoint, it returns a value in `ETag` header, you can pass this value in the header `If-None-Match` of subsequent requests. If the file has not been changed since the previous request, you will receive `304 Not Modified` response otherwise you'll get the latest file. operationId: Downloading a Draft Form Attachment parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: filename in: path description: The name of tha attachment. required: true schema: type: string example: people.csv responses: 200: description: OK headers: Content-Disposition: schema: type: string ETag: schema: type: string description: content version identifier content: '{the MIME type of the attachment file itself or text/csv for a Dataset}': example: | (binary data) 403: description: Forbidden content: '{the MIME type of the attachment file itself or text/csv for a Dataset}': schema: required: - code type: object properties: code: type: string message: type: string application/json: schema: $ref: '#/components/schemas/Error403' post: tags: - Draft Form summary: Uploading a Draft Form Attachment description: |- To upload a binary to an expected file slot, `POST` the binary to its endpoint. Supply a `Content-Type` MIME-type header if you have one. As of version 2022.3, if there is already a Dataset linked to this attachment, it will be unlinked and replaced with the uploaded file. operationId: Uploading a Draft Form Attachment parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: filename in: path description: The name of that attachment. required: true schema: type: string example: people.csv responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Success' 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' delete: tags: - Draft Form summary: Clearing a Draft Form Attachment description: Because Form Attachments are completely determined by the XForms definition of the form itself, there is no direct way to entirely remove a Form Attachment entry from the list, only to clear its uploaded content or to unlink the Dataset. Thus, when you issue a `DELETE` to the attachment's endpoint, that is what happens. operationId: Clearing a Draft Form Attachment parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: filename in: path description: The name of tha attachment. required: true schema: type: string example: people.csv responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Success' 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' patch: tags: - Draft Form summary: Linking a Dataset to a Draft Form Attachment description: |- _(introduced: version 2022.3)_ This endpoint can update a Form Attachment's link to a Dataset. You can use this to link or unlink a Dataset to a Form Attachment. Linking of a Dataset to the Attachment only happens if the Attachment type is `file` and there is a Dataset with the exact name of the Attachment (excluding extension `.csv`) in the Project. For example, if the Form definition includes an Attachment named `people.csv`, then it can be linked to a Dataset named `people`. Pay special attention to letter case and spaces. When linking a Dataset, if there is any existing file attached then it will be removed. operationId: Linking a Dataset to a Draft Form Attachment parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: filename in: path description: The name of the attachment. required: true schema: type: string example: people.csv requestBody: content: '*/*': schema: $ref: '#/components/schemas/PatchAttachment' required: false responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Success' 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' 404: description: Not Found content: application/json: schema: required: - code type: object properties: code: type: string message: type: string example: code: "404.1" message: Could not find the resource you were looking for. x-codegen-request-body-name: body /v1/projects/{projectId}/forms/{xmlFormId}/draft/fields: get: tags: - Draft Form summary: Getting Draft Form Schema Fields description: Identical to the [same request](/central-api-form-management/#getting-form-schema-fields) for the published Form, but will return the fields related to the current Draft version. operationId: Getting Draft Form Schema Fields parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: odata in: query description: If set to `true`, will sanitize field names. schema: type: boolean example: "false" responses: 200: description: OK content: application/json: schema: type: array example: - name: meta path: /meta type: structure - name: instanceID path: /meta/instanceID type: string - name: name path: /name type: string - name: age path: /age type: int - name: photo path: /photo type: binary binary: true items: required: - name - path - type type: object properties: name: type: string path: type: string type: type: string binary: type: boolean example: - name: meta path: /meta type: structure - name: instanceID path: /meta/instanceID type: string - name: name path: /name type: string - name: age path: /age type: int - name: photo path: /photo type: binary binary: true 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/draft/publish: post: tags: - Draft Form summary: Publishing a Draft Form description: |- This will publish your current Draft Form and make it the active Form definition (and attachments). If your Draft `version` conflicts with an older version of the Form, you will get an error. If you wish for the `version` to be set on your behalf as part of the publish operation, you can provide the new version string as a querystring parameter `?version`. Once the Draft is published, there will no longer be a Draft version of the form. Starting with Version 2022.3, publishing a Draft Form that defines a Dataset schema will also publish the Dataset. It will generate `dataset.create` event in Audit logs and make the Dataset available in [Datasets APIs](/central-api-dataset-management). If the Dataset is already published and the Form adds new properties then `dataset.update` event will be generated. operationId: Publishing a Draft Form parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: version in: query description: The `version` to be associated with the Draft once it's published. schema: type: string example: newVersion responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Success' 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' 409: description: Conflict content: application/json: schema: required: - code type: object properties: code: type: string message: type: string example: code: "409.1" message: A resource already exists with id value(s) of 1. /v1/projects/{projectId}/forms/{xmlFormId}/versions: get: tags: - Published Form Versions summary: Listing Published Form Versions description: |- Each entry of the version listing will contain some of the same duplicate keys with basic information about the Form: `xmlFormId` and `createdAt`, for example. This is done to match the data you'd receive if you'd requested each version separately. This endpoint supports retrieving extended metadata; provide a header `X-Extended-Metadata: true` to additionally retrieve the `Actor` that each version was `publishedBy`. operationId: Listing Published Form Versions parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple responses: 200: description: Ok content: application/json: schema: type: array items: $ref: '#/components/schemas/Form' example: - projectId: 1 xmlFormId: simple name: Simple version: "2.1" enketoId: abcdef hash: 51a93eab3a1974dbffc4c7913fa5a16a keyId: 3 state: open publishedAt: 2018-01-21T00:04:11.153Z createdAt: 2018-01-19T23:58:03.395Z updatedAt: 2018-03-21T12:45:02.312Z application/json; extended: schema: type: array items: $ref: '#/components/schemas/ExtendedFormVersion' example: - projectId: 1 xmlFormId: simple name: Simple version: "2.1" enketoId: abcdef hash: 51a93eab3a1974dbffc4c7913fa5a16a keyId: 3 state: open publishedAt: 2018-01-21T00:04:11.153Z createdAt: 2018-01-19T23:58:03.395Z updatedAt: 2018-03-21T12:45:02.312Z publishedBy: createdAt: 2018-04-18T23:19:14.802Z displayName: My Display Name id: 115 type: user updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z 403: description: Forbidden content: application/json; extended: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/versions/{version}: get: tags: - Published Form Versions summary: Getting Form Version Details description: Since the XForms specification allows blank strings as `version`s (and Central treats the lack of a `version` as a blank string), you may run into trouble using this resource if you have such a Form. In this case, pass the special value `___` (three underscores) as the `version` to retrieve the blank `version` version. operationId: Getting Form Version Details parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: version in: path description: The `version` of the Form version being referenced. Pass `___` to indicate a blank `version`. required: true schema: type: string example: one responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Form' 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/versions/{version}.xml: get: tags: - Published Form Versions summary: Retrieving Form Version XML description: To get the XML of the Form Version, add `.xml` to the end of the request URL. operationId: Retrieving Form Version XML parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: version in: path description: The `version` of the Form version being referenced. Pass `___` to indicate a blank `version`. required: true schema: type: string example: one responses: 200: description: OK content: application/xml: example: | <h:html xmlns="http://www.w3.org/2002/xforms" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:jr="http://openrosa.org/javarosa"> <h:head> <h:title>Simple</h:title> <model> <instance> <data id="simple" version="2.1"> <meta> <instanceID/> </meta> <name/> <age/> </data> </instance> <bind nodeset="/data/meta/instanceID" type="string" readonly="true()" calculate="concat('uuid:', uuid())"/> <bind nodeset="/data/name" type="string"/> <bind nodeset="/data/age" type="int"/> </model> </h:head> <input ref="/data/name"> <label>What is your name?</label> </input> <input ref="/data/age"> <label>What is your age?</label> </input> </h:body> </h:html> 403: description: Forbidden content: application/xml: schema: required: - code type: object properties: code: type: string message: type: string application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/versions/{version}.xlsx: get: tags: - Published Form Versions summary: Retrieving Form Version XLS(X) description: If a Form Version was created with an Excel file (`.xls` or `.xlsx`), you can get that file back by adding `.xls` or `.xlsx` as appropriate to the Form Version resource path. This endpoint supports `ETag` header, which can be used to avoid downloading the same content more than once. When an API consumer calls this endpoint, the endpoint returns a value in `ETag` header. If you pass that value in the `If-None-Match` header of a subsequent request, then if the file has not been changed since the previous request, you will receive `304 Not Modified` response; otherwise you'll get the latest file. operationId: Retrieving Form Version XLS(X) parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: version in: path description: The `version` of the Form version being referenced. Pass `___` to indicate a blank `version`. required: true schema: type: string example: one responses: 200: description: OK headers: ETag: schema: type: string description: content version identifier content: application/xml: example: | (binary data) 403: description: Forbidden content: application/xml: schema: required: - code type: object properties: code: type: string message: type: string application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/versions/{version}/attachments: get: tags: - Published Form Versions summary: Listing Form Version Attachments description: Attachments are specific to each version of a Form. You can retrieve the attachments associated with a given version here. operationId: Listing Form Version Attachments parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: version in: path description: The `version` of the Form version being referenced. Pass `___` to indicate a blank `version`. required: true schema: type: string example: one responses: 200: description: OK content: application/json: schema: type: array items: $ref: '#/components/schemas/FormAttachment' example: - name: myfile.mp3 type: image exists: true blobExists: true datasetExists: true updatedAt: 2018-03-21T12:45:02.312Z 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/versions/{version}/attachments/{filename}: get: tags: - Published Form Versions summary: Downloading a Form Version Attachment description: |- To download a single file, use this endpoint. The appropriate `Content-Disposition` (attachment with a filename) and `Content-Type` (based on the type supplied at upload time) will be given. This endpoint supports `ETag` header, which can be used to avoid downloading the same content more than once. When an API consumer calls this endpoint, the endpoint returns a value in `ETag` header. If you pass that value in the `If-None-Match` header of a subsequent request, then if the file has not been changed since the previous request, you will receive `304 Not Modified` response; otherwise you'll get the latest file. operationId: Downloading a Form Version Attachment parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: version in: path description: The `version` of the Form version being referenced. Pass `___` to indicate a blank `version`. required: true schema: type: string example: one - name: filename in: path description: The name of tha attachment. required: true schema: type: string example: people.csv responses: 200: description: OK headers: Content-Disposition: schema: type: string ETag: schema: type: string description: content version identifier content: "{the MIME type of the attachment file itself}": schema: type: object example: (binary data) 304: description: Not Modified 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/versions/{version}/fields: get: tags: - Published Form Versions summary: Getting Form Version Schema Fields description: Identical to the [same request](/central-api-form-management/#getting-form-schema-fields) for the published Form, but will return the fields related to the specified version. operationId: Getting Form Version Schema Fields parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: version in: path description: The `version` of the Form version being referenced. Pass `___` to indicate a blank `version`. required: true schema: type: string example: one - name: odata in: query description: If set to `true`, will sanitize field names. schema: type: boolean example: "false" responses: 200: description: OK content: application/json: schema: type: array example: - name: meta path: /meta type: structure - name: instanceID path: /meta/instanceID type: string - name: name path: /name type: string - name: age path: /age type: int - name: photo path: /photo type: binary binary: true items: required: - name - path - type type: object properties: name: type: string path: type: string type: type: string binary: type: boolean example: - name: meta path: /meta type: structure - name: instanceID path: /meta/instanceID type: string - name: name path: /name type: string - name: age path: /age type: int - name: photo path: /photo type: binary binary: true 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/assignments: get: tags: - Form Assignments summary: Listing all Form Assignments description: |- This will list every assignment upon this Form, in the form of `actorId`/`roleId` pairs. This endpoint supports retrieving extended metadata; provide a header `X-Extended-Metadata: true` to expand the `actorId` into a full `actor` objects. The Role reference remains a numeric ID. operationId: Listing all Form Assignments parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "2" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple responses: 200: description: 'This is the Extended Metadata response, if requested via the appropriate header:' content: application/json: schema: type: array items: $ref: '#/components/schemas/Assignment' example: - actorId: 115 roleId: 4 application/json; extended: schema: type: array items: $ref: '#/components/schemas/ExtendedAssignment' example: - actor: createdAt: 2018-04-18T23:19:14.802Z displayName: My Display Name id: 115 type: user updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z roleId: 4 403: description: Forbidden content: application/json; extended: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/assignments/{roleId}: get: tags: - Form Assignments summary: Listing all Actors assigned some Form Role description: Given a `roleId`, which may be a numeric ID or a string role `system` name, this endpoint lists all `Actors` that have been assigned that Role upon this particular Form. operationId: Listing all Actors assigned some Form Role parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: roleId in: path description: Typically the integer ID of the `Role`. You may also supply the Role `system` name if it has one. required: true schema: type: string example: manager responses: 200: description: OK content: application/json: schema: type: array items: $ref: '#/components/schemas/Actor' example: - createdAt: 2018-04-18T23:19:14.802Z displayName: My Display Name id: 115 type: user updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/assignments/{roleId}/{actorId}: post: tags: - Form Assignments summary: Assigning an Actor to a Form Role description: |- Given a `roleId`, which may be a numeric ID or a string role `system` name, and a numeric `actorId`, assigns that Role to that Actor for this particular Form. No `POST` body data is required, and if provided it will be ignored. operationId: Assigning an Actor to a Form Role parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: roleId in: path description: Typically the integer ID of the `Role`. You may also supply the Role `system` name if it has one. required: true schema: type: string example: manager - name: actorId in: path description: The integer ID of the `Actor`. required: true schema: type: number example: "14" responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Success' 403: description: Forbidden content: {} delete: tags: - Form Assignments summary: Revoking a Form Role Assignment from an Actor description: Given a `roleId`, which may be a numeric ID or a string role `system` name, and a numeric `actorId`, unassigns that Role from that Actor for this particular Form. operationId: Revoking a Form Role Assignment from an Actor parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: roleId in: path description: Typically the integer ID of the `Role`. You may also supply the Role `system` name if it has one. required: true schema: type: string example: manager - name: actorId in: path description: The integer ID of the `Actor`. required: true schema: type: number example: "14" responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Success' 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/public-links: get: tags: - Public Access Links summary: Listing all Links description: |- This will list every Public Access Link upon this Form. This endpoint supports retrieving extended metadata; provide a header `X-Extended-Metadata: true` to retrieve the Actor the Link was `createdBy`. operationId: Listing all Links parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "2" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple responses: 200: description: 'This is the Extended Metadata response, if requested via the appropriate header:' content: application/json: schema: type: array items: $ref: '#/components/schemas/PublicLink' example: - createdAt: 2018-04-18T23:19:14.802Z displayName: Public Survey id: 115 type: public_link updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z token: d1!E2GVHgpr4h9bpxxtqUJ7EVJ1Q$Dusm2RBXg8XyVJMCBCbvyE8cGacxUx3bcUT once: false application/json; extended: schema: type: array items: $ref: '#/components/schemas/ExtendedPublicLink' example: - createdAt: 2018-04-18T23:19:14.802Z displayName: Public Survey id: 115 type: public_link updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z token: d1!E2GVHgpr4h9bpxxtqUJ7EVJ1Q$Dusm2RBXg8XyVJMCBCbvyE8cGacxUx3bcUT once: false createdBy: createdAt: 2018-04-18T23:19:14.802Z displayName: My Display Name id: 115 type: user updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z post: tags: - Public Access Links summary: Creating a Link description: 'To create a new Public Access Link to this Form, you must send at least a `displayName` for the resulting Actor. You may also provide `once: true` if you want to create a link that [can only be filled by each respondent once](https://blog.enketo.org/single-submission-surveys/). This setting is enforced by Enketo using local device tracking; the link is still distributable to multiple recipients, and the enforcement can be defeated by using multiple browsers or devices.' operationId: Creating a Link parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "2" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple requestBody: content: '*/*': schema: required: - displayName type: object properties: displayName: type: string description: The name of the Link, for keeping track of. This name is displayed on the Central administration website but not to survey respondents. once: type: boolean description: If set to `true`, an Enketo [single submission survey](https://blog.enketo.org/single-submission-surveys/) will be created instead of a standard one, limiting respondents to a single submission each. example: displayName: my public link once: false required: false responses: 200: description: OK content: application/json: schema: required: - createdAt - displayName - id - type type: object properties: createdAt: type: string description: ISO date format displayName: type: string description: All `Actor`s, regardless of type, have a display name id: type: number type: type: string description: the Type of this Actor; typically this will be `user`. enum: - user - field_key - public_link - singleUse updatedAt: type: string description: ISO date format deletedAt: type: string description: ISO date format token: type: string description: If present, this is the Token to include as the `st` query parameter for this `Public Link`. If not present, this `Public Link` has been revoked. once: type: boolean description: If set to `true`, an Enketo [single submission survey](https://blog.enketo.org/single-submission-surveys/) will be created instead of a standard one, limiting respondents to a single submission each. example: createdAt: 2018-04-18T23:19:14.802Z displayName: My Display Name id: 115 type: user updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z token: d1!E2GVHgpr4h9bpxxtqUJ7EVJ1Q$Dusm2RBXg8XyVJMCBCbvyE8cGacxUx3bcUT once: false 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' x-codegen-request-body-name: body /v1/projects/{projectId}/forms/{xmlFormId}/public-links/{linkId}: delete: tags: - Public Access Links summary: Deleting a Link description: You can fully delete a link by issuing `DELETE` to its resource. This will remove the Link from the system entirely. If instead you wish to revoke the Link's access to prevent future submission without removing its record entirely, you can issue [`DELETE /sessions/:token`](/central-api-authentication/#logging-out-current-session). operationId: Deleting a Link parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: linkId in: path description: The numeric ID of the Link required: true schema: type: integer example: "42" responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Success' 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/dataset-diff: get: tags: - Related Datasets summary: Published Form Related Datasets description: This endpoint lists the name and Properties of a Dataset that are affected by a Form. The list of Properties includes all published Properties on that Dataset, but each property has the `inForm` flag to note whether or not it will be filled in by that form. operationId: Published Form Related Datasets parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple responses: 200: description: This is the standard response content: application/json: schema: type: array items: $ref: '#/components/schemas/DatasetDiff' example: - name: people properties: - name: first_name inForm: true /v1/projects/{projectId}/forms/{xmlFormId}/draft/dataset-diff: get: tags: - Related Datasets summary: Draft Form Dataset Diff description: This endpoint reflects the change to a Dataset that will go into effect once the form is Published. Like the endpoint above, it lists the Dataset name and Properties, but it also includes the `isNew` flag on both the Dataset, and on each individual property. This flag is true only if the Dataset/Property is new and is going to be created by publishing the Draft Form. operationId: Draft Form Dataset Diff parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple responses: 200: description: This is the standard response content: application/json: schema: type: array items: $ref: '#/components/schemas/DraftDatasetDiff' example: - name: people isNew: true properties: - name: first_name inForm: true isNew: true /v1/projects/{projectId}/forms/{xmlFormId}/submissions: get: tags: - Submissions summary: Listing all Submissions on a Form description: |- Currently, there are no paging or filtering options, so listing `Submission`s will get you every Submission in the system, every time. This endpoint supports retrieving extended metadata; provide a header `X-Extended-Metadata: true` to return a `submitter` data object alongside the `submitterId` Actor ID reference. operationId: Listing all Submissions on a Form parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple responses: 200: description: OK content: application/json: schema: type: array items: $ref: '#/components/schemas/Submission' example: - instanceId: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 submitterId: 23 deviceId: imei:123456 userAgent: Enketo/3.0.4 reviewState: approved createdAt: 2018-01-19T23:58:03.395Z updatedAt: 2018-03-21T12:45:02.312Z currentVersion: instanceId: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 instanceName: village third house submitterId: 23 deviceId: imei:123456 userAgent: Enketo/3.0.4 createdAt: 2018-01-19T23:58:03.395Z current: true application/json; extended: schema: type: array items: $ref: '#/components/schemas/ExtendedSubmission' example: - instanceId: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 submitterId: 23 deviceId: imei:123456 userAgent: Enketo/3.0.4 reviewState: approved createdAt: 2018-01-19T23:58:03.395Z updatedAt: 2018-03-21T12:45:02.312Z currentVersion: instanceId: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 instanceName: village third house submitterId: 23 deviceId: imei:123456 userAgent: Enketo/3.0.4 createdAt: 2018-01-19T23:58:03.395Z current: true submitter: createdAt: 2018-04-18T23:19:14.802Z displayName: My Display Name id: 115 type: user updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z 403: description: Forbidden content: application/json; extended: schema: $ref: '#/components/schemas/Error403' post: tags: - Submissions summary: Creating a Submission description: |- To create a Submission by REST rather than over the [OpenRosa interface](/central-api-openrosa-endpoints/#openrosa-form-submission-api), you may `POST` the Submission XML to this endpoint. The request must have an XML `Content-Type` (`text/xml` or `application/xml`). Unlike the OpenRosa Form Submission API, this interface does _not_ accept Submission attachments upon Submission creation. Instead, the server will determine which attachments are expected based on the Submission XML, and you may use the endpoints found in the following section to add the appropriate attachments and check the attachment status and content. If the XML is unparseable or there is some other input problem with your data, you will get a `400` error in response. If a submission already exists with the given `instanceId`, you will get a `409` error in response. operationId: Creating a Submission parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: deviceID in: query description: Optionally record a particular `deviceID` associated with this submission. It is recorded along with the data, but Central does nothing more with it. schema: type: string example: b1628661-65ed-4cab-8e30-19c17fef2de0 responses: 200: description: OK content: application/json: schema: required: - createdAt - instanceId - submitterId type: object properties: instanceId: type: string description: The `instanceId` of the `Submission`, given by the Submission XML. submitterId: type: number description: The ID of the `Actor` (`App User`, `User`, or `Public Link`) that originally submitted this `Submission`. deviceId: type: string description: The self-identified `deviceId` of the device that collected the data, sent by it upon submission to the server. The initial submission `deviceId` will be returned here. userAgent: type: string description: The self-identified `userAgent` of the device that collected the data, sent by it upon submission to the server. The initial submission `userAgent` will be returned here. reviewState: type: string description: The current review state of the submission. enum: - null - edited - hasIssues - rejected - approved - approved createdAt: type: string description: ISO date format. The time that the server received the Submission. updatedAt: type: string description: ISO date format. `null` when the Submission is first created, then updated when the Submission's XML data or metadata is updated. currentVersion: required: - createdAt - current - instanceId - submitterId type: object properties: instanceId: type: string description: The `instanceId` of the `Submission` version, given by the Submission XML. instanceName: type: string description: The `instanceName`, if any, given by the Submission XML in the metadata section. submitterId: type: number description: The ID of the `Actor` (`App User`, `User`, or `Public Link`) that submitted this `Submission` version. deviceId: type: string description: The self-identified `deviceId` of the device that submitted the `Submission` version. userAgent: type: string description: The self-identified `userAgent` of the device that submitted the `Submission` version. createdAt: type: string description: ISO date format. The time that the server received the `Submission` version. current: type: boolean description: Whether the version is current or not. description: The current version of the `Submission`. example: instanceId: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 submitterId: 23 deviceId: imei:123456 userAgent: Enketo/3.0.4 reviewState: approved createdAt: 2018-01-19T23:58:03.395Z updatedAt: 2018-03-21T12:45:02.312Z currentVersion: instanceId: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 instanceName: village third house submitterId: 23 deviceId: imei:123456 userAgent: Enketo/3.0.4 createdAt: 2018-01-19T23:58:03.395Z current: true 400: description: Bad Request content: application/json: schema: required: - code type: object properties: code: type: string details: type: object properties: {} description: a subobject that contains programmatically readable details about this error message: type: string example: code: "400" message: Could not parse the given data (2 chars) as json. 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' 409: description: Conflict content: application/json: schema: required: - code type: object properties: code: type: string message: type: string example: code: "409.1" message: A resource already exists with id value(s) of 1. /v1/projects/{projectId}/forms/{xmlFormId}/submissions/{instanceId}: get: tags: - Submissions summary: Getting Submission metadata description: |- Like how `Form`s are addressed by their XML `formId`, individual `Submission`s are addressed in the URL by their `instanceId`. As of version 1.4, a `deviceId` and `userAgent` will also be returned with each submission. The client device may transmit these extra metadata when the data is submitted. If it does, those fields will be recognized and returned here for reference. Here, only the initial `deviceId` and `userAgent` will be reported. If you wish to see these metadata for any submission edits, including the most recent edit, you will need to [list the versions](/central-api-submission-management/#listing-versions). As of version 2023.2, this API returns `currentVersion` that contains metadata of the most recent version of the Submission. This endpoint supports retrieving extended metadata; provide a header `X-Extended-Metadata: true` to return a `submitter` data object alongside the `submitterId` Actor ID reference. operationId: Getting Submission metadata parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: instanceId in: path description: The `instanceId` of the Submission being referenced. required: true schema: type: string example: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 responses: 200: description: 'This is the Extended Metadata response, if requested via the appropriate header:' content: application/json: schema: $ref: '#/components/schemas/Submission' example: instanceId: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 submitterId: 23 deviceId: imei:123456 userAgent: Enketo/3.0.4 reviewState: approved createdAt: 2018-01-19T23:58:03.395Z updatedAt: 2018-03-21T12:45:02.312Z currentVersion: instanceId: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 instanceName: village third house submitterId: 23 deviceId: imei:123456 userAgent: Enketo/3.0.4 createdAt: 2018-01-19T23:58:03.395Z current: true application/json; extended: schema: $ref: '#/components/schemas/ExtendedSubmission' example: instanceId: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 submitterId: 23 deviceId: imei:123456 userAgent: Enketo/3.0.4 reviewState: approved createdAt: 2018-01-19T23:58:03.395Z updatedAt: 2018-03-21T12:45:02.312Z currentVersion: instanceId: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 instanceName: village third house submitterId: 23 deviceId: imei:123456 userAgent: Enketo/3.0.4 createdAt: 2018-01-19T23:58:03.395Z current: true submitter: createdAt: 2018-04-18T23:19:14.802Z displayName: My Display Name id: 115 type: user updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z 301: description: Returns 301 with URL of the specific Submission version if `instanceId` of a Submission edit is provided content: text/html: example: "<Redirects to correct Submission URL>" 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' put: tags: - Submissions summary: Updating Submission Data description: |- _(introduced: version 1.2)_ You can use this endpoint to submit _updates_ to an existing submission. The `instanceId` that is submitted with the initial version of the submission is used permanently to reference that submission logically, which is to say the initial submission and all its subsequent versions. Each subsequent version will also provide its own `instanceId`. This `instanceId` becomes that particular version's identifier. To perform an update, you need to provide in the submission XML an additional [`deprecatedID` metadata node](https://getodk.github.io/xforms-spec/#metadata) with the `instanceID` of the particular and current submission version you are replacing. If the `deprecatedID` you give is anything other than the identifier of the current version of the submission at the time the server receives it, you will get a `409 Conflict` back. You can get the current version `instanceID` by getting the [current XML of the submission](/central-api-submission-management/#retrieving-submission-xml). The XML data you send will _replace_ the existing data entirely. All of the data must be present in the updated XML. When you create a new submission version, any uploaded media files attached to the current version that match expected attachment names in the new version will automatically be copied over to the new version. So if you don't make any changes to media files, there is no need to resubmit them. You can get information about all the submission versions [from the `/versions` subresource](/central-api-submission-management/#submission-versions). operationId: Updating Submission Data parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: instanceId in: path description: The `instanceId` of the Submission being updated. required: true schema: type: string example: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 responses: 200: description: OK content: application/json: schema: required: - createdAt - instanceId - submitterId type: object properties: instanceId: type: string description: The `instanceId` of the `Submission`, given by the Submission XML. submitterId: type: number description: The ID of the `Actor` (`App User`, `User`, or `Public Link`) that originally submitted this `Submission`. deviceId: type: string description: The self-identified `deviceId` of the device that collected the data, sent by it upon submission to the server. The initial submission `deviceId` will be returned here. userAgent: type: string description: The self-identified `userAgent` of the device that collected the data, sent by it upon submission to the server. The initial submission `userAgent` will be returned here. reviewState: type: string description: The current review state of the submission. enum: - null - edited - hasIssues - rejected - approved - approved createdAt: type: string description: ISO date format. The time that the server received the Submission. updatedAt: type: string description: ISO date format. `null` when the Submission is first created, then updated when the Submission's XML data or metadata is updated. currentVersion: required: - createdAt - current - instanceId - submitterId type: object properties: instanceId: type: string description: The `instanceId` of the `Submission` version, given by the Submission XML. instanceName: type: string description: The `instanceName`, if any, given by the Submission XML in the metadata section. submitterId: type: number description: The ID of the `Actor` (`App User`, `User`, or `Public Link`) that submitted this `Submission` version. deviceId: type: string description: The self-identified `deviceId` of the device that submitted the `Submission` version. userAgent: type: string description: The self-identified `userAgent` of the device that submitted the `Submission` version. createdAt: type: string description: ISO date format. The time that the server received the `Submission` version. current: type: boolean description: Whether the version is current or not. description: The current version of the `Submission`. example: instanceId: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 submitterId: 23 deviceId: imei:123456 userAgent: Enketo/3.0.4 reviewState: approved createdAt: 2018-01-19T23:58:03.395Z updatedAt: 2018-03-21T12:45:02.312Z currentVersion: instanceId: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 instanceName: village third house submitterId: 23 deviceId: imei:123456 userAgent: Enketo/3.0.4 createdAt: 2018-01-19T23:58:03.395Z current: true 400: description: Bad Request content: application/json: schema: required: - code type: object properties: code: type: string details: type: object properties: {} description: a subobject that contains programmatically readable details about this error message: type: string example: code: "400" message: Could not parse the given data (2 chars) as json. 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' 409: description: Conflict content: application/json: schema: required: - code type: object properties: code: type: string message: type: string example: code: "409.1" message: A resource already exists with id value(s) of 1. patch: tags: - Submissions summary: Updating Submission metadata description: |- Currently, the only updatable _metadata_ on a Submission is its `reviewState`. To update the submission _data_ itself, please see [Updating Submission data](/central-api-submission-management/#updating-submission-data). Starting with Version 2022.3, changing the `reviewState` of a Submission to `approved` can create an Entity in a Dataset if the corresponding Form maps Dataset Properties to Form Fields. If an Entity is created successfully then an `entity.create` event is logged in Audit logs, else `entity.error` is logged. operationId: Updating Submission metadata parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: instanceId in: path description: The `instanceId` of the Submission being referenced. required: true schema: type: string example: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 responses: 200: description: OK content: application/json: schema: required: - createdAt - instanceId - submitterId type: object properties: instanceId: type: string description: The `instanceId` of the `Submission`, given by the Submission XML. submitterId: type: number description: The ID of the `Actor` (`App User`, `User`, or `Public Link`) that originally submitted this `Submission`. deviceId: type: string description: The self-identified `deviceId` of the device that collected the data, sent by it upon submission to the server. The initial submission `deviceId` will be returned here. userAgent: type: string description: The self-identified `userAgent` of the device that collected the data, sent by it upon submission to the server. The initial submission `userAgent` will be returned here. reviewState: type: string description: The current review state of the submission. enum: - null - edited - hasIssues - rejected - approved - approved createdAt: type: string description: ISO date format. The time that the server received the Submission. updatedAt: type: string description: ISO date format. `null` when the Submission is first created, then updated when the Submission's XML data or metadata is updated. currentVersion: required: - createdAt - current - instanceId - submitterId type: object properties: instanceId: type: string description: The `instanceId` of the `Submission` version, given by the Submission XML. instanceName: type: string description: The `instanceName`, if any, given by the Submission XML in the metadata section. submitterId: type: number description: The ID of the `Actor` (`App User`, `User`, or `Public Link`) that submitted this `Submission` version. deviceId: type: string description: The self-identified `deviceId` of the device that submitted the `Submission` version. userAgent: type: string description: The self-identified `userAgent` of the device that submitted the `Submission` version. createdAt: type: string description: ISO date format. The time that the server received the `Submission` version. current: type: boolean description: Whether the version is current or not. description: The current version of the `Submission`. example: instanceId: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 submitterId: 23 deviceId: imei:123456 userAgent: Enketo/3.0.4 reviewState: approved createdAt: 2018-01-19T23:58:03.395Z updatedAt: 2018-03-21T12:45:02.312Z currentVersion: instanceId: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 instanceName: village third house submitterId: 23 deviceId: imei:123456 userAgent: Enketo/3.0.4 createdAt: 2018-01-19T23:58:03.395Z current: true 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/submissions/{instanceId}.xml: get: tags: - Submissions summary: Retrieving Submission XML description: To get only the XML of the `Submission` rather than all of the details with the XML as one of many properties, just add `.xml` to the end of the request URL. operationId: Retrieving Submission XML parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: instanceId in: path description: The `instanceId` of the Submission being referenced. required: true schema: type: string example: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 responses: 200: description: OK content: application/xml: example: | <data id="simple"> <orx:meta><orx:instanceID>uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44</orx:instanceID></orx:meta> <name>Alice</name> <age>32</age> </data> /v1/projects/{projectId}/forms/{xmlFormId}/submissions/{instanceId}/edit: get: tags: - Submissions summary: Getting an Enketo Edit URL description: |- _(introduced: version 1.2)_ This endpoint redirects the user to an Enketo-powered page that allows the user to interactively edit the submission. Once the user is satisfied, they can perform the submission update directly through the Enketo interface. The Enketo instance is already hosted inside of ODK Central. There is no reason to create or use a separate Enketo installation. This endpoint is intended for use by the Central administration frontend and will not work without it. In particular, the user must be logged into the Central administration site for Enketo editing to work. If there is no Central authentication cookie present when Enketo is loaded, the browser will then be redirected by Enketo to a Central login page. operationId: Getting an Enketo Edit URL parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: instanceId in: path description: The `instanceId` of the Submission being updated. required: true schema: type: string example: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 responses: 302: description: Found headers: Location: schema: type: string content: {} 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/submissions.csv.zip: get: tags: - Submissions summary: Exporting Form Submissions to CSV description: |- To export all the `Submission` data associated with a `Form`, just add `.csv.zip` to the end of the listing URL. The response will be a ZIP file containing one or more CSV files, as well as all multimedia attachments associated with the included Submissions. You can exclude the media attachments from the ZIP file by specifying `?attachments=false`. If [Project Managed Encryption](/central-api-encryption) is being used, additional querystring parameters may be provided in the format `{keyId}={passphrase}` for any number of keys (eg `1=secret&4=password`). This will decrypt any records encrypted under those managed keys. Submissions encrypted under self-supplied keys will not be decrypted. **Note**: if you are building a browser-based application, please consider the alternative `POST` endpoint, described in the following section. If a passphrase is supplied but is incorrect, the entire request will fail. If a passphrase is not supplied but encrypted records exist, only the metadata for those records will be returned, and they will have a `status` of `not decrypted`. If you are running an unsecured (`HTTP` rather than `HTTPS`) Central server, it is not a good idea to export data this way as your passphrase and the decrypted data will be sent plaintext over the network. You can use an [OData-style `$filter` query](/central-api-odata-endpoints/#data-document) to filter the submissions that will appear in the ZIP file. This is a bit awkward, since this endpoint has nothing to do with OData, but since we already must recognize the OData syntax, it is less strange overall for now not to invent a whole other one here. Only a subset of the `$filter` features are available; please see the linked section for more information. operationId: Exporting Form Submissions to CSV parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: attachments in: query description: Set to false to exclude media attachments from the export. schema: type: boolean example: "true" - name: '%24filter' in: query description: If provided, will filter responses to those matching the given OData query. Only [certain fields](/central-api-odata-endpoints/#data-document) are available to reference. The operators `lt`, `le`, `eq`, `neq`, `ge`, `gt`, `not`, `and`, and `or` are supported, and the built-in functions `now`, `year`, `month`, `day`, `hour`, `minute`, `second`. schema: type: string example: year(__system/submissionDate) lt year(now()) - name: groupPaths in: query description: Set to false to remove group path prefixes from field header names (eg `instanceID` instead of `meta-instanceID`). This behavior mimics a similar behavior in ODK Briefcase. schema: type: boolean example: "true" - name: deletedFields in: query description: Set to true to restore all fields previously deleted from this form for this export. All known fields and data for those fields will be merged and exported. schema: type: boolean example: "false" - name: splitSelectMultiples in: query description: Set to true to create a boolean column for every known select multiple option in the export. The option name is in the field header, and a `0` or a `1` will be present in each cell indicating whether that option was checked for that row. This behavior mimics a similar behavior in ODK Briefcase. schema: type: boolean example: "false" responses: 200: description: OK headers: Content-Disposition: schema: type: string content: {} 400: description: Bad Request content: application/json: schema: required: - code type: object properties: code: type: string details: type: object properties: {} description: a subobject that contains programmatically readable details about this error message: type: string example: code: "400" message: Could not parse the given data (2 chars) as json. 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' post: tags: - Submissions summary: Exporting Form Submissions to CSV via POST description: |- This non-REST-compliant endpoint is provided for use with [Project Managed Encryption](/central-api-encryption). In every respect, it behaves identically to the `GET` endpoint described in the previous section, except that it works over `POST`. This is necessary because for browser-based applications, it is a dangerous idea to simply link the user to `/submissions.csv.zip?2=supersecretpassphrase` because the browser will remember this route in its history and thus the passphrase will become exposed. This is especially dangerous as there are techniques for quickly learning browser-visited URLs of any arbitrary domain. You can exclude the media attachments from the ZIP file by specifying `?attachments=false`. And so, for this `POST` version of the Submission CSV export endpoint, the passphrases may be provided via `POST` body rather than querystring. Two formats are supported: form URL encoding (`application/x-www-form-urlencoded`) and JSON. In either case, the keys should be the `keyId`s and the values should be the `passphrase`s, as with the `GET` version above. operationId: Exporting Form Submissions to CSV via POST parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: attachments in: query description: Set to false to exclude media attachments from the export. schema: type: boolean example: "true" - name: '%24filter' in: query description: If provided, will filter responses to those matching the given OData query. Only [certain fields](/central-api-odata-endpoints/#data-document) are available to reference. The operators `lt`, `le`, `eq`, `neq`, `ge`, `gt`, `not`, `and`, and `or` are supported, and the built-in functions `now`, `year`, `month`, `day`, `hour`, `minute`, `second`. schema: type: string example: year(__system/submissionDate) lt year(now()) - name: groupPaths in: query description: Set to false to remove group path prefixes from field header names (eg `instanceID` instead of `meta-instanceID`). This behavior mimics a similar behavior in ODK Briefcase. schema: type: boolean example: "true" - name: deletedFields in: query description: Set to true to restore all fields previously deleted from this form for this export. All known fields and data for those fields will be merged and exported. schema: type: boolean example: "false" - name: splitSelectMultiples in: query description: Set to true to create a boolean column for every known select multiple option in the export. The option name is in the field header, and a `0` or a `1` will be present in each cell indicating whether that option was checked for that row. This behavior mimics a similar behavior in ODK Briefcase. schema: type: boolean example: "false" responses: 200: description: OK headers: Content-Disposition: schema: type: string content: {} 400: description: Bad Request content: application/json: schema: required: - code type: object properties: code: type: string details: type: object properties: {} description: a subobject that contains programmatically readable details about this error message: type: string example: code: "400" message: Could not parse the given data (2 chars) as json. 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/submissions.csv: get: tags: - Submissions summary: Exporting Root Data to Plain CSV description: |- _(introduced: version 1.1)_ The above submission endpoints will give you a ZIP file with the submission data in it. This is necessary to provide all the possible related repeat table files, as well as the media files associated with the submissions. But ZIP files can be difficult to work with, and many Forms have no repeats nor media attachments. To export _just_ the root table (no repeat data nor media files), you can call this endpoint instead, which will directly give you CSV data. Please see the [above endpoint](/central-api-submission-management/#exporting-form-submissions-to-csv) for notes on dealing with Managed Encryption. operationId: Exporting Root Data to Plain CSV parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: '%24filter' in: query description: If provided, will filter responses to those matching the given OData query. Only [certain fields](/central-api-odata-endpoints/#data-document) are available to reference. The operators `lt`, `le`, `eq`, `neq`, `ge`, `gt`, `not`, `and`, and `or` are supported, and the built-in functions `now`, `year`, `month`, `day`, `hour`, `minute`, `second`. schema: type: string example: year(__system/submissionDate) lt year(now()) responses: 200: description: OK content: {} 400: description: Bad Request content: application/json: schema: required: - code type: object properties: code: type: string details: type: object properties: {} description: a subobject that contains programmatically readable details about this error message: type: string example: code: "400" message: Could not parse the given data (2 chars) as json. 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' post: tags: - Submissions summary: Exporting Root Data to Plain CSV via POST description: |- _(introduced: version 1.1)_ This endpoint is useful only for Forms under Project Managed Encryption. As with `GET` to `.csv` just above, this endpoint will only return CSV text data, rather than a ZIP file containing ore or more files. Please see that endpoint for further explanation. As with [`POST` to `.csv.zip`](/central-api-submission-management/#exporting-form-submissions-to-csv-via-post) it allows secure submission of decryption passkeys. Please see that endpoint for more information on how to do this. operationId: Exporting Root Data to Plain CSV via POST parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: '%24filter' in: query description: If provided, will filter responses to those matching the given OData query. Only [certain fields](/central-api-odata-endpoints/#data-document) are available to reference. The operators `lt`, `le`, `eq`, `neq`, `ge`, `gt`, `not`, `and`, and `or` are supported, and the built-in functions `now`, `year`, `month`, `day`, `hour`, `minute`, `second`. schema: type: string example: year(__system/submissionDate) lt year(now()) responses: 200: description: OK content: {} 400: description: Bad Request content: application/json: schema: required: - code type: object properties: code: type: string details: type: object properties: {} description: a subobject that contains programmatically readable details about this error message: type: string example: code: "400" message: Could not parse the given data (2 chars) as json. 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/submissions/{instanceId}/audits: get: tags: - Submissions summary: Retrieving Audit Logs description: |- _(introduced: version 1.2)_ You can retrieve all [Server Audit Logs](/central-api-system-endpoints/#server-audit-logs) relating to a submission. They will be returned most recent first. This endpoint supports retrieving extended metadata; provide a header `X-Extended-Metadata: true` to additionally expand the `actorId` into full `actor` details, and `acteeId` into full `actee` details. The `actor` will always be an Actor, and the `actee` will be the Form this Submission is a part of. operationId: Retrieving Audit Logs parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: instanceId in: path description: The `instanceId` of the Submission. required: true schema: type: string example: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 responses: 200: description: OK content: application/json: schema: type: array items: $ref: '#/components/schemas/Audit' example: - actorId: 42 action: form.create acteeId: 85cb9aff-005e-4edd-9739-dc9c1a829c44 loggedAt: 2018-04-18T23:19:14.802Z application/json; extended: schema: type: array items: $ref: '#/components/schemas/ExtendedAudit' example: - actorId: 42 action: form.create acteeId: 85cb9aff-005e-4edd-9739-dc9c1a829c44 loggedAt: 2018-04-18T23:19:14.802Z actor: createdAt: 2018-04-18T23:19:14.802Z displayName: My Display Name id: 115 type: user updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/submissions/keys: get: tags: - Submissions summary: Listing Encryption Keys description: This endpoint provides a listing of all known encryption keys needed to decrypt all Submissions for a given Form. It will return at least the `base64RsaPublicKey` property (as `public`) of all known versions of the form that have submissions against them. If managed keys are being used and a `hint` was provided, that will be returned as well. operationId: Listing Encryption Keys parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple responses: 200: description: OK content: application/json: schema: type: array items: $ref: '#/components/schemas/Key' example: - id: 1 public: bcFeKDF3Sg8W91Uf5uxaIlsuhzmjbgUnIyiLzIjrx4CAaf9Y9LG7TAu6wKPqfbH6ZAkJTFSfjLNovbKhpOQcmO5VZGGay6yvXrX1TFW6C6RLITy74erxfUAStdtpP4nraCYqQYqn5zD4/1OmgweJt5vzGXW2ch7lrROEQhXB9lK+bjEeWx8TFW/+6ha/oRLnl6a2RBRL6mhwy3PoByNTKndB2MP4TygCJ/Ini4ivk74iSqVnoeuNJR/xUcU+kaIpZEIjxpAS2VECJU9fZvS5Gt84e5wl/t7bUKu+dlh/cUgHfk6+6bwzqGQYOe5A== managed: true hint: it was a secret 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/submissions/submitters: get: tags: - Submissions summary: Listing Submitters description: This endpoint provides a listing of all known submitting actors to a given Form. Each Actor that has submitted to the given Form will be returned once. operationId: Listing Submitters parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple responses: 200: description: OK content: application/json: schema: type: array items: $ref: '#/components/schemas/Actor' example: - createdAt: 2018-04-18T23:19:14.802Z displayName: My Display Name id: 115 type: user updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/submissions/{instanceId}/comments: get: tags: - Comments summary: Listing Comments description: |- Comments have only a `body` comment text and an `actor` that made the comment. This endpoint supports retrieving extended metadata; provide a header `X-Extended-Metadata: true` to return a `actor` data object alongside the `actorId` Actor ID reference. operationId: Listing Comments parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: instanceId in: path description: The `instanceId` of the Submission being referenced. required: true schema: type: string example: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 responses: 200: description: OK content: application/json: schema: type: array items: $ref: '#/components/schemas/Comment' example: - body: this is my comment actorId: 42 application/json; extended: schema: type: array items: $ref: '#/components/schemas/ExtendedComment' example: - body: this is my comment actorId: 42 actor: createdAt: 2018-04-18T23:19:14.802Z displayName: My Display Name id: 115 type: user updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' post: tags: - Comments summary: Posting Comments description: Currently, the only accepted data is `body`, which contains the body of the comment to be made. operationId: Posting Comments parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: instanceId in: path description: The `instanceId` of the Submission being referenced. required: true schema: type: string example: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 requestBody: content: '*/*': schema: required: - body type: object properties: body: type: string description: The text of the comment. example: body: this is the text of my comment required: false responses: 200: description: OK content: application/json: schema: required: - actorId - body type: object properties: body: type: string description: The text of the comment. actorId: type: number description: The ID of the Actor that made the comment. example: body: this is my comment actorId: 42 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' x-codegen-request-body-name: body /v1/projects/{projectId}/forms/{xmlFormId}/submissions/{instanceId}/attachments: get: tags: - Attachments summary: Listing expected Submission Attachments description: You can retrieve the list of expected Submission attachments at this route, along with a boolean flag indicating whether the server actually has a copy of the expected file or not. If the server has a file, you can then append its filename to the request URL to download only that file (see below). operationId: Listing expected Submission Attachments parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: instanceId in: path description: The `instanceId` of the Submission being referenced. required: true schema: type: string example: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 responses: 200: description: OK content: application/json: schema: type: array items: $ref: '#/components/schemas/SubmissionAttachment' example: - name: file1.jpg exists: true - name: file2.jpg exists: false - name: file3.jpg exists: true 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/submissions/{instanceId}/attachments/{filename}: get: tags: - Attachments summary: Downloading an Attachment description: The `Content-Type` and `Content-Disposition` will be set appropriately based on the file itself when requesting an attachment file download. This endpoint supports `ETag`, which can be used to avoid downloading the same content more than once. When an API consumer calls this endpoint, it returns a value in `ETag` header, you can pass this value in the header `If-None-Match` of subsequent requests. If the file has not been changed since the previous request, you will receive `304 Not Modified` response otherwise you'll get the latest file. operationId: Downloading an Attachment parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: instanceId in: path description: The `instanceId` of the Submission being referenced. required: true schema: type: string example: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 - name: filename in: path description: The name of the file as given by the Attachments listing resource. required: true schema: type: string example: file1.jpg responses: 200: description: OK headers: Content-Disposition: schema: type: string ETag: schema: type: string description: content version identifier content: '{the MIME type of the attachment file itself}': example: | (binary data) 403: description: Forbidden content: '{the MIME type of the attachment file itself}': schema: required: - code type: object properties: code: type: string message: type: string application/json: schema: $ref: '#/components/schemas/Error403' post: tags: - Attachments summary: Uploading an Attachment description: |- _(introduced: version 0.4)_ To upload a binary to an expected file slot, `POST` the binary to its endpoint. Supply a `Content-Type` MIME-type header if you have one. operationId: Uploading an Attachment parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: instanceId in: path description: The `instanceId` of the Submission being referenced. required: true schema: type: string example: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 - name: filename in: path description: The name of the file as given by the Attachments listing resource. required: true schema: type: string example: file1.jpg responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Success' 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' delete: tags: - Attachments summary: Clearing a Submission Attachment description: |- _(introduced: version 0.4)_ Because Submission Attachments are completely determined by the XML data of the submission itself, there is no direct way to entirely remove a Submission Attachment entry from the list, only to clear its uploaded content. Thus, when you issue a `DELETE` to the attachment's endpoint, that is what happens. operationId: Clearing a Submission Attachment parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: instanceId in: path description: The `instanceId` of the Submission being referenced. required: true schema: type: string example: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 - name: filename in: path description: The name of the file as given by the Attachments listing resource. required: true schema: type: string example: file1.jpg responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Success' 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/submissions/{instanceId}/versions: get: tags: - Submission Versions summary: Listing Versions description: |- This will return all submission metadata for every version of this submission, in descending creation order. This endpoint supports retrieving extended metadata; provide a header `X-Extended-Metadata: true` to return a `submitter` data object alongside the `submitterId` Actor ID reference. operationId: Listing Versions parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: instanceId in: path description: The `instanceId` of the initially submitted version. Please see the notes at the top of this documentation section for more information. required: true schema: type: string example: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 responses: 200: description: OK content: application/json: schema: type: array items: $ref: '#/components/schemas/SubmissionVersion' example: - instanceId: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 instanceName: village third house submitterId: 23 deviceId: imei:123456 userAgent: Enketo/3.0.4 createdAt: 2018-01-19T23:58:03.395Z current: true formVersion: "1.0" application/json; extended: schema: type: array items: $ref: '#/components/schemas/ExtendedSubmissionVersion' example: - instanceId: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 instanceName: village third house submitterId: 23 deviceId: imei:123456 userAgent: Enketo/3.0.4 createdAt: 2018-01-19T23:58:03.395Z current: true submitter: createdAt: 2018-04-18T23:19:14.802Z displayName: My Display Name id: 115 type: user updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z formVersion: "1.0" 403: description: Forbidden content: application/json; extended: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/submissions/{instanceId}/versions/{versionId}: get: tags: - Submission Versions summary: Getting Version Details description: |- Returns metadata about a particular version of the submission. As with the normal submission endpoint, you'll only get metadata in JSON out of this route. If you want to retrieve the XML, [add `.xml`](/central-api-submission-management/#getting-version-xml). This endpoint supports retrieving extended metadata; provide a header `X-Extended-Metadata: true` to return a `submitter` data object alongside the `submitterId` Actor ID reference. operationId: Getting Version Details parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: instanceId in: path description: The `instanceId` of the Submission being referenced. required: true schema: type: string example: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 - name: versionId in: path description: The `instanceId` of the particular version of this submission in question. required: true schema: type: string example: uuid:b1628661-65ed-4cab-8e30-19c17fef2de0 responses: 200: description: 'This is the Extended Metadata response, if requested via the appropriate header:' content: application/json: schema: $ref: '#/components/schemas/SubmissionVersion' example: instanceId: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 instanceName: village third house submitterId: 23 deviceId: imei:123456 userAgent: Enketo/3.0.4 createdAt: 2018-01-19T23:58:03.395Z current: true formVersion: "1.0" application/json; extended: schema: $ref: '#/components/schemas/ExtendedSubmissionVersion' example: instanceId: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 instanceName: village third house submitterId: 23 deviceId: imei:123456 userAgent: Enketo/3.0.4 createdAt: 2018-01-19T23:58:03.395Z current: true submitter: createdAt: 2018-04-18T23:19:14.802Z displayName: My Display Name id: 115 type: user updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z formVersion: "1.0" 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/submissions/{instanceId}/versions/{versionId}.xml: get: tags: - Submission Versions summary: Getting Version XML description: Returns the XML of a particular version of the submission. operationId: Getting Version XML parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: instanceId in: path description: The `instanceId` of the Submission being referenced. required: true schema: type: string example: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 - name: versionId in: path description: The `instanceId` of the particular version of this submission in question. required: true schema: type: string example: uuid:b1628661-65ed-4cab-8e30-19c17fef2de0 responses: 200: description: OK content: application/xml: example: | <data id="simple"> <orx:meta><orx:instanceID>uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44</orx:instanceID></orx:meta> <name>Alice</name> <age>32</age> </data> 403: description: Forbidden content: application/xml: schema: required: - code type: object properties: code: type: string message: type: string application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/submissions/{instanceId}/versions/{versionId}/attachments: get: tags: - Submission Versions summary: Listing Version expected Attachments description: You can retrieve the list of expected Submission attachments for the given version at this route, along with a boolean flag indicating whether the server actually has a copy of the expected file or not. If the server has a file, you can then append its filename to the request URL to download only that file (see below). operationId: Listing Version expected Attachments parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: instanceId in: path description: The `instanceId` of the Submission being referenced. required: true schema: type: string example: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 - name: versionId in: path description: The `instanceId` of the particular version of this submission in question. required: true schema: type: string example: uuid:b1628661-65ed-4cab-8e30-19c17fef2de0 responses: 200: description: OK content: application/json: schema: type: array items: $ref: '#/components/schemas/SubmissionAttachment' example: - name: file1.jpg exists: true - name: file2.jpg exists: false - name: file3.jpg exists: true 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/submissions/{instanceId}/versions/{versionId}/attachments/{filename}: get: tags: - Submission Versions summary: Downloading a Version's Attachment description: It is important to note that this endpoint returns whatever is _currently_ uploaded against the _particular version_ of the _Submission_. It will not track overwritten attachments. This endpoint supports `ETag`, which can be used to avoid downloading the same content more than once. When an API consumer calls this endpoint, it returns a value in `ETag` header, you can pass this value in the header `If-None-Match` of subsequent requests. If the file has not been changed since the previous request, you will receive `304 Not Modified` response otherwise you'll get the latest file. operationId: Downloading a Version's Attachment parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: instanceId in: path description: The `instanceId` of the Submission being referenced. required: true schema: type: string example: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 - name: versionId in: path description: The `instanceId` of the particular version of this submission in question. required: true schema: type: string example: uuid:b1628661-65ed-4cab-8e30-19c17fef2de0 - name: filename in: path description: The name of the file as given by the Attachments listing resource. required: true schema: type: string example: file1.jpg responses: 200: description: OK headers: Content-Disposition: schema: type: string ETag: schema: type: string description: content version identifier content: '{the MIME type of the attachment file itself}': example: | (binary data) 403: description: Forbidden content: '{the MIME type of the attachment file itself}': schema: required: - code type: object properties: code: type: string message: type: string application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/submissions/{instanceId}/diffs: get: tags: - Submission Versions summary: Getting changes between Versions description: This returns the changes, or edits, between different versions of a Submission. These changes are returned in an object that is indexed by the `instanceId` that uniquely identifies that version. Between two submissions, there is an array of objects representing how each field changed. This change object contains the old and new values, as well as the path of that changed node in the Submission XML. These changes reflect the updated `instanceID` and `deprecatedID` fields as well as the edited value. operationId: Getting changes between Versions parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: instanceId in: path description: The `instanceId` of the Submission being referenced. required: true schema: type: string example: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 responses: 200: description: OK content: application/json: schema: type: array items: type: array items: $ref: '#/components/schemas/SubmissionDiffValue' example: two: - new: Donna old: Dana path: - name - new: '55' old: '44' path: - age - new: two old: one path: - meta - instanceID - new: one old: path: - meta - deprecatedID 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/draft/submissions: get: tags: - Draft Submissions summary: Listing all Submissions on a Draft Form description: Identical to [the non-Draft version](/central-api-submission-management/#listing-all-submissions-on-a-form) of this endpoint. operationId: Listing all Submissions on a Draft Form parameters: - name: projectId in: path description: The `id` of the project this form belongs to. required: true schema: type: number example: "1" - name: xmlFormId in: path description: The `id` of this form as given in its XForms XML definition required: true schema: type: string example: simple responses: 200: description: 'This is the Extended Metadata response, if requested via the appropriate header:' content: application/json: schema: type: array items: $ref: '#/components/schemas/Submission' example: - instanceId: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 submitterId: 23 deviceId: imei:123456 userAgent: Enketo/3.0.4 reviewState: approved createdAt: 2018-01-19T23:58:03.395Z updatedAt: 2018-03-21T12:45:02.312Z currentVersion: instanceId: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 instanceName: village third house submitterId: 23 deviceId: imei:123456 userAgent: Enketo/3.0.4 createdAt: 2018-01-19T23:58:03.395Z current: true application/json; extended: schema: type: array items: $ref: '#/components/schemas/ExtendedSubmission' example: - instanceId: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 submitterId: 23 deviceId: imei:123456 userAgent: Enketo/3.0.4 reviewState: approved createdAt: 2018-01-19T23:58:03.395Z updatedAt: 2018-03-21T12:45:02.312Z currentVersion: instanceId: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 instanceName: village third house submitterId: 23 deviceId: imei:123456 userAgent: Enketo/3.0.4 createdAt: 2018-01-19T23:58:03.395Z current: true submitter: createdAt: 2018-04-18T23:19:14.802Z displayName: My Display Name id: 115 type: user updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' post: tags: - Draft Submissions summary: Creating a Submission description: Identical to [the non-Draft version](/central-api-submission-management/#creating-a-submission) of this endpoint. operationId: Creating a Submission for a draft Form parameters: - name: projectId in: path description: The `id` of the project this form belongs to. required: true schema: type: number example: "1" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple responses: 200: description: OK content: application/json: schema: required: - createdAt - instanceId - submitterId type: object properties: instanceId: type: string description: The `instanceId` of the `Submission`, given by the Submission XML. submitterId: type: number description: The ID of the `Actor` (`App User`, `User`, or `Public Link`) that originally submitted this `Submission`. deviceId: type: string description: The self-identified `deviceId` of the device that collected the data, sent by it upon submission to the server. The initial submission `deviceId` will be returned here. userAgent: type: string description: The self-identified `userAgent` of the device that collected the data, sent by it upon submission to the server. The initial submission `userAgent` will be returned here. reviewState: type: string description: The current review state of the submission. enum: - null - edited - hasIssues - rejected - approved - approved createdAt: type: string description: ISO date format. The time that the server received the Submission. updatedAt: type: string description: ISO date format. `null` when the Submission is first created, then updated when the Submission's XML data or metadata is updated. currentVersion: required: - createdAt - current - instanceId - submitterId type: object properties: instanceId: type: string description: The `instanceId` of the `Submission` version, given by the Submission XML. instanceName: type: string description: The `instanceName`, if any, given by the Submission XML in the metadata section. submitterId: type: number description: The ID of the `Actor` (`App User`, `User`, or `Public Link`) that submitted this `Submission` version. deviceId: type: string description: The self-identified `deviceId` of the device that submitted the `Submission` version. userAgent: type: string description: The self-identified `userAgent` of the device that submitted the `Submission` version. createdAt: type: string description: ISO date format. The time that the server received the `Submission` version. current: type: boolean description: Whether the version is current or not. description: The current version of the `Submission`. example: instanceId: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 submitterId: 23 deviceId: imei:123456 userAgent: Enketo/3.0.4 reviewState: approved createdAt: 2018-01-19T23:58:03.395Z updatedAt: 2018-03-21T12:45:02.312Z currentVersion: instanceId: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 instanceName: village third house submitterId: 23 deviceId: imei:123456 userAgent: Enketo/3.0.4 createdAt: 2018-01-19T23:58:03.395Z current: true 400: description: Bad Request content: application/json: schema: required: - code type: object properties: code: type: string details: type: object properties: {} description: a subobject that contains programmatically readable details about this error message: type: string example: code: "400" message: Could not parse the given data (2 chars) as json. 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' 409: description: Conflict content: application/json: schema: required: - code type: object properties: code: type: string message: type: string example: code: "409.1" message: A resource already exists with id value(s) of 1. /v1/projects/{projectId}/forms/{xmlFormId}/draft/submissions.csv.zip: get: tags: - Draft Submissions summary: Exporting Form Submissions to CSV description: Identical to [the non-Draft version](/central-api-submission-management/#exporting-form-submissions-to-csv) of this endpoint. operationId: Exporting Form(Draft) Submissions to CSV parameters: - name: projectId in: path description: The `id` of the project this form belongs to. required: true schema: type: number example: "1" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple responses: 200: description: OK headers: Content-Disposition: schema: type: string content: {} 400: description: Bad Request content: application/json: schema: required: - code type: object properties: code: type: string details: type: object properties: {} description: a subobject that contains programmatically readable details about this error message: type: string example: code: "400" message: Could not parse the given data (2 chars) as json. 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' post: tags: - Draft Submissions summary: Exporting Form Submissions to CSV via POST description: Identical to [the non-Draft version](/central-api-submission-management/#exporting-form-submissions-to-csv-via-post) of this endpoint. operationId: Exporting Form(Draft) Submissions to CSV via POST parameters: - name: projectId in: path description: The `id` of the project this form belongs to. required: true schema: type: number example: "1" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple responses: 200: description: OK headers: Content-Disposition: schema: type: string content: {} 400: description: Bad Request content: application/json: schema: required: - code type: object properties: code: type: string details: type: object properties: {} description: a subobject that contains programmatically readable details about this error message: type: string example: code: "400" message: Could not parse the given data (2 chars) as json. 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/draft/submissions/keys: get: tags: - Draft Submissions summary: Listing Encryption Keys description: Identical to [the non-Draft version](/central-api-submission-management/#listing-encryption-keys) of this endpoint. operationId: Listing Encryption Keys (Draft Form) parameters: - name: projectId in: path description: The `id` of the project this form belongs to. required: true schema: type: number example: "1" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple responses: 200: description: OK content: application/json: schema: type: array items: $ref: '#/components/schemas/Key' example: - id: 1 public: bcFeKDF3Sg8W91Uf5uxaIlsuhzmjbgUnIyiLzIjrx4CAaf9Y9LG7TAu6wKPqfbH6ZAkJTFSfjLNovbKhpOQcmO5VZGGay6yvXrX1TFW6C6RLITy74erxfUAStdtpP4nraCYqQYqn5zD4/1OmgweJt5vzGXW2ch7lrROEQhXB9lK+bjEeWx8TFW/+6ha/oRLnl6a2RBRL6mhwy3PoByNTKndB2MP4TygCJ/Ini4ivk74iSqVnoeuNJR/xUcU+kaIpZEIjxpAS2VECJU9fZvS5Gt84e5wl/t7bUKu+dlh/cUgHfk6+6bwzqGQYOe5A== managed: true hint: it was a secret 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/draft/submissions/{instanceId}: get: tags: - Draft Submissions summary: Getting Submission details description: Identical to [the non-Draft version](/central-api-submission-management/#getting-submission-metadata) of this endpoint. operationId: Getting Submission details parameters: - name: projectId in: path description: The `id` of the project this form belongs to. required: true schema: type: number example: "1" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: instanceId in: path description: The `instanceId` of the Submission being referenced. required: true schema: type: string example: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 responses: 200: description: 'This is the Extended Metadata response, if requested via the appropriate header:' content: application/json; extended: schema: required: - createdAt - instanceId - submitter - submitterId type: object properties: instanceId: type: string description: The `instanceId` of the `Submission`, given by the Submission XML. submitterId: type: number description: The ID of the `Actor` (`App User`, `User`, or `Public Link`) that originally submitted this `Submission`. deviceId: type: string description: The self-identified `deviceId` of the device that collected the data, sent by it upon submission to the server. The initial submission `deviceId` will be returned here. userAgent: type: string description: The self-identified `userAgent` of the device that collected the data, sent by it upon submission to the server. The initial submission `userAgent` will be returned here. reviewState: type: string description: The current review state of the submission. enum: - null - edited - hasIssues - rejected - approved - approved createdAt: type: string description: ISO date format. The time that the server received the Submission. updatedAt: type: string description: ISO date format. `null` when the Submission is first created, then updated when the Submission's XML data or metadata is updated. currentVersion: required: - createdAt - current - instanceId - submitterId type: object properties: instanceId: type: string description: The `instanceId` of the `Submission` version, given by the Submission XML. instanceName: type: string description: The `instanceName`, if any, given by the Submission XML in the metadata section. submitterId: type: number description: The ID of the `Actor` (`App User`, `User`, or `Public Link`) that submitted this `Submission` version. deviceId: type: string description: The self-identified `deviceId` of the device that submitted the `Submission` version. userAgent: type: string description: The self-identified `userAgent` of the device that submitted the `Submission` version. createdAt: type: string description: ISO date format. The time that the server received the `Submission` version. current: type: boolean description: Whether the version is current or not. description: The current version of the `Submission`. submitter: required: - createdAt - displayName - id - type type: object properties: createdAt: type: string description: ISO date format displayName: type: string description: All `Actor`s, regardless of type, have a display name id: type: number type: type: string description: the Type of this Actor; typically this will be `user`. enum: - user - field_key - public_link - singleUse updatedAt: type: string description: ISO date format deletedAt: type: string description: ISO date format description: The full details of the `Actor` that submitted this `Submission`. example: instanceId: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 submitterId: 23 deviceId: imei:123456 userAgent: Enketo/3.0.4 reviewState: approved createdAt: 2018-01-19T23:58:03.395Z updatedAt: 2018-03-21T12:45:02.312Z currentVersion: instanceId: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 instanceName: village third house submitterId: 23 deviceId: imei:123456 userAgent: Enketo/3.0.4 createdAt: 2018-01-19T23:58:03.395Z current: true submitter: createdAt: 2018-04-18T23:19:14.802Z displayName: My Display Name id: 115 type: user updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z application/json: schema: required: - createdAt - instanceId - submitter - submitterId type: object properties: instanceId: type: string description: The `instanceId` of the `Submission`, given by the Submission XML. submitterId: type: number description: The ID of the `Actor` (`App User`, `User`, or `Public Link`) that originally submitted this `Submission`. deviceId: type: string description: The self-identified `deviceId` of the device that collected the data, sent by it upon submission to the server. The initial submission `deviceId` will be returned here. userAgent: type: string description: The self-identified `userAgent` of the device that collected the data, sent by it upon submission to the server. The initial submission `userAgent` will be returned here. reviewState: type: string description: The current review state of the submission. enum: - null - edited - hasIssues - rejected - approved - approved createdAt: type: string description: ISO date format. The time that the server received the Submission. updatedAt: type: string description: ISO date format. `null` when the Submission is first created, then updated when the Submission's XML data or metadata is updated. currentVersion: required: - createdAt - current - instanceId - submitterId type: object properties: instanceId: type: string description: The `instanceId` of the `Submission` version, given by the Submission XML. instanceName: type: string description: The `instanceName`, if any, given by the Submission XML in the metadata section. submitterId: type: number description: The ID of the `Actor` (`App User`, `User`, or `Public Link`) that submitted this `Submission` version. deviceId: type: string description: The self-identified `deviceId` of the device that submitted the `Submission` version. userAgent: type: string description: The self-identified `userAgent` of the device that submitted the `Submission` version. createdAt: type: string description: ISO date format. The time that the server received the `Submission` version. current: type: boolean description: Whether the version is current or not. description: The current version of the `Submission`. submitter: required: - createdAt - displayName - id - type type: object properties: createdAt: type: string description: ISO date format displayName: type: string description: All `Actor`s, regardless of type, have a display name id: type: number type: type: string description: the Type of this Actor; typically this will be `user`. enum: - user - field_key - public_link - singleUse updatedAt: type: string description: ISO date format deletedAt: type: string description: ISO date format description: The full details of the `Actor` that submitted this `Submission`. 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}/draft/submissions/{instanceId}.xml: get: tags: - Draft Submissions summary: Retrieving Submission XML description: Identical to [the non-Draft version](/central-api-submission-management/#retrieving-submission-xml) of this endpoint. operationId: Retrieving Submission XML (Draft Form) parameters: - name: projectId in: path description: The `id` of the project this form belongs to. required: true schema: type: number example: "1" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: instanceId in: path description: The `instanceId` of the Submission being referenced. required: true schema: type: string example: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 responses: 200: description: OK content: application/xml: example: | <data id="simple"> <orx:meta><orx:instanceID>uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44</orx:instanceID></orx:meta> <name>Alice</name> <age>32</age> </data> /v1/projects/{projectId}/forms/{xmlFormId}/draft/submissions/{instanceId}/attachments: get: tags: - Draft Submissions summary: Listing expected Submission Attachments description: Identical to [the non-Draft version](/central-api-submission-management/#listing-expected-submission-attachments) of this endpoint. operationId: Listing expected Submission Attachments (Draft Form) parameters: - name: projectId in: path description: The `id` of the project this form belongs to. required: true schema: type: number example: "1" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: instanceId in: path description: The `instanceId` of the Submission being referenced. required: true schema: type: string example: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 responses: 200: description: OK content: application/json: schema: type: array items: $ref: "#/components/schemas/SubmissionAttachment" example: - name: file1.jpg exists: true - name: file2.jpg exists: false - name: file3.jpg exists: true 403: description: Forbidden content: application/json: schema: $ref: "#/components/schemas/Error403" /v1/projects/{projectId}/forms/{xmlFormId}/draft/submissions/{instanceId}/attachments/{filename}: get: tags: - Draft Submissions summary: Downloading an Attachment description: Identical to [the non-Draft version](/central-api-submission-management/#downloading-an-attachment) of this endpoint. operationId: Downloading an Attachment (Draft Form) parameters: - name: projectId in: path description: The `id` of the project this form belongs to. required: true schema: type: number example: "1" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: instanceId in: path description: The `instanceId` of the Submission being referenced. required: true schema: type: string example: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 - name: filename in: path description: The name of the file as given by the Attachments listing resource. required: true schema: type: string example: file1.jpg responses: 200: description: OK headers: Content-Disposition: schema: type: string content: '{the MIME type of the attachment file itself}': example: | (binary data) 403: description: Forbidden content: '{the MIME type of the attachment file itself}': schema: required: - code type: object properties: code: type: string message: type: string application/json: schema: $ref: '#/components/schemas/Error403' post: tags: - Draft Submissions summary: Uploading an Attachment description: Identical to [the non-Draft version](/central-api-submission-management/#uploading-an-attachment) of this endpoint. operationId: Uploading an Attachment (Form Draft) parameters: - name: projectId in: path description: The `id` of the project this form belongs to. required: true schema: type: number example: "1" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: instanceId in: path description: The `instanceId` of the Submission being referenced. required: true schema: type: string example: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 - name: filename in: path description: The name of the file as given by the Attachments listing resource. required: true schema: type: string example: file1.jpg responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Success' 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' delete: tags: - Draft Submissions summary: Clearing a Submission Attachment description: Identical to [the non-Draft version](/central-api-submission-management/#clearing-a-submission-attachment) of this endpoint. operationId: Clearing a Submission Attachment (Form Draft) parameters: - name: projectId in: path description: The `id` of the project this form belongs to. required: true schema: type: number example: "1" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: instanceId in: path description: The `instanceId` of the Submission being referenced. required: true schema: type: string example: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 - name: filename in: path description: The name of the file as given by the Attachments listing resource. required: true schema: type: string example: file1.jpg responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Success' 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /projects/{projectId}/datasets: get: tags: - Dataset Management summary: Listing Datasets description: The Dataset listing endpoint returns all published Datasets in a Project. If a Draft Form defines a new Dataset, that Dataset will not be included in this list until the Form is published. operationId: Listing Datasets parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" responses: 200: description: OK content: application/json: schema: type: array items: $ref: '#/components/schemas/Dataset' example: - name: people createdAt: '2018-01-19T23:58:03.395Z' projectId: 1 approvalRequired: true application/json; extended: schema: type: array items: $ref: '#/components/schemas/ExtendedDataset' example: - name: people createdAt: '2018-01-19T23:58:03.395Z' projectId: 1 approvalRequired: true lastEntity: '2018-04-18T03:04:51.695Z' entities: 10 conflicts: 2 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' post: tags: - Dataset Management summary: Creating Datasets description: |- You can create a Dataset with a specific `name` within a Project. This Dataset can then be populated with Entities via the API or via Forms and Submissions, and then used by other Forms. This endpoint allows a Dataset to be created programatically without an input form. The name of a Dataset is case-sensitive in that it will keep the capitalization provided (e.g. "Trees"). But Central will not allow a second Dataset with the same name but different capitalization to be created (e.g. "trees" when "Trees" already exists). By default, the Dataset will have no properties, but each Entity will have a `label` and a unique ID (`uuid`). You can add additional properties with this [related endpoint](/central-api-dataset-management/#adding-properties). The Dataset name must follow the the same rules as XML identifiers and not start with `.` or `__`. See the [Entities XForms Specification](https://getodk.github.io/xforms-spec/entities.html#declaring-that-a-form-creates-entities) for more information. operationId: Creating Datasets parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" requestBody: content: '*/*': schema: required: - name type: object properties: name: type: string description: The desired name of the Dataset. Must be a valid approvalRequired: type: boolean description: Control whether a Submission should be approved before an Entity is created from it. required: false example: name: Trees approvalRequired: false required: false responses: 200: description: OK content: application/json: schema: type: array items: $ref: '#/components/schemas/DatasetMetadata' example: name: people createdAt: '2018-01-19T23:58:03.395Z' projectId: 1 approvalRequired: false sourceForms: [] linkedForms: [] properties: [] 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' 409: description: Conflict content: application/json: schema: required: - code type: object properties: code: type: number message: type: string example: code: 409.3 message: A resource already exists with name,projectId value(s) of trees,1. /projects/{projectId}/datasets/{name}: get: tags: - Dataset Management summary: Dataset Metadata description: Returns the metadata of a published Dataset including properties and forms that create and consume the Dataset. operationId: Dataset Metadata parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: name in: path description: Name of the Dataset required: true schema: type: string example: people responses: 200: description: OK content: application/json: schema: type: array items: $ref: '#/components/schemas/DatasetMetadata' example: name: people createdAt: '2018-01-19T23:58:03.395Z' projectId: 1 approvalRequired: true sourceForms: - xmlFormId: treeRegistration name: Tree Registration linkedForms: - xmlFormId: simple name: Simple properties: - name: the.age odataName: the_age publishedAt: '2018-01-21T00:04:11.153Z' forms: - xmlFormId: simple name: Simple 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' patch: tags: - Dataset Management summary: Update Dataset Metadata operationId: Update Dataset Metadata description: |- You can only update `approvalRequired` using this endpoint. `approvalRequired` flag controls the Entity creation flow; if it is `true` then the Submission must be approved before an Entity can be created from it and if it is `false` then an Entity is created as soon as the Submission is received by the ODK Central. By default `approvalRequired` is `false` for the Datasets created after v2023.3. Datasets created prior to that will have `approvalRequired` set to `true`. parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: name in: path description: Name of the Dataset required: true schema: type: string example: people requestBody: content: 'application/json': schema: type: object properties: approvalRequired: type: boolean description: Control whether a Submission should be approved before an Entity is created from it. example: true example: approvalRequired: true responses: 200: description: OK content: application/json: schema: type: array items: $ref: '#/components/schemas/DatasetMetadata' example: name: people createdAt: '2018-01-19T23:58:03.395Z' projectId: 1 approvalRequired: true sourceForms: - xmlFormId: treeRegistration name: Tree Registration linkedForms: - xmlFormId: simple name: Simple properties: - name: the.age odataName: the_age publishedAt: '2018-01-21T00:04:11.153Z' forms: - xmlFormId: simple name: Simple 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /projects/{projectId}/datasets/{name}/properties: post: tags: - Dataset Management summary: Adding Properties description: |- Creates a new Property with a specified name in the Dataset. Property names follow the same rules as form field names (valid XML identifiers) and cannot use the reserved names of `name` or `label`, or begin with the reserved prefix `__`. operationId: Adding Properties parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: name in: path description: Name of the Dataset required: true schema: type: string example: people requestBody: content: '*/*': schema: required: - name type: object properties: name: type: string description: The desired name of the Property. example: name: circumference required: false responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Success' 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /projects/{projectId}/datasets/{name}/entities.csv: get: tags: - Dataset Management summary: Download Dataset description: |- Datasets (collections of Entities) can be used as Attachments in other Forms, but they can also be downloaded directly as a CSV file. The CSV format closely matches the [OData Dataset Service](/central-api-odata-endpoints/#odata-dataset-service) format, with columns for system properties such as `__id` (the Entity UUID), `__createdAt`, `__creatorName`, etc., the Entity Label `label`, and the Dataset/Entity Properties themselves. If any Property for an given Entity is blank (e.g. it was not captured by that Form or was left blank), that field of the CSV is blank. The `$filter` querystring parameter can be used to filter on system-level properties, similar to how filtering in the [OData Dataset Service](/central-api-odata-endpoints/#odata-dataset-service) works. This endpoint supports `ETag` header, which can be used to avoid downloading the same content more than once. When an API consumer calls this endpoint, the endpoint returns a value in the ETag header. If you pass that value in the If-None-Match header of a subsequent request, then if the Dataset has not been changed since the previous request, you will receive `304 Not Modified` response; otherwise you'll get the new data. operationId: Download Dataset parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: name in: path description: Name of the Dataset required: true schema: type: string example: people - name: $filter in: query description: If provided, will filter responses to those matching the query. Only system-level Entity fields are available to reference. The operators `lt`, `le`, `eq`, `neq`, `ge`, `gt`, `not`, `and`, and `or` are supported, and the built-in functions `now`, `year`, `month`, `day`, `hour`, `minute`, `second`. schema: type: string example: __system/conflict eq \'hard\' responses: 200: description: OK headers: Content-Disposition: schema: type: string ETag: schema: type: string description: content version identifier content: text/csv: example: | __id,label,geometry,species,circumference_cm,__createdAt,__creatorId,__creatorName,__updates,__updatedAt,__version 2c1ee90b-dde8-434b-9985-2eefd8465339,666cm purpleheart,-29.281608 -67.624883 0 0,purpleheart,667,2023-05-31T19:49:28.902Z,22,Alice,1,2023-05-31T19:52:34.467Z,1 84ac3a03-9980-4098-93a5-b81fdc6ea749,555cm wallaba,18.921876 77.309451 0 0,wallaba,555,2023-05-31T19:49:20.152Z,22,Alice,0,,1 403: description: Forbidden content: text/csv: schema: required: - code type: object properties: code: type: string message: type: string application/json: schema: $ref: '#/components/schemas/Error403' /projects/{projectId}/datasets/{name}/entities: get: tags: - Entity Management summary: Entities Metadata description: |- This endpoint returns a list of the Entities of a Dataset. Please note that this endpoint only returns metadata of the entities not the data. If you want to get the data of all entities then please refer to [OData Dataset Service](/central-api-odata-endpoints/#odata-form-service) You can provide `?deleted=true` to get only deleted entities. operationId: Entities Metadata parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: name in: path description: Name of the Dataset required: true schema: type: string example: people responses: 200: description: OK content: application/json: schema: type: array description: Standard Response items: $ref: '#/components/schemas/EntitySummary' example: - uuid: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 createdAt: '2018-01-19T23:58:03.395Z' updatedAt: '2018-03-21T12:45:02.312Z' deletedAt: '2018-03-21T12:45:02.312Z' creatorId: 1 currentVersion: label: John (88) current: true createdAt: '2018-03-21T12:45:02.312Z' creatorId: 1 userAgent: Enketo/3.0.4 version: 1 baseVersion: null conflictingProperties: null application/json; extended: schema: type: array description: Extended Response items: $ref: '#/components/schemas/ExtendedEntitySummary' example: - uuid: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 createdAt: '2018-01-19T23:58:03.395Z' updatedAt: '2018-03-21T12:45:02.312Z' deletedAt: '2018-03-21T12:45:02.312Z' creatorId: 1 conflict: null creator: createdAt: '2018-04-18T23:19:14.802Z' displayName: My Display Name id: 115 type: user updatedAt: '2018-04-18T23:42:11.406Z' deletedAt: '2018-04-18T23:42:11.406Z' currentVersion: label: John (88) current: true createdAt: '2018-03-21T12:45:02.312Z' creatorId: 1 userAgent: Enketo/3.0.4 version: 1 baseVersion: null conflictingProperties: null creator: createdAt: '2018-04-18T23:19:14.802Z' displayName: My Display Name id: 115 type: user updatedAt: '2018-04-18T23:42:11.406Z' deletedAt: '2018-04-18T23:42:11.406Z' 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' post: tags: - Entity Management summary: Creating Entities description: |- Creates one or more Entities in the Dataset. For creating **a single Entity**, the request body takes a JSON representation of the Entity, which has the following properties: 1. A `data` object containing values for the user-defined Dataset properties. (Not all properties have to have values.) 2. A `label` property, which cannot be blank or an empty string. (This is used as a human-readable label in Forms that consume Entities.) 3. An optional `uuid` property. If the `uuid` is not specified, Central will generate a UUID for an Entity with the provided data and label. ` { "label": "John Doe", "data": { "firstName": "John", "age": "22" } } ` The value type of all properties is `string`. For creating **multiple Entities** in bulk, the request body takes an array `entities` containing a list of Entity objects as described above. The bulk entity version also takes a `source` property with a required `name` field and optional `size`, for example to capture the filename and size of a bulk upload source. ` { "entities": [...], "source": {"name": "file.csv", "size": 100} } ` You can provide header `X-Action-Notes` to store the metadata about the request. The metadata can retrieved using [Entity Audit Log](/central-api-entity-management/#entity-audit-log) operationId: Creating an Entity parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: name in: path description: Name of the Dataset required: true schema: type: string example: people requestBody: content: '*/*': schema: oneOf: - $ref: '#/components/schemas/EntityCreateSingle' - $ref: '#/components/schemas/EntityCreateBulk' example: entities: - uuid: 54a405a0-53ce-4748-9788-d23a30cc3afa label: John Doe (22) data: firstName: John age: '22' - uuid: 0c3a7922-b611-42ca-a961-944e09fa9aa2 label: Amy Jane (38) data: firstName: Amy age: '38' source: name: my_dataset.csv size: 100 responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Entity' example: uuid: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 createdAt: '2018-01-19T23:58:03.395Z' updatedAt: '2018-03-21T12:45:02.312Z' deletedAt: '2018-03-21T12:45:02.312Z' creatorId: 1 conflict: null currentVersion: label: John (88) current: true createdAt: '2018-03-21T12:45:02.312Z' creatorId: 1 userAgent: Enketo/3.0.4 conflictingProperties: null version: 1 baseVersion: null data: firstName: John age: '88' dataReceived: label: John (88) firstName: John age: '88' 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /projects/{projectId}/datasets/{name}/entities/{uuid}: get: tags: - Entity Management summary: Getting Entity Details description: |- This returns the metadata and current data of an Entity. The data and label of an Entity are found in the `currentVersion` object under `data` and `label` respectively. The `currentVersion` object also contains version-specific metadata fields such as `version`, `baseVersion`, details about conflicts that version introduced, etc. See the [versions](/central-api-entity-management/#listing-versions) endpoint for more details. The Entity also contains top-level system metadata such as `uuid`, `createdAt` and `updatedAt` timestamps, and `creatorId` (or full `creator` if extended metadata is requested). **Conflicts** An Entity's metadata also has a `conflict` field, which indicates the current conflict status of the Entity. The value of a conflict can either be: * `null`. The Entity does not have conflicting versions. * `soft`. The Entity has a version that was based on a version other than the version immediately prior to it. (The specified `baseVerson` was not the latest version on the server.) * `hard`. The Entity has a version that was based on a version other than the version immediately prior to it. Further, that version updated the same property as another update. If an Entity has a conflict, it can be marked as resolved. After that, the conflict field will be null until a new conflicting version is received. operationId: Getting Entity Details parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: name in: path description: Name of the Dataset required: true schema: type: string example: people - name: uuid in: path description: UUID of the Entity required: true schema: type: string example: 54a405a0-53ce-4748-9788-d23a30cc3afa responses: 200: description: OK content: application/json: schema: type: array items: $ref: '#/components/schemas/Entity' example: uuid: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 createdAt: '2018-01-19T23:58:03.395Z' updatedAt: '2018-03-21T12:45:02.312Z' deletedAt: '2018-03-21T12:45:02.312Z' creatorId: 1 conflict: null currentVersion: label: John (88) current: true createdAt: '2018-03-21T12:45:02.312Z' creatorId: 1 userAgent: Enketo/3.0.4 conflictingProperties: null version: 1 baseVersion: null data: firstName: John age: '88' dataReceived: firstName: John age: '88' label: John (88) application/json; extended: schema: type: array items: $ref: '#/components/schemas/ExtendedEntity' example: uuid: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 createdAt: '2018-01-19T23:58:03.395Z' updatedAt: '2018-03-21T12:45:02.312Z' deletedAt: '2018-03-21T12:45:02.312Z' creatorId: 1 conflict: null creator: createdAt: '2018-04-18T23:19:14.802Z' displayName: My Display Name id: 115 type: user updatedAt: '2018-04-18T23:42:11.406Z' deletedAt: '2018-04-18T23:42:11.406Z' currentVersion: label: John (88) current: true createdAt: '2018-03-21T12:45:02.312Z' creatorId: 1 userAgent: Enketo/3.0.4 conflictingProperties: null version: 1 baseVersion: null data: firstName: John age: '88' dataReceived: firstName: John age: '88' label: John (88) creator: createdAt: '2018-04-18T23:19:14.802Z' displayName: My Display Name id: 115 type: user updatedAt: '2018-04-18T23:42:11.406Z' deletedAt: '2018-04-18T23:42:11.406Z' 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' delete: tags: - Entity Management summary: Deleting an Entity description: Use this API to delete an Entity. With this API, Entity is soft-deleted, which means it is still in the database and you can retreive it by passing `?deleted=true` to [GET /projects/:id/datasets/:name/entities](/central-api-entity-management/#entities-metadata). In the future, we will provide a way to restore deleted entities and purge deleted entities. operationId: Deleting an Entity parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: name in: path description: Name of the Dataset required: true schema: type: string example: people - name: uuid in: path description: UUID of the Entity required: true schema: type: string example: 54a405a0-53ce-4748-9788-d23a30cc3afa responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Success' 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' patch: tags: - Entity Management summary: Updating an Entity description: |- This endpoint is used to update the label or the properties (passed as JSON in the request body) of an Entity. You only need to include the properties you wish to update. To unset the value of any property, you can set it to empty string (""). The label must be a non-empty string. Setting a property to `null` will throw an error. Attempting to update a property that doesn't exist in the Dataset will throw an error. **Specifying a base version** You must either provide the query parameter `baseVersion` or use the `force=true` query parameter. The specified `baseVersion` must match the current version of the Entity on the server or the request will be rejected. This acts as a check to ensure you are not trying to update based on stale data. To update an Entity regardless of its current state, use the `force` flag with value `true`. **Resolving a conflict** You can also use this endpoint to resolve an Entity conflict by passing the `resolve=true` query parameter, in which case providing data in the request body is optional. When not providing new data, only the `conflict` status from the Entity will be cleared and no new version will be created. When providing data, the `conflict` will be cleared and an updated version of the Entity will be added. operationId: Updating an Entity parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: name in: path description: Name of the Dataset required: true schema: type: string example: people - name: uuid in: path description: UUID of the Entity required: true schema: type: string example: 54a405a0-53ce-4748-9788-d23a30cc3afa - name: baseVersion in: query description: The base version of the Entity you are applying the update to (must match the latest version on the server) required: false schema: type: integer example: 2 - name: force in: query description: Flag to forcefully update the Entity required: false schema: type: boolean example: true - name: resolve in: query description: Flag to resolve the conflict required: false schema: type: boolean example: true requestBody: content: '*/*': schema: type: object properties: label: type: string description: Label of the Entity data: $ref: '#/components/schemas/DataExample' example: label: John Doe (88) data: firstName: John age: '88' responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Entity' example: uuid: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 createdAt: '2018-01-19T23:58:03.395Z' updatedAt: '2018-03-21T12:45:02.312Z' deletedAt: '2018-03-21T12:45:02.312Z' creatorId: 1 conflict: null currentVersion: label: John (88) current: true createdAt: '2018-03-21T12:45:02.312Z' creatorId: 1 userAgent: Enketo/3.0.4 conflictingProperties: null version: 1 baseVersion: null data: firstName: John age: '88' dataReceived: firstName: John age: '88' label: John (88) 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' x-codegen-request-body-name: body /projects/{projectId}/datasets/{name}/entities/{uuid}/versions: get: tags: - Entity Management summary: Listing Versions description: |- This returns the Entity metadata and data for every version of this Entity, in ascending creation order. This endpoint supports retrieving extended metadata; provide a header `X-Extended-Metadata: true` to return a `creator` data object alongside the `creatorId` Actor ID reference. There is an optional query flag `relevantToConflict` that returns the subset of past versions of an Entity that are relevant to the Entity's current conflict. This includes the latest version, the base version, the previous server version, and any other versions since the last time the Entity was in a conflict-free state. If the Entity is not in conflict, zero versions are returned. operationId: Listing Entity Versions parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: name in: path description: Name of the Dataset required: true schema: type: string example: people - name: uuid in: path description: UUID of the Entity required: true schema: type: string example: 54a405a0-53ce-4748-9788-d23a30cc3afa - name: relevantToConflict in: query description: Flag to return only the versions of the entity that are relevant to the current conflict. schema: type: boolean example: true responses: 200: description: OK content: application/json: schema: type: array description: Standard Response items: $ref: '#/components/schemas/EntityVersionFull' example: - label: John (88) current: true createdAt: '2018-03-21T12:45:02.312Z' creatorId: 1 userAgent: Enketo/3.0.4 version: 1 baseVersion: null conflict: null resolved: false lastGoodVersion: true relevantToConflict: false conflictingProperties: null baseDiff: [] serverDiff: [] source: "// Similar to Audit.details. This property is experimental and may change in the future." data: firstName: John age: '88' dataReceived: firstName: John age: '88' label: John (88) application/json; extended: schema: type: array description: Extended Response items: $ref: '#/components/schemas/ExtendedEntityVersionFull' example: - label: John (88) current: true createdAt: '2018-03-21T12:45:02.312Z' creatorId: 1 userAgent: Enketo/3.0.4 version: 1 baseVersion: null conflict: null resolved: false lastGoodVersion: true relevantToConflict: false conflictingProperties: null baseDiff: [] serverDiff: [] source: "// Similar to Audit.details. This property is experimental and may change in the future." data: firstName: John age: '88' dataReceived: firstName: John age: '88' label: John (88) creator: createdAt: '2018-04-18T23:19:14.802Z' displayName: My Display Name id: 115 type: user updatedAt: '2018-04-18T23:42:11.406Z' deletedAt: '2018-04-18T23:42:11.406Z' 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /projects/{projectId}/datasets/{name}/entities/{uuid}/diffs: get: tags: - Entity Management summary: Getting changes between Versions description: This returns the changes, or edits, between different versions of an Entity. These changes are returned as an array of arrays. Between two Entities, there is an array of objects representing how each property changed. This change object contains the old and new values, as well as the property name. operationId: Getting changes between Entity Versions parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: name in: path description: Name of the Dataset required: true schema: type: string example: people - name: uuid in: path description: UUID of the Entity required: true schema: type: string example: 54a405a0-53ce-4748-9788-d23a30cc3afa responses: 200: description: + Response 200 content: application/json: schema: type: array items: $ref: '#/components/schemas/EntityDiffValue' example: - - new: John old: Dana propertyName: firstName - new: Doe old: Roe propertyName: lastName - new: John Doe old: Jane Roe propertyName: label - - new: Robert old: Doe propertyName: firstName - new: Robert Doe old: Doe Doe propertyName: label 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /projects/{projectId}/datasets/{name}/entities/{uuid}/audits: get: tags: - Entity Management summary: Entity Audit Log description: Returns [Server Audit Logs](/central-api-system-endpoints/#server-audit-logs) relating to an Entity. They will be returned most recent first. operationId: Entity Audit Log parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: name in: path description: Name of the Dataset required: true schema: type: string example: people - name: uuid in: path description: UUID of the Entity required: true schema: type: string example: 54a405a0-53ce-4748-9788-d23a30cc3afa responses: 200: description: OK content: application/json: schema: type: array items: $ref: '#/components/schemas/Audit' example: - actorId: 42 action: entity.create acteeId: 85cb9aff-005e-4edd-9739-dc9c1a829c44 loggedAt: 2018-04-18T23:19:14.802Z 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/formList: get: tags: - OpenRosa Endpoints summary: OpenRosa Form Listing API description: |- This is the mostly standards-compliant implementation of the [OpenRosa Form Discovery (Listing) API](https://bitbucket.org/javarosa/javarosa/wiki/FormListAPI). We will not attempt to redocument the standard here. The following aspects of the standard are _not_ supported by ODK Central: * The `deviceID` may be provided with the request, but it will be ignored. * The `Accept-Language` header may be provided with the request, but it will be ignored. * The `?formID=` querystring parameter is not supported and will be ignored. * The `?verbose` querystring parameter is not supported and will be ignored. * The `?listAllVersions` querystring is not supported and will be ignored. Central does not yet support multiple active versions of the same Form. * No `<xforms-group/>` will ever be provided, as Central does not yet support this feature. By default, the given `<name/>` in the Form Listing response is the friendly name associated with the `Form` (`<title>` in the XML and `name` on the API resource). If no such value can be found, then the `xmlFormId` will be given as the `<name>` instead. A `<manifestUrl/>` property will be given per `<xform>` if and only if that form is expected to have media or data file attachments associated with it, based on its XForms definition. It will appear even if no attachments have actually been uploaded to the server to fulfill those expectations. This resource always requires authentication. If a valid Actor is authenticated at all, a form list will always be returned, filtered by what that Actor is allowed to access. If you haven't already, please take a look at the **HTTP Request API** notes above on the required OpenRosa headers. operationId: OpenRosa Form Listing API parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "7" - name: X-OpenRosa-Version in: header description: e.g. 1.0 schema: type: string example: "1.0" responses: 200: description: OK headers: X-OpenRosa-Version: schema: type: string content: text/xml: example: | <?xml version="1.0" encoding="UTF-8"?> <xforms xmlns="http://openrosa.org/xforms/xformsList"> <xform> <formID>basic</formID> <name>basic</name> <version></version> <hash>md5:a64817a5688dd7c17563e32d4eb1cab2</hash> <downloadUrl>https://your.odk.server/v1/projects/7/forms/basic.xml</downloadUrl> <manifestUrl>https://your.odk.server/v1/projects/7/forms/basic/manifest</manifestUrl> </xform> <xform> <formID>simple</formID> <name>Simple</name> <version></version> <hash>md5:</hash> <downloadUrl>https://your.odk.server/v1/projects/7/forms/simple.xml</downloadUrl> </xform> </xforms> /v1/projects/{projectId}/submission: post: tags: - OpenRosa Endpoints summary: OpenRosa Form Submission API description: |- This is the fully standards-compliant implementation of the [OpenRosa Form Submission API](https://bitbucket.org/javarosa/javarosa/wiki/FormSubmissionAPI). We will not attempt to redocument the submission part of the standard here, but please read further for information about _updating_ submissions with new data. Some things to understand when using this API for any reason: * ODK Central will always provide an `X-OpenRosa-Accept-Content-Length` of 100 megabytes. In reality, this number depends on how the server has been deployed. The default Docker-based installation, for example, is limited to 100MB at the nginx layer. * The `xml_submission_file` may have a Content Type of either `text/xml` _or_ `application/xml`. * Central supports the `HEAD` request preflighting recommended by the specification, but does not require it. Because our supported authentication methods do not follow the try/retry pattern, only preflight your request if you want to read the `X-OpenRosa-Accept-Content-Length` header or are concerned about the other issues listed in the standards document, like proxies. * As stated in the standards document, it is possible to submit multimedia attachments with the `Submission` across multiple `POST` requests to this API. _However_, we impose the additional restriction that the Submission XML (`xml_submission_file`) _may not change_ between requests. If Central sees a Submission with an `instanceId` it already knows about but the XML has changed in any way, it will respond with a `409 Conflict` error and reject the submission. * Central will never return a `202` in any response from this API. * If you haven't already, please take a look at the **HTTP Request API** notes above on the required OpenRosa headers. You can use this endpoint to submit _updates_ to an existing submission. To do so, provide additionally a [`deprecatedID` metadata XML node](https://getodk.github.io/xforms-spec/#metadata) with the `instanceID` of the submission you are replacing. Some things to understand when submitting updates: * The new XML entirely replaces the old XML. No merging will be performed. So your new submission must contain exactly the current data. * If the `deprecatedID` you provide has already been deprecated, your request will be rejected with a `409 Conflict` and a useful error message. * If the submission you are deprecating had media files uploaded for it, any of those that are still relevant will be carried over to the new version by filename reference. Any files you provide will overwrite these carryovers. * Just as with initial submission, you can send multiple requests to this endpoint to submit additional media files if they do not comfortably fit in a single request. Also the same as initial submission, you'll need to provide exactly the same XML to make this happen. For updates, this will need to include the `deprecatedID`. operationId: OpenRosa Form Submission API parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "7" - name: X-OpenRosa-Version in: header description: e.g. 1.0 schema: type: string example: "1.0" responses: 201: description: Created headers: X-OpenRosa-Version: schema: type: string content: text/xml: example: | <OpenRosaResponse xmlns="http://openrosa.org/http/response" items="0"> <message nature="">full submission upload was successful!</message> </OpenRosaResponse> 400: description: 'This is one of several possible `400` failures the API might return:' headers: X-OpenRosa-Version: schema: type: string content: text/xml: example: | <OpenRosaResponse xmlns="http://openrosa.org/http/response" items="0"> <message nature="error">A resource already exists with a attachment file name of attachment1.jpg.</message> </OpenRosaResponse> 403: description: Forbidden headers: X-OpenRosa-Version: schema: type: string content: text/xml: example: | <OpenRosaResponse xmlns="http://openrosa.org/http/response" items="0"> <message nature="error">The authenticated actor does not have rights to perform that action.</message> </OpenRosaResponse> 409: description: Conflict headers: X-OpenRosa-Version: schema: type: string content: text/xml: example: | <OpenRosaResponse xmlns="http://openrosa.org/http/response" items="0"> <message nature="error">A submission already exists with this ID, but with different XML. Resubmissions to attach additional multimedia must resubmit an identical xml_submission_file.</message> </OpenRosaResponse> /v1/projects/{projectId}/forms/{xmlFormId}/manifest: get: tags: - OpenRosa Endpoints summary: OpenRosa Form Manifest API description: |- _(introduced: version 0.2)_ This is the fully standards-compliant implementation of the [OpenRosa Form Manifest API](https://bitbucket.org/javarosa/javarosa/wiki/FormListAPI#!the-manifest-document). We will not attempt to redocument the standard here. A Manifest document is available at this resource path for any form in the system. However: * A link to this document will not be given in the [Form Listing API](/central-api-openrosa-endpoints/#openrosa-form-listing-api) unless we expect the form to have media or data file attachments based on the XForms definition of the form. * The Manifest will only output information for files the server actually has in its possession. Any missing expected files will be omitted, as we cannot provide a `hash` or `downloadUrl` for them. * For Attachments that are linked to a Dataset, the value of `hash` is calculated using the MD5 of the last updated timestamp of the Dataset, instead of the content of the Dataset. operationId: OpenRosa Form Manifest API parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "7" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: X-OpenRosa-Version in: header description: e.g. 1.0 schema: type: string example: "1.0" responses: 200: description: OK headers: X-OpenRosa-Version: schema: type: string content: text/xml: example: | <?xml version="1.0" encoding="UTF-8"?> <manifest xmlns="http://openrosa.org/xforms/xformsManifest"> <mediaFile> <filename>question1.jpg</filename> <hash>md5:a64817a5688dd7c17563e32d4eb1cab2</hash> <downloadUrl>https://your.odk.server/v1/projects/7/forms/basic/attachments/question1.jpg</downloadUrl> </mediaFile> <mediaFile> <filename>question2.jpg</filename> <hash>md5:a6fdc426037143cf71cced68e2532e3c</hash> <downloadUrl>https://your.odk.server/v1/projects/7/forms/basic/attachments/question2.jpg</downloadUrl> </mediaFile> </manifest> 403: description: Forbidden headers: X-OpenRosa-Version: schema: type: string content: text/xml: example: | <OpenRosaResponse xmlns="http://openrosa.org/http/response" items="0"> <message nature="error">The authenticated actor does not have rights to perform that action.</message> </OpenRosaResponse> /v1/test/{token}/projects/{projectId}/forms/{xmlFormId}/draft/formList: get: tags: - Draft Testing Endpoints summary: OpenRosa Form Listing API description: Identical to the [non-Draft version](/central-api-openrosa-endpoints/#openrosa-form-listing-api), but will only list the Draft Form to be tested. operationId: OpenRosa Form Listing API (Draft Form) parameters: - name: token in: path description: The authentication Draft Token associated with the Draft Form in question. required: true schema: type: string example: "IeksRu1CNZs7!qjAot2T17dPzkrw9B4iTtpj7OoIJBmXvnHM8z8Ka4QP" - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "7" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: X-OpenRosa-Version in: header description: e.g. 1.0 schema: type: string example: "1.0" responses: 200: description: OK headers: X-OpenRosa-Version: schema: type: string content: text/xml: example: | <?xml version="1.0" encoding="UTF-8"?> <xforms xmlns="http://openrosa.org/xforms/xformsList"> <xform> <formID>basic</formID> <name>basic</name> <version></version> <hash>md5:a64817a5688dd7c17563e32d4eb1cab2</hash> <downloadUrl>https://your.odk.server/v1/test/IeksRu1CNZs7!qjAot2T17dPzkrw9B4iTtpj7OoIJBmXvnHM8z8Ka4QP/projects/7/forms/basic/draft.xml</downloadUrl> <manifestUrl>https://your.odk.server/v1/test/IeksRu1CNZs7!qjAot2T17dPzkrw9B4iTtpj7OoIJBmXvnHM8z8Ka4QP/projects/7/forms/basic/draft/manifest</manifestUrl> </xform> </xforms> /v1/test/{token}/projects/{projectId}/forms/{xmlFormId}/draft/submission: post: tags: - Draft Testing Endpoints summary: OpenRosa Form Submission API description: Identical to the [non-Draft version](/central-api-openrosa-endpoints/#openrosa-form-submission-api), but will only submit to (and allow submissions to) the Draft Form to be tested. operationId: OpenRosa Form Submission API (Draft Form) parameters: - name: token in: path description: The authentication Draft Token associated with the Draft Form in question. required: true schema: type: string example: "IeksRu1CNZs7!qjAot2T17dPzkrw9B4iTtpj7OoIJBmXvnHM8z8Ka4QP" - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "7" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: X-OpenRosa-Version in: header description: e.g. 1.0 schema: type: string example: "1.0" responses: 201: description: Created headers: X-OpenRosa-Version: schema: type: string content: text/xml: example: | <OpenRosaResponse xmlns="http://openrosa.org/http/response" items="0"> <message nature="">full submission upload was successful!</message> </OpenRosaResponse> 400: description: 'This is one of several possible `400` failures the API might return:' headers: X-OpenRosa-Version: schema: type: string content: text/xml: example: | <OpenRosaResponse xmlns="http://openrosa.org/http/response" items="0"> <message nature="error">A resource already exists with a attachment file name of attachment1.jpg.</message> </OpenRosaResponse> 403: description: Forbidden headers: X-OpenRosa-Version: schema: type: string content: text/xml: example: | <OpenRosaResponse xmlns="http://openrosa.org/http/response" items="0"> <message nature="error">The authenticated actor does not have rights to perform that action.</message> </OpenRosaResponse> 409: description: Conflict headers: X-OpenRosa-Version: schema: type: string content: text/xml: example: | <OpenRosaResponse xmlns="http://openrosa.org/http/response" items="0"> <message nature="error">A submission already exists with this ID, but with different XML. Resubmissions to attach additional multimedia must resubmit an identical xml_submission_file.</message> </OpenRosaResponse> /v1/test/{token}/projects/{projectId}/forms/{xmlFormId}/draft/manifest: get: tags: - Draft Testing Endpoints summary: OpenRosa Form Manifest API description: Identical to the [non-Draft version](/central-api-openrosa-endpoints/#openrosa-form-manifest-api). operationId: OpenRosa Form Manifest API (Draft Form) parameters: - name: token in: path description: The authentication Draft Token associated with the Draft Form in question. required: true schema: type: string example: "IeksRu1CNZs7!qjAot2T17dPzkrw9B4iTtpj7OoIJBmXvnHM8z8Ka4QP" - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "7" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: X-OpenRosa-Version in: header description: e.g. 1.0 schema: type: string example: "1.0" responses: 200: description: OK headers: X-OpenRosa-Version: schema: type: string content: text/xml: example: | <?xml version="1.0" encoding="UTF-8"?> <manifest xmlns="http://openrosa.org/xforms/xformsManifest"> <mediaFile> <filename>question.jpg</filename> <hash>md5:a64817a5688dd7c17563e32d4eb1cab2</hash> <downloadUrl>https://your.odk.server/v1/test/IeksRu1CNZs7!qjAot2T17dPzkrw9B4iTtpj7OoIJBmXvnHM8z8Ka4QP/projects/7/forms/basic/draft/attachments/question.jpg</downloadUrl> </mediaFile> </manifest> 403: description: Forbidden headers: X-OpenRosa-Version: schema: type: string content: text/xml: example: | <OpenRosaResponse xmlns="http://openrosa.org/http/response" items="0"> <message nature="error">The authenticated actor does not have rights to perform that action.</message> </OpenRosaResponse> /v1/test/{token}/projects/{projectId}/forms/{xmlFormId}/draft/attachments/{filename}: get: tags: - Draft Testing Endpoints summary: Downloading a Form Attachment description: Identical to the [non-Draft version](/central-api-form-management/#downloading-a-form-attachment). operationId: Downloading a Form Attachment (Draft Form) parameters: - name: token in: path description: The authentication Draft Token associated with the Draft Form in question. required: true schema: type: string example: "IeksRu1CNZs7!qjAot2T17dPzkrw9B4iTtpj7OoIJBmXvnHM8z8Ka4QP" - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "7" - name: xmlFormId in: path description: The `xmlFormId` of the Form being referenced. required: true schema: type: string example: simple - name: filename in: path description: The name of the file as given by the Attachments listing resource. required: true schema: type: string example: file1.jpg responses: 200: description: OK headers: Content-Disposition: schema: type: string content: '{the MIME type of the attachment file itself}': example: | (binary data) 403: description: Forbidden content: '{the MIME type of the attachment file itself}': schema: required: - code type: object properties: code: type: string message: type: string application/json: schema: $ref: '#/components/schemas/Error403' /v1/projects/{projectId}/forms/{xmlFormId}.svc: get: tags: - OData Form Service summary: Service Document description: |- The Service Document is essentially the index of all available documents. From this document, you will find links to all other available information in this OData service. In particular, you will find the Metadata Document, as well as a data document for each table defined by the `Form`. You will always find a link to the `/Submissions` subpath, which is the data document that represents the "root" table, the data from each `Submission` that is not nested within any `repeat`s. This document is available only in JSON format. operationId: Service Document parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "7" - name: xmlFormId in: path description: The `xmlFormId` of the `Form` whose OData service you wish to access. required: true schema: type: string example: simple responses: 200: description: OK content: application/json; charset=utf-8; odata.metadata=minimal: schema: type: object properties: '@odata.context': type: string value: type: array items: required: - kind - name - url type: object properties: kind: type: string name: type: string url: type: string example: '@odata.context': https://your.odk.server/v1/projects/7/forms/sample.svc/$metadata value: - kind: EntitySet name: Submissions url: Submissions - kind: EntitySet name: Submissions.children.child url: Submissions.children.child example: '@odata.context': https://your.odk.server/v1/projects/7/forms/sample.svc/$metadata value: - kind: EntitySet name: Submissions url: Submissions - kind: EntitySet name: Submissions.children.child url: Submissions.children.child application/json: schema: type: object properties: '@odata.context': type: string value: type: array items: required: - kind - name - url type: object properties: kind: type: string name: type: string url: type: string example: '@odata.context': https://your.odk.server/v1/projects/7/forms/sample.svc/$metadata value: - kind: EntitySet name: Submissions url: Submissions - kind: EntitySet name: Submissions.children.child url: Submissions.children.child 403: description: Forbidden content: application/json; charset=utf-8; odata.metadata=minimal: schema: required: - code type: object properties: code: type: string message: type: string application/json: schema: $ref: '#/components/schemas/Error403' 406: description: Not Acceptable content: application/json; charset=utf-8; odata.metadata=minimal: schema: required: - code type: object properties: code: type: string message: type: string application/json: schema: required: - code type: object properties: code: type: string message: type: string example: code: "406.1" message: 'Requested format not acceptable; this resource allows: (application/json, json).' /v1/projects/{projectId}/forms/{xmlFormId}.svc/$metadata: get: tags: - OData Form Service summary: Metadata Document description: |- The Metadata Document describes, in [EDMX CSDL](http://docs.oasis-open.org/odata/odata-csdl-xml/v4.01/odata-csdl-xml-v4.01.html), the schema of all the data you can retrieve from the OData Form Service in question. This is essentially the XForms form schema translated into the OData format. EDMX/CSDL defines schemas in terms of objects, their properties, and relationships to other objects. If you are writing a tool to analyze your own data, whose schema you already know and understand, there is very little reason to touch this endpoint. You can likely skip ahead to the data documents themselves and work directly with the simple JSON output returned by those endpoints. This endpoint is more useful for authors of tools which seek to generically work with arbitrary data whose schemas they cannot know in advance. In general, the way we model the XForms schema in OData terms is to represent `group`s as `ComplexType`s, and `repeat`s as `EntityType`s. In the world of OData, the primary difference between these two types is that Entity Types require Primary Keys, while Complex Types do not. This fits well with the way XForms surveys tend to be structured. Most other types map to `String`. The exceptions are numbers, which map either to `Int64` or `Decimal` as appropriate, datetime fields which are always `DateTimeOffset`, date fields which become `Date`, and geography points which will appear as `GeographyPoint`, `GeographyLineString`, or `GeographyPolygon` given a `geopoint`, `geotrace`, or `geoshape`. We also advertise the relationships between tables (the point at which a `repeat` connects the parent data to the repeated subtable) using the `NavigationProperty`. This should allow clients to present the data in an interconnected way, without the user having to specify how the tables connect to each other. This implementation of the OData standard includes a set of Annotations describing the supported features of the service in the form of the [Capabilities Vocabulary](https://github.com/oasis-tcs/odata-vocabularies/blob/master/vocabularies/Org.OData.Capabilities.V1.md). In general, however, you can assume that the server supports the Minimal Conformance level and nothing beyond. While the latest 4.01 OData specification adds a new JSON EDMX CSDL format, most servers and clients do not yet support that format, and so for this release of ODK Central only the older XML EDMX CSDL format is available. operationId: Metadata Document parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "7" - name: xmlFormId in: path description: The `xmlFormId` of the `Form` whose OData service you wish to access. required: true schema: type: string example: simple responses: 200: description: OK content: application/xml: example: |2 <?xml version="1.0" encoding="UTF-8"?> <edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0"> <edmx:DataServices> <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="org.opendatakit.user.simple"> <EntityType Name="Submissions"> <Key><PropertyRef Name="__id"/></Key> <Property Name="__id" Type="Edm.String"/> <Property Name="meta" Type="org.opendatakit.user.simple.meta"/> <Property Name="name" Type="Edm.String"/> <Property Name="age" Type="Edm.Int64"/> </EntityType> <ComplexType Name="meta"> <Property Name="instanceID" Type="Edm.String"/> </ComplexType> <EntityContainer Name="simple"> <EntitySet Name="Submissions" EntityType="org.opendatakit.user.simple.Submissions"> <Annotation Term="Org.OData.Capabilities.V1.ConformanceLevel" EnumMember="Org.OData.Capabilities.V1.ConformanceLevelType/Minimal"/> <Annotation Term="Org.OData.Capabilities.V1.BatchSupported" Bool="false"/> <Annotation Term="Org.OData.Capabilities.V1.CountRestrictions"> <Record><PropertyValue Property="Countable" Bool="true"/></Record> </Annotation> <Annotation Term="Org.OData.Capabilities.V1.FilterFunctions"> <Record> <PropertyValue Property="NonCountableProperties"> <Collection> <String>eq</String> </Collection> </PropertyValue> </Record> </Annotation> <Annotation Term="Org.OData.Capabilities.V1.FilterFunctions"> <Record> <PropertyValue Property="Filterable" Bool="true"/> <PropertyValue Property="RequiresFilter" Bool="false"/> <PropertyValue Property="NonFilterableProperties"> <Collection> <PropertyPath>meta</PropertyPath> <PropertyPath>name</PropertyPath> <PropertyPath>age</PropertyPath> </Collection> </PropertyValue> </Record> </Annotation> <Annotation Term="Org.OData.Capabilities.V1.SortRestrictions"> <Record><PropertyValue Property="Sortable" Bool="false"/></Record> </Annotation> <Annotation Term="Org.OData.Capabilities.V1.ExpandRestrictions"> <Record><PropertyValue Property="Expandable" Bool="false"/></Record> </Annotation> </EntitySet> </EntityContainer> </Schema> </edmx:DataServices> </edmx:Edmx> 403: description: Forbidden content: application/xml: schema: required: - code type: object properties: code: type: string message: type: string application/json: schema: $ref: '#/components/schemas/Error403' 406: description: Not Acceptable content: application/xml: schema: required: - code type: object properties: code: type: string message: type: string application/json: schema: required: - code type: object properties: code: type: string message: type: string example: code: "406.1" message: 'Requested format not acceptable; this resource allows: (application/json, json).' /v1/projects/{projectId}/forms/{xmlFormId}.svc/{table}: get: tags: - OData Form Service summary: Data Document description: |- The data documents are JSON representations of each table of `Submission` data. They follow the [corresponding specification](http://docs.oasis-open.org/odata/odata-json-format/v4.01/odata-json-format-v4.01.html), but apart from the representation of geospatial data as GeoJSON rather than the ODK proprietary format, the output here should not be surprising. If you are looking for JSON output of Submission data, this is the best place to look. The `$top` and `$skip` querystring parameters, specified by OData, apply `limit` and `offset` operations to the data, respectively. The `$count` parameter, also an OData standard, will annotate the response data with the total row count, regardless of the scoping requested by `$top` and `$skip`. If `$top` parameter is provided in the request then the response will include `@odata.nextLink` that you can use as is to fetch the next set of data. As of ODK Central v2023.4, `@odata.nextLink` contains a `$skiptoken` (an opaque cursor), which allows you to page through Submissions with a consistent offset, even while new Submissions are being created. While paging is possible through these parameters, it will not greatly improve the performance of exporting data. ODK Central prefers to bulk-export all of its data at once if possible. As of ODK Central v1.1, the [`$filter` querystring parameter](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#_Toc31358948) is partially supported. In OData, you can use `$filter` to filter by certain data fields in the schema. The operators `lt`, `le`, `eq`, `ne`, `ge`, `gt`, `not`, `and`, and `or` are supported. The built-in functions `now`, `year`, `month`, `day`, `hour`, `minute`, `second` are supported. These supported elements may be combined in any way, but all other `$filter` features will cause an error. The fields you can query against are as follows: | Submission Metadata | REST API Name | OData Field Name | | --------------------------- | ------------- | ------------------------- | | Submitter Actor ID | `submitterId` | `__system/submitterId` | | Submission Timestamp | `createdAt` | `__system/submissionDate` | | Submission Update Timestamp | `updatedAt` | `__system/updatedAt` | | Review State | `reviewState` | `__system/reviewState` | You can use `$root` expression to filter subtables (repeats) by Submission Metadata, you'll have to prefix above fields by `$root/Submissions/` in the filter criteria. For example, to filter a repeat table by Submission Timestamp you can pass `$filter=$root/Submissions/__system/submissionDate gt 2020-01-31T23:59:59.999Z` in the query parameter. Note that the `submissionDate` has a time component. This means that any comparisons you make need to account for the full time of the submission. It might seem like `$filter=__system/submissionDate le 2020-01-31` would return all results on or before 31 Jan 2020, but in fact only submissions made before midnight of that day would be accepted. To include all of the month of January, you need to filter by either `$filter=__system/submissionDate le 2020-01-31T23:59:59.999Z` or `$filter=__system/submissionDate lt 2020-02-01`. Remember also that you can [query by a specific timezone](https://en.wikipedia.org/wiki/ISO_8601#Time_offsets_from_UTC). Please see the [OData documentation](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#_Toc31358948) on `$filter` [operations](http://docs.oasis-open.org/odata/odata/v4.01/cs01/part1-protocol/odata-v4.01-cs01-part1-protocol.html#sec_BuiltinFilterOperations) and [functions](http://docs.oasis-open.org/odata/odata/v4.01/cs01/part1-protocol/odata-v4.01-cs01-part1-protocol.html#sec_BuiltinQueryFunctions) for more information. As of ODK Central v1.2, you can use `%24expand=*` to expand all repeat repetitions. This is helpful if you'd rather get one nested JSON data payload of all hierarchical data, rather than retrieve each of repeat as a separate flat table with references. The _nonstandard_ `$wkt` querystring parameter may be set to `true` to request that geospatial data is returned as a [Well-Known Text (WKT) string](https://en.wikipedia.org/wiki/Well-known_text) rather than a GeoJSON structure. This exists primarily to support Tableau, which cannot yet read GeoJSON, but you may find it useful as well depending on your mapping software. **Please note** that both GeoJSON and WKT follow a `(lon, lat, alt)` coördinate ordering rather than the ODK-proprietary `lat lon alt`. This is so that the values map neatly to `(x, y, z)`. GPS accuracy information is not a part of either standards specification, and so is presently omitted from OData output entirely. GeoJSON support may come in a future version. As of ODK Central v2022.3, the [`$select` query parameter](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#_Toc31358942) is supported with some limitations: + `$select` and `$expand` can't be used together. + Child properties of repeats can't be requested using `$select` As of ODK Central v2024.1, the [`$orderby` query parameter](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#_Toc31358952) is now supported, and can sort on the same fields as `$filter`, noted above. The order can be specified as `ASC` (ascending) or `DESC` (descending), which are case-insensitive. Multiple sort expressions can be used together, separated by commas, e.g. `$orderby=__system/submitterId ASC, __system/reviewState DESC`. As the vast majority of clients only support the JSON OData format, that is the only format ODK Central offers. operationId: Data Document parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "7" - name: xmlFormId in: path description: The `xmlFormId` of the `Form` whose OData service you wish to access. required: true schema: type: string example: simple - name: table in: path description: The name of the table to be returned. These names can be found in the output of the [Service Document](/central-api-odata-endpoints/#service-document). required: true schema: type: string example: Submissions - name: '%24skip' in: query description: If supplied, the first `$skip` rows will be omitted from the results. schema: type: number example: "10" - name: '%24top' in: query description: If supplied, only up to `$top` rows will be returned in the results. schema: type: number example: "5" - name: '%24count' in: query description: If set to `true`, an `@odata.count` property will be added to the result indicating the total number of rows, ignoring the above paging parameters. schema: type: boolean example: "true" - name: '%24wkt' in: query description: If set to `true`, geospatial data will be returned as Well-Known Text (WKT) strings rather than GeoJSON structures. schema: type: boolean example: "true" - name: '%24filter' in: query description: If provided, will filter responses to those matching the query. Only [certain fields](/central-api-odata-endpoints/#data-document) are available to reference. The operators `lt`, `le`, `eq`, `neq`, `ge`, `gt`, `not`, `and`, and `or` are supported, and the built-in functions `now`, `year`, `month`, `day`, `hour`, `minute`, `second`. schema: type: string example: year(__system/submissionDate) lt year(now()) - name: '%24orderby' in: query description: If provided, will sort responses according to specified order expression. Only the same fields as `$filter` above can be used to sort. Multiple expressions can be used together. schema: type: string example: __system/submitterId asc, __system/updatedAt desc - name: '%24expand' in: query description: Repetitions, which should get expanded. Currently, only `*` is implemented, which expands all repetitions. schema: type: string example: '*' - name: '%24select' in: query description: If provided, will return only the selected fields. schema: type: string example: __id, age, name, meta/instanceID - name: '%24skiptoken' in: query description: Opaque cursor from `@odata.nextLink` used for paging. schema: type: string responses: 200: description: OK content: application/json: schema: type: object properties: '@odata.context': type: string value: type: array items: required: - __id - age - meta - name type: object properties: __id: type: string age: type: number meta: type: object properties: instanceID: type: string name: type: string example: '@odata.context': https://your.odk.server/v1/projects/7/forms/simple.svc/$metadata#Submissions value: - __id: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 age: 25 meta: instanceID: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 name: Bob - __id: uuid:297000fd-8eb2-4232-8863-d25f82521b87 age: 30 meta: instanceID: uuid:297000fd-8eb2-4232-8863-d25f82521b87 name: Alice example: '@odata.context': https://your.odk.server/v1/projects/7/forms/simple.svc/$metadata#Submissions value: - __id: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 age: 25 meta: instanceID: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 name: Bob - __id: uuid:297000fd-8eb2-4232-8863-d25f82521b87 age: 30 meta: instanceID: uuid:297000fd-8eb2-4232-8863-d25f82521b87 name: Alice 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' 406: description: Not Acceptable content: application/json: schema: required: - code type: object properties: code: type: string message: type: string example: code: "406.1" message: 'Requested format not acceptable; this resource allows: (application/json, json).' 501: description: Not Implemented content: application/json: schema: required: - code type: object properties: code: type: string message: type: string example: code: "501.1" message: The requested feature $unsupported is not supported by this server. /#/dl/projects{projectId}/forms/{xmlFormId}/submissions/{instanceId}/attachments/{filename}: get: tags: - OData Form Service summary: Data Download Path description: |- _(introduced: version 1.2)_ This route is a web browser oriented endpoint intended for user-interactive usage only. It's not part of the Central API, but is documented here as it can be useful. If you are writing or configuring an OData client and have submission media files to deal with, you can run into authentication problems directly fetching or linking the media file URLs that are provided in the OData feed. This can be due to several reasons: if the user is not logged into the Central administration site (and thus has no valid cookie), if the request comes from a foreign origin (and thus cookies are not sent by the browser), and more. To help manage this, the frontend provides a `/#/dl` path that allows file download. Just take a normal attachment download path and replace the `/v1` near the beginning of the path with `/#/dl`, and the user will be taken to a page managed by the Central administration website that will ensure the user is logged in, and offer the file as a download. Because this `/#/dl` path returns a web page that causes a file download rather than directly returning the media file in question, it cannot be used to directly embed or retrieve these files, for example in a `<img>` tag. operationId: Data Download Path parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "7" - name: xmlFormId in: path description: The `xmlFormId` of the `Form` whose OData service you wish to access. required: true schema: type: string example: simple - name: instanceId in: path description: The `instanceId` of the Submission being referenced. required: true schema: type: string example: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 - name: filename in: path description: The name of the file to be retrieved. required: true schema: type: string example: file1.jpg responses: 200: description: OK content: text/html: example: | (html markup data) /v1/projects/{projectId}/datasets/{name}.svc: get: tags: - OData Dataset Service summary: Service Document description: |- The Service Document provides a link to the main source of information in this OData service: the list of `Entities` in this `Dataset`, as well as the Metadata Document describing the schema of this information. This document is available only in JSON format. operationId: Service Document for Datasets parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "7" - name: name in: path description: The `name` of the `Dataset` whose OData service you wish to access. required: true schema: type: string example: trees responses: 200: description: OK content: application/json; charset=utf-8; odata.metadata=minimal: schema: type: object properties: '@odata.context': type: string value: type: array items: required: - kind - name - url type: object properties: kind: type: string name: type: string url: type: string example: '@odata.context': https://your.odk.server/v1/projects/7/datasets/sample.svc/$metadata value: - kind: EntitySet name: Entities url: Entities - kind: EntitySet name: Entities.children.child url: Entities.children.child example: '@odata.context': https://your.odk.server/v1/projects/7/datasets/sample.svc/$metadata value: - kind: EntitySet name: Entities url: Entities - kind: EntitySet name: Entities.children.child url: Entities.children.child application/json: schema: type: object properties: '@odata.context': type: string value: type: array items: required: - kind - name - url type: object properties: kind: type: string name: type: string url: type: string example: '@odata.context': https://your.odk.server/v1/projects/7/datasets/sample.svc/$metadata value: - kind: EntitySet name: Entities url: Entities - kind: EntitySet name: Entities.children.child url: Entities.children.child 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' 406: description: Not Acceptable content: application/json: schema: required: - code type: object properties: code: type: string message: type: string example: code: "406.1" message: 'Requested format not acceptable; this resource allows: (application/json, json).' /v1/projects/{projectId}/datasets/{name}.svc/$metadata: get: tags: - OData Dataset Service summary: Metadata Document description: The Metadata Document describes, in [EDMX CSDL](http://docs.oasis-open.org/odata/odata-csdl-xml/v4.01/odata-csdl-xml-v4.01.html), the schema of all the data you can retrieve from the OData Dataset Service in question. Essentially, these are the Dataset properties, or the schema of each `Entity`, translated into the OData format. operationId: Metadata Document for Dataset parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: name in: path description: Name of the Dataset required: true schema: type: string example: people responses: 200: description: OK content: application/xml: example: | <?xml version="1.0" encoding="UTF-8"?> <edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0"> <edmx:DataServices> <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="org.opendatakit.entity"> <ComplexType Name="metadata"> <Property Name="createdAt" Type="Edm.DateTimeOffset"/> <Property Name="creatorId" Type="Edm.String"/> <Property Name="creatorName" Type="Edm.String"/> <Property Name="updates" Type="Edm.Int64"/> <Property Name="updatedAt" Type="Edm.DateTimeOffset"/> <Property Name="version" Type="Edm.Int64"/> <Property Name="conflict" Type="Edm.String"/> </ComplexType> </Schema> <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="org.opendatakit.user.trees"> <EntityType Name="Entities"> <Key> <PropertyRef Name="__id"/> </Key> <Property Name="__id" Type="Edm.String"/> <Property Name="__system" Type="org.opendatakit.entity.metadata"/> <Property Name="label" Type="Edm.String"/> <Property Name="geometry" Type="Edm.String"/> <Property Name="species" Type="Edm.String"/> <Property Name="circumference_cm" Type="Edm.String"/> </EntityType> <EntityContainer Name="trees"> <EntitySet Name="Entities" EntityType="org.opendatakit.user.trees.Entities"> <Annotation Term="Org.OData.Capabilities.V1.ConformanceLevel" EnumMember="Org.OData.Capabilities.V1.ConformanceLevelType/Minimal"/> <Annotation Term="Org.OData.Capabilities.V1.BatchSupported" Bool="false"/> <Annotation Term="Org.OData.Capabilities.V1.CountRestrictions"> <Record> <PropertyValue Property="Countable" Bool="true"/> </Record> </Annotation> <Annotation Term="Org.OData.Capabilities.V1.FilterFunctions"> <Record> <PropertyValue Property="NonCountableProperties"> <Collection> <String>eq</String> </Collection> </PropertyValue> </Record> </Annotation> <Annotation Term="Org.OData.Capabilities.V1.FilterFunctions"> <Record> <PropertyValue Property="Filterable" Bool="true"/> <PropertyValue Property="RequiresFilter" Bool="false"/> <PropertyValue Property="NonFilterableProperties"> <Collection> <PropertyPath>geometry</PropertyPath> <PropertyPath>species</PropertyPath> <PropertyPath>circumference_cm</PropertyPath> </Collection> </PropertyValue> </Record> </Annotation> <Annotation Term="Org.OData.Capabilities.V1.SortRestrictions"> <Record> <PropertyValue Property="Sortable" Bool="false"/> </Record> </Annotation> <Annotation Term="Org.OData.Capabilities.V1.ExpandRestrictions"> <Record> <PropertyValue Property="Expandable" Bool="false"/> </Record> </Annotation> </EntitySet> </EntityContainer> </Schema> </edmx:DataServices> </edmx:Edmx> 403: description: Forbidden content: application/xml: schema: required: - code type: object properties: code: type: string message: type: string application/json: schema: $ref: '#/components/schemas/Error403' 406: description: Not Acceptable content: application/xml: schema: required: - code type: object properties: code: type: string message: type: string application/json: schema: required: - code type: object properties: code: type: string message: type: string example: code: "406.1" message: 'Requested format not acceptable; this resource allows: (application/json, json).' /v1/projects/{projectId}/datasets/{name}.svc/Entities: get: tags: - OData Dataset Service summary: Data Document description: |- A data document is the straightforward JSON representation of all the `Entities` in a `Dataset`. The `$top` and `$skip` querystring parameters, specified by OData, apply `limit` and `offset` operations to the data, respectively. The `$count` parameter, also an OData standard, will annotate the response data with the total row count, regardless of the scoping requested by `$top` and `$skip`. If `$top` parameter is provided in the request then the response will include `@odata.nextLink` that you can use as is to fetch the next set of data. As of ODK Central v2023.4, `@odata.nextLink` contains a `$skiptoken` (an opaque cursor) to better paginate around deleted Entities. The [`$filter` querystring parameter](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#_Toc31358948) can be used to filter certain data fields in the system-level schema, but not the Dataset properties. The operators `lt`, `le`, `eq`, `ne`, `ge`, `gt`, `not`, `and`, and `or` are supported. The built-in functions `now`, `year`, `month`, `day`, `hour`, `minute`, `second` are supported. The fields you can query against are as follows: | Entity Metadata | OData Field Name | | ------------------------| -------------------- | | Entity Creator Actor ID | `__system/creatorId` | | Entity Timestamp | `__system/createdAt` | | Entity Update Timestamp | `__system/updatedAt` | | Entity Conflict | `__system/conflict` | Note that `createdAt` and `updatedAt` are time components. This means that any comparisons you make need to account for the full time of the entity. It might seem like `$filter=__system/createdAt le 2020-01-31` would return all results on or before 31 Jan 2020, but in fact only entities made before midnight of that day would be accepted. To include all of the month of January, you need to filter by either `$filter=__system/createdAt le 2020-01-31T23:59:59.999Z` or `$filter=__system/createdAt lt 2020-02-01`. Remember also that you can [query by a specific timezone](https://en.wikipedia.org/wiki/ISO_8601#Time_offsets_from_UTC). Please see the [OData documentation](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#_Toc31358948) on `$filter` [operations](http://docs.oasis-open.org/odata/odata/v4.01/cs01/part1-protocol/odata-v4.01-cs01-part1-protocol.html#sec_BuiltinFilterOperations) and [functions](http://docs.oasis-open.org/odata/odata/v4.01/cs01/part1-protocol/odata-v4.01-cs01-part1-protocol.html#sec_BuiltinQueryFunctions) for more information. The [`$select` query parameter](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#_Toc31358942) will return just the fields you specify and is supported on `__id`, `__system`, `__system/creatorId`, `__system/createdAt` and `__system/updatedAt`, as well as on user defined properties. The [`$orderby` query parameter](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#_Toc31358952) will return Entities sorted by different fields, which come from the same list used by `$filter`, as noted above. The order can be specified as `ASC` (ascending) or `DESC` (descending), which are case-insensitive. Multiple sort expressions can be used together, separated by commas, e.g. `$orderby=__system/creatorId ASC, __system/conflict DESC`. As the vast majority of clients only support the JSON OData format, that is the only format ODK Central offers. operationId: Data Document for Dataset parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: name in: path description: Name of the Dataset required: true schema: type: string example: people - name: '%24skip' in: query description: If supplied, the first `$skip` rows will be omitted from the results. schema: type: number example: "10" - name: '%24top' in: query description: If supplied, only up to `$top` rows will be returned in the results. schema: type: number example: "5" - name: '%24count' in: query description: If set to `true`, an `@odata.count` property will be added to the result indicating the total number of rows, ignoring the above paging parameters. schema: type: boolean example: "true" - name: '%24filter' in: query description: If provided, will filter responses to those matching the query. Only [certain fields](/central-api-odata-endpoints/#data-document) are available to reference. The operators `lt`, `le`, `eq`, `neq`, `ge`, `gt`, `not`, `and`, and `or` are supported, and the built-in functions `now`, `year`, `month`, `day`, `hour`, `minute`, `second`. schema: type: string example: year(__system/createdAt) lt year(now()) - name: '%24orderby' in: query description: If provided, will sort responses according to specified order expression. Only the same fields as `$filter` above can be used to sort. Multiple expressions can be used together. schema: type: string example: __system/creatorId asc, __system/updatedAt desc - name: '%24select' in: query description: If provided, will return only the selected fields. schema: type: string example: __id, label, name - name: '%24skiptoken' in: query description: Opaque cursor from `@odata.nextLink` used for paging. schema: type: string responses: 200: description: Ok content: application/json: schema: $ref: '#/components/schemas/EntityOdata' example: '@odata.context': https://your.odk.server/v1/projects/7/datasets/trees.svc/$metadata#Entities value: - __id: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 label: 25cm purpleheart geometry: 32.7413996 -117.1394617 53.80000305175781 13.933, species: purpleheart, circumference_cm: 2 __system: createdAt: '2022-12-09T19:41:16.478Z' creatorId: 39 creatorName: Tree surveyor updates: 1, updatedAt: '2023-04-31T19:41:16.478Z' version: 1 conflict: null - __id: aeebd746-3b1e-4a24-ba9d-ed6547bd5ff1 label: 345cm mora __system: createdAt: '2023-04-09T19:10:16.128Z' creatorId: 39 creatorName: Tree surveyor updates: 1, updatedAt: '2023-04-31T19:41:16.478Z' version: 2 conflict: null geometry: 47.722581 18.562111 0 0, species: mora, circumference_cm: 345 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' 406: description: Not Acceptable content: application/json: schema: required: - code type: object properties: code: type: string message: type: string example: code: "406.1" message: 'Requested format not acceptable; this resource allows: (application/json, json).' 501: description: Not Implemented content: application/json: schema: required: - code type: object properties: code: type: string message: type: string example: code: "501.1" message: The requested feature $unsupported is not supported by this server. /v1/projects/{projectId}/forms/{xmlFormId}/draft.svc: get: tags: - Draft Testing summary: Service Document description: Identical to [the non-Draft version](/central-api-odata-endpoints/#service-document) of this endpoint. operationId: Service Document for Dataset parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "7" - name: xmlFormId in: path description: The `xmlFormId` of the `Form` whose OData service you wish to access. required: true schema: type: string example: simple responses: 200: description: OK content: application/json; charset=utf-8; odata.metadata=minimal: schema: type: object properties: '@odata.context': type: string value: type: array items: required: - kind - name - url type: object properties: kind: type: string name: type: string url: type: string example: '@odata.context': https://your.odk.server/v1/projects/7/forms/sample.svc/$metadata value: - kind: EntitySet name: Submissions url: Submissions - kind: EntitySet name: Submissions.children.child url: Submissions.children.child example: '@odata.context': https://your.odk.server/v1/projects/7/forms/sample.svc/$metadata value: - kind: EntitySet name: Submissions url: Submissions - kind: EntitySet name: Submissions.children.child url: Submissions.children.child application/json: schema: type: object properties: '@odata.context': type: string value: type: array items: required: - kind - name - url type: object properties: kind: type: string name: type: string url: type: string example: '@odata.context': https://your.odk.server/v1/projects/7/forms/sample.svc/$metadata value: - kind: EntitySet name: Submissions url: Submissions - kind: EntitySet name: Submissions.children.child url: Submissions.children.child 403: description: Forbidden content: application/json; charset=utf-8; odata.metadata=minimal: schema: required: - code type: object properties: code: type: string message: type: string application/json: schema: $ref: '#/components/schemas/Error403' 406: description: Not Acceptable content: application/json; charset=utf-8; odata.metadata=minimal: schema: required: - code type: object properties: code: type: string message: type: string application/json: schema: required: - code type: object properties: code: type: string message: type: string example: code: "406.1" message: 'Requested format not acceptable; this resource allows: (application/json, json).' /v1/projects/{projectId}/forms/{xmlFormId}/draft.svc/$metadata: get: tags: - Draft Testing summary: Metadata Document description: Identical to [the non-Draft version](/central-api-odata-endpoints/#metadata-document) of this endpoint. operationId: Metadata Document (Draft Form) parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the `Form` whose OData service you wish to access. required: true schema: type: string example: simple responses: 200: description: OK content: application/xml: example: |2 <?xml version="1.0" encoding="UTF-8"?> <edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0"> <edmx:DataServices> <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="org.opendatakit.user.simple"> <EntityType Name="Submissions"> <Key><PropertyRef Name="__id"/></Key> <Property Name="__id" Type="Edm.String"/> <Property Name="meta" Type="org.opendatakit.user.simple.meta"/> <Property Name="name" Type="Edm.String"/> <Property Name="age" Type="Edm.Int64"/> </EntityType> <ComplexType Name="meta"> <Property Name="instanceID" Type="Edm.String"/> </ComplexType> <EntityContainer Name="simple"> <EntitySet Name="Submissions" EntityType="org.opendatakit.user.simple.Submissions"> <Annotation Term="Org.OData.Capabilities.V1.ConformanceLevel" EnumMember="Org.OData.Capabilities.V1.ConformanceLevelType/Minimal"/> <Annotation Term="Org.OData.Capabilities.V1.BatchSupported" Bool="false"/> <Annotation Term="Org.OData.Capabilities.V1.CountRestrictions"> <Record><PropertyValue Property="Countable" Bool="true"/></Record> </Annotation> <Annotation Term="Org.OData.Capabilities.V1.FilterFunctions"> <Record> <PropertyValue Property="NonCountableProperties"> <Collection> <String>eq</String> </Collection> </PropertyValue> </Record> </Annotation> <Annotation Term="Org.OData.Capabilities.V1.FilterFunctions"> <Record> <PropertyValue Property="Filterable" Bool="true"/> <PropertyValue Property="RequiresFilter" Bool="false"/> <PropertyValue Property="NonFilterableProperties"> <Collection> <PropertyPath>meta</PropertyPath> <PropertyPath>name</PropertyPath> <PropertyPath>age</PropertyPath> </Collection> </PropertyValue> </Record> </Annotation> <Annotation Term="Org.OData.Capabilities.V1.SortRestrictions"> <Record><PropertyValue Property="Sortable" Bool="false"/></Record> </Annotation> <Annotation Term="Org.OData.Capabilities.V1.ExpandRestrictions"> <Record><PropertyValue Property="Expandable" Bool="false"/></Record> </Annotation> </EntitySet> </EntityContainer> </Schema> </edmx:DataServices> </edmx:Edmx> 403: description: Forbidden content: application/xml: schema: required: - code type: object properties: code: type: string message: type: string application/json: schema: $ref: '#/components/schemas/Error403' 406: description: Not Acceptable content: application/xml: schema: required: - code type: object properties: code: type: string message: type: string application/json: schema: required: - code type: object properties: code: type: string message: type: string example: code: "406.1" message: 'Requested format not acceptable; this resource allows: (application/json, json).' /v1/projects/{projectId}/forms/{xmlFormId}/draft.svc/{table}: get: tags: - Draft Testing summary: Data Document description: Identical to [the non-Draft version](/central-api-odata-endpoints/#data-document) of this endpoint. operationId: Data Document (Draft Form) parameters: - name: projectId in: path description: The numeric ID of the Project required: true schema: type: number example: "16" - name: xmlFormId in: path description: The `xmlFormId` of the `Form` whose OData service you wish to access. required: true schema: type: string example: simple - name: table in: path description: The name of the table to be returned. These names can be found in the output of the [Service Document](/central-api-odata-endpoints/#service-document). required: true schema: type: string example: Submissions - name: '%24skip' in: query description: If supplied, the first `$skip` rows will be omitted from the results. schema: type: number example: "10" - name: '%24top' in: query description: If supplied, only up to `$top` rows will be returned in the results. schema: type: number example: "5" - name: '%24count' in: query description: If set to `true`, an `@odata.count` property will be added to the result indicating the total number of rows, ignoring the above paging parameters. schema: type: boolean example: "true" - name: '%24wkt' in: query description: If set to `true`, geospatial data will be returned as Well-Known Text (WKT) strings rather than GeoJSON structures. schema: type: boolean example: "true" - name: '%24filter' in: query description: If provided, will filter responses to those matching the query. Only [certain fields](/central-api-odata-endpoints/#data-document) are available to reference. The operators `lt`, `le`, `eq`, `neq`, `ge`, `gt`, `not`, `and`, and `or` are supported, and the built-in functions `now`, `year`, `month`, `day`, `hour`, `minute`, `second`. schema: type: string example: year(__system/submissionDate) lt year(now()) - name: '%24expand' in: query description: Repetitions, which should get expanded. Currently, only `*` is implemented, which expands all repetitions. schema: type: string example: '*' - name: '%24select' in: query description: If provided, will return only the selected fields. schema: type: string example: __id, age, name, meta/instanceID responses: 200: description: OK content: application/json: schema: type: object properties: '@odata.context': type: string value: type: array items: required: - __id - age - meta - name type: object properties: __id: type: string age: type: number meta: type: object properties: instanceID: type: string name: type: string example: '@odata.context': https://your.odk.server/v1/projects/7/forms/simple.svc/$metadata#Submissions value: - __id: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 age: 25 meta: instanceID: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 name: Bob - __id: uuid:297000fd-8eb2-4232-8863-d25f82521b87 age: 30 meta: instanceID: uuid:297000fd-8eb2-4232-8863-d25f82521b87 name: Alice example: '@odata.context': https://your.odk.server/v1/projects/7/forms/simple.svc/$metadata#Submissions value: - __id: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 age: 25 meta: instanceID: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 name: Bob - __id: uuid:297000fd-8eb2-4232-8863-d25f82521b87 age: 30 meta: instanceID: uuid:297000fd-8eb2-4232-8863-d25f82521b87 name: Alice 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' 406: description: Not Acceptable content: application/json: schema: required: - code type: object properties: code: type: string message: type: string example: code: "406.1" message: 'Requested format not acceptable; this resource allows: (application/json, json).' 501: description: Not Implemented content: application/json: schema: required: - code type: object properties: code: type: string message: type: string example: code: "501.1" message: The requested feature $unsupported is not supported by this server. /v1/config/analytics: get: tags: - Usage Reporting Configuration summary: Getting the current configuration description: If the Usage Reporting configuration is not set, this endpoint will return a `404`. Once the configuration is set, this endpoint will indicate whether the server will share usage data with the Central team. If the server will share usage data, and contact information was provided, this endpoint will also return the provided work email address and organization name. operationId: Getting the current configuration responses: 200: description: OK content: application/json: schema: required: - key - setAt - value type: object properties: key: type: string description: The type of system configuration. setAt: type: string description: ISO date format. The last time this system configuration was set. value: required: - enabled type: object properties: enabled: type: boolean description: '`true` if the server will share usage data with the Central team and `false` if not.' email: type: string description: The work email address to include with the metrics report. organization: type: string description: The organization name to include with the metrics report. description: Details about the Usage Reporting configuration. example: key: some_type setAt: 2018-01-06T00:32:52.787Z value: enabled: true email: my.email.address@getodk.org organization: Organization Name 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' 404: description: Not Found content: application/json: schema: required: - code type: object properties: code: type: string message: type: string example: code: "404.1" message: Could not find the resource you were looking for. post: tags: - Usage Reporting Configuration summary: Setting a new configuration description: |- An Administrator can use this endpoint to choose whether the server will share anonymous usage data with the Central team. This configuration affects the entire server. Until the Usage Reporting configuration is set, Administrators will see a message on the Central administration website that provides further information. If an Administrator specifies `true` for `enabled`, the server will share anonymous usage data monthly with the Central team. By specifying `true`, the Administrator accepts the [Terms of Service](https://getodk.org/legal/tos) and [Privacy Policy](https://getodk.org/legal/privacy). The Administrator can also share contact information to include with the report. If an Administrator specifies `false` for `enabled`, the server will not share anonymous usage data with the Central team. Administrators will no longer see the message on the administration website. If the Usage Reporting configuration is already set, the current configuration will be overwritten with the new one. operationId: Setting a new configuration requestBody: content: '*/*': schema: required: - enabled type: object properties: enabled: type: boolean description: See above. email: type: string description: A work email address to include with the metrics report. organization: type: string description: An organization name to include with the metrics report. example: enabled: true email: my.email.address@getodk.org organization: Organization Name required: false responses: 200: description: OK content: application/json: schema: required: - key - setAt - value type: object properties: key: type: string description: The type of system configuration. setAt: type: string description: ISO date format. The last time this system configuration was set. value: required: - enabled type: object properties: enabled: type: boolean description: '`true` if the server will share usage data with the Central team and `false` if not.' email: type: string description: The work email address to include with the metrics report. organization: type: string description: The organization name to include with the metrics report. description: Details about the Usage Reporting configuration. example: key: some_type setAt: 2018-01-06T00:32:52.787Z value: enabled: true email: my.email.address@getodk.org organization: Organization Name 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' x-codegen-request-body-name: body delete: tags: - Usage Reporting Configuration summary: Unsetting the current configuration description: If the Usage Reporting configuration is unset, Administrators will once again see a message on the the Central administration website. operationId: Unsetting the current configuration responses: 200: description: OK content: application/json: schema: $ref: '#/components/schemas/Success' 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/analytics/preview: get: tags: - Usage Report Preview summary: Getting the Usage Report preview description: An Administrator can use this endpoint to preview the metrics being sent. The preview is computed on the fly and represents what the report would look like if sent at that time. This endpoint does not directly submit the Usage Report; that is handled internally as a scheduled Central task. operationId: Getting the Usage Report preview responses: 200: description: OK content: {} 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/audits: get: tags: - Server Audit Logs summary: Getting Audit Log Entries description: |- This resource allows access to those log entries, with some paging and filtering options. These are provided by querystring parameters: `action` allows filtering by the action types listed above, `start` and `end` allow filtering by log timestamp (see below), and `limit` and `offset` control paging. If no paging parameters are given, the server will attempt to return every audit log entry that it has. The `start` and `end` parameters work based on exact timestamps, given in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format. It is possible to provide just a datestring (eg `2000-01-01`), in which case midnight will be inferred. But this value alone leaves the timezone unspecified. When no timezone is given, the server's local time will be used: the standard [Docker deployment](https://docs.getodk.org/central-install/) will always set server local time to UTC, but installations may have been customized, and there is no guarantee the UTC default hasn't been overridden. For this reason, **we recommend always setting a timezone** when querying based on `start` and `end`: either by appending a `z` to indicate UTC (eg `2000-01-01z`) or by explicitly specifying a timezone per ISO 8601 (eg `2000-01-01+08`). The same applies for full timestamps (eg `2000-01-01T12:12:12z`, `2000-01-01T12:12:12+08`). `start` may be given without `end`, and vice versa, in which case the timestamp filter will only be bounded on the specified side. They are both inclusive (`>=` and `<=`, respectively). This endpoint supports retrieving extended metadata; provide a header `X-Extended-Metadata: true` to additionally expand the `actorId` into full `actor` details, and `acteeId` into full `actee` details. The `actor` will always be an Actor, but the `actee` may be an Actor, a Project, a Form, or some other type of object depending on the type of action. operationId: Getting Audit Log Entries parameters: - name: action in: query description: The name of the `action` to filter by. schema: type: string example: form.create - name: start in: query description: The timestamp before which log entries are to be filtered out. schema: type: string example: 2000-01-01z - name: end in: query description: The timestamp after which log entries are to be filtered out. schema: type: string example: 2000-12-31T23:59.999z - name: limit in: query description: The maximum number of entries to return. schema: type: number example: "100" - name: offset in: query description: The zero-indexed number of entries to skip from the result. schema: type: number example: "200" responses: 200: description: OK content: application/json: schema: type: array items: $ref: '#/components/schemas/Audit' example: - actorId: 42 action: user.session.create details: userAgent: Mozilla/5.0 acteeId: 85cb9aff-005e-4edd-9739-dc9c1a829c44 loggedAt: 2018-04-18T23:19:14.802Z application/json; extended: schema: type: array items: $ref: '#/components/schemas/ExtendedAudit' example: - actorId: 42 action: form.create details: userAgent: Mozilla/5.0 acteeId: 85cb9aff-005e-4edd-9739-dc9c1a829c44 loggedAt: 2018-04-18T23:19:14.802Z actor: createdAt: 2018-04-18T23:19:14.802Z displayName: My Display Name id: 115 type: user updatedAt: 2018-04-18T23:42:11.406Z deletedAt: 2018-04-18T23:42:11.406Z 400: description: Bad Request content: application/json: schema: $ref: '#/components/schemas/Error400' example: code: "400" message: Could not parse the given data (2 chars) as json. 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' /v1/backup: post: tags: - Direct Backup summary: Using an Encryption Passphrase description: |- Use the `POST` verb to start a direct download ad-hoc backup. You will want to supply a `passphrase` with your chosen encryption passphrase. It is possible to omit this, in which case the backup will still be encrypted, but it will decrypt given an empty passphrase. Please see the section notes above about the long-running nature of this endpoint. operationId: Using an Encryption Passphrase requestBody: content: '*/*': schema: type: object properties: passphrase: type: string description: The passphrase with which to encrypt the backup. example: passphrase: my-password required: false responses: 200: description: OK headers: Content-Disposition: schema: type: string content: {} 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error403' x-codegen-request-body-name: body components: schemas: Actor: required: - createdAt - displayName - id - type type: object properties: createdAt: type: string description: ISO date format example: 2018-04-18T23:19:14.802Z displayName: type: string description: All `Actor`s, regardless of type, have a display name example: My Display Name id: type: number example: 115.0 type: $ref: '#/components/schemas/ActorType' updatedAt: type: string description: ISO date format example: 2018-04-18T23:42:11.406Z deletedAt: type: string description: ISO date format example: 2018-04-18T23:42:11.406Z ActorType: type: string description: The type of actor enum: - user - field_key - public_link - singleUse User: allOf: - $ref: '#/components/schemas/Actor' - type: object properties: email: type: string description: The email address of the user example: AppUser: allOf: - $ref: '#/components/schemas/Actor' - type: object properties: token: type: string description: If present, this is the Token that can be used to authenticate a request as this `App User`. If not present, this `App User`'s access has been revoked. example: d1!E2GVHgpr4h9bpxxtqUJ7EVJ1Q$Dusm2RBXg8XyVJMCBCbvyE8cGacxUx3bcUT projectId: type: number description: The ID of the `Project` that this `App User` is bound to. example: 1 ExtendedAppUser: allOf: - $ref: '#/components/schemas/AppUser' - type: object properties: createdBy: allOf: - $ref: '#/components/schemas/Actor' description: The `Actor` that created this `App User` lastUsed: type: string description: ISO date format. The last time this `App User` was used to authenticate a request. example: 2018-04-14T08:34:21.633Z Role: type: object properties: id: type: number example: 4 description: The numerical ID of the Role. name: type: string example: Project Manager description: The human-readable name for the Role. system: type: string example: manager description: The system name of the Role. Roles that have system names may not be modified. verbs: type: array items: type: string example: - project.update - project.delete description: The array of string verbs this Role confers. createdAt: type: string description: ISO date format example: 2018-04-18T23:42:11.406Z updatedAt: type: string description: ISO date format example: 2018-09-18T23:42:11.406Z Assignment: type: object properties: actorId: type: number example: 42 description: The numeric Actor ID being assigned. roleId: type: number example: 4 description: The numeric Role ID being assigned. ExtendedAssignment: type: object properties: actor: allOf: - $ref: '#/components/schemas/Actor' description: The full Actor data for this assignment. roleId: type: number example: 4 description: The numeric Role ID being assigned. FormSummaryAssignment: type: object required: - actorId - xmlFormId - roleId properties: actorId: type: number example: 42 description: The numeric Actor ID being assigned. xmlFormId: type: string example: simple description: The `id` of the assigned form as given in its XForms XML definition roleId: type: number example: 4 description: The numeric Role ID being assigned. ExtendedFormSummaryAssignment: type: object required: - actor - xmlFormId - roleId properties: actor: $ref: '#/components/schemas/Actor' description: The full Actor data for this assignment. xmlFormId: type: string example: simple description: The `id` of the assigned form as given in its XForms XML definition roleId: type: number example: 4 description: The numeric Role ID being assigned. Project: type: object required: - name properties: id: type: number example: 1 description: The numerical ID of the Project. name: type: string example: Default Project description: The name of the Project. description: type: string example: Description of this Project to show on Central. description: The description of the Project, which is rendered as Markdown on Frontend. keyId: type: number example: 3 description: If managed encryption is enabled on the project, the numeric ID of the encryption key as tracked by Central is given here. archived: type: boolean description: Whether the Project is archived or not. `null` is equivalent to `false`. All this does is sort the Project to the bottom of the list and disable management features in the web management application. ExtendedProject: allOf: - $ref: '#/components/schemas/Project' - type: object required: - appUsers - forms - datasets properties: appUsers: type: number example: 4 description: The number of App Users created within this Project. forms: type: number example: 7 description: The number of forms within this Project. lastSubmission: type: string example: '2018-04-18T03:04:51.695Z' description: ISO date format. The timestamp of the most recent submission to any form in this project, if any. datasets: type: number example: 2 description: The number of Datasets within this Project. ExtendedProjectWithVerbs: allOf: - $ref: '#/components/schemas/ExtendedProject' - type: object properties: verbs: type: array items: type: string example: - "form.create" - "form.delete" description: The array of string verbs the authenticated Actor may perform on and within this Project. EntitySummaryFields: type: object properties: uuid: type: string description: The `uuid` of the Entity that uniquely identifies the Entity. example: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 createdAt: type: string description: ISO date format. The time that the server received the Entity. example: 2018-04-18T23:42:11.406Z updatedAt: type: string description: Timestamp of the last update in ISO date format. `null` when there is only one version of the Entity. example: 2018-04-18T23:42:11.406Z deletedAt: type: string description: Timestamp of the deletion in ISO date format. `null` if the Entity is not deleted. example: 2018-04-18T23:42:11.406Z creatorId: type: number description: The ID of the Actor (App User, User, or Public Link) that originally created the Entity. example: 1 conflict: type: string description: |- Type of the conflict. `hard`: baseVersion conflicts and multiple versions update the same property `soft`: baseVersion conflicts but data updates are independent enum: - soft - hard EntityVersionFields: type: object properties: label: type: string description: Label of the Entity example: John (88) current: type: boolean description: if the version is the latest one example: true creatorId: type: number description: The ID of the Actor (App User, User, or Public Link) that originally created the Entity. example: 1 userAgent: type: string description: The self-identified `userAgent` of the device that created the `Entity` version. example: Enketo/3.0.4 conflictingProperties: type: array description: list of properties updated offline simultaneously. items: type: string version: type: number description: The version number of the Entity. Each update increments this number. example: 2 baseVersion: type: number description: The version number of the version that was the "base version" of this version. The base version is the version that was shown to the data collector when they made their update. example: 1 EntitySummary: allOf: - $ref: '#/components/schemas/EntitySummaryFields' - type: object properties: currentVersion: $ref: '#/components/schemas/EntityVersionFields' ExtendedEntityVersionSummary: allOf: - $ref: '#/components/schemas/EntityVersionFields' - type: object properties: creator: $ref: '#/components/schemas/Actor' ExtendedEntitySummary: allOf: - $ref: '#/components/schemas/EntitySummaryFields' - type: object properties: currentVersion: $ref: '#/components/schemas/EntityVersionFields' creator: $ref: '#/components/schemas/Actor' Entity: allOf: - $ref: '#/components/schemas/EntitySummaryFields' - type: object properties: currentVersion: $ref: '#/components/schemas/EntityVersion' ExtendedEntity: allOf: - $ref: '#/components/schemas/EntitySummaryFields' - type: object properties: creator: $ref: '#/components/schemas/Actor' currentVersion: $ref: '#/components/schemas/EntityVersion' EntityVersion: allOf: - $ref: '#/components/schemas/EntityVersionFields' - type: object properties: data: $ref: '#/components/schemas/DataExample' dataReceived: $ref: '#/components/schemas/DataReceivedExample' ExtendedEntityVersion: allOf: - $ref: '#/components/schemas/EntityVersion' - type: object properties: creator: $ref: '#/components/schemas/Actor' EntityVersionFull: allOf: - $ref: '#/components/schemas/EntityVersion' - type: object properties: source: type: object description: The source of the Entity version, such as a Submission or an API request. This property is experimental and may change in the future. example: {event: {}, submission: {}} baseDiff: type: array description: List of properties that are different between this version and its base version. Includes the label if it differs between the two versions. example: ['name', 'age'] serverDiff: type: array description: List of properties that are different between this version and the previous version on the server. Includes the label if it differs between the two versions. example: ['name', 'age'] conflict: type: string description: Type of the conflict if this version causes a conflict; otherwise `null` enum: - soft - hard resolved: type: boolean description: Is the conflict resolved? Note that this is also false for the version which didn't cause a conflict example: false lastGoodVersion: type: boolean description: Indicates whether this version is the last known good version. Currently, the last known good version is defined as the version immediately prior to the first unresolved conflict. If there is no conflict, or if all conflicts are resolved, then the current version is the last known good version. This property is experimental, as the definition of the last known good version may change in the future. example: false relevantToConflict: type: boolean description: Indicates whether this version includes information relevant to resolving a conflict. If so, it will be shown to the user during conflict resolution. This property is experimental, as we may redefine conflict relevance in the future. example: false ExtendedEntityVersionFull: allOf: - $ref: '#/components/schemas/EntityVersionFull' - type: object properties: creator: $ref: '#/components/schemas/Actor' EntityDiffValue: type: array items: $ref: '#/components/schemas/EntityDiffValueItems' EntityDiffValueItems: type: object properties: new: type: string description: The new value of this property. example: John old: type: string description: The old value of this property. example: Jane propertyName: type: string description: The name of the property that is changed. example: name EntityBulkSource: type: object properties: name: type: string description: A name to identify the bulk source, filename or API run example: myfile.csv size: type: number description: Optional, meant to indicate filesize (in MB) example: 100 description: An object describing the source of this bulk create action. EntityOdata: type: object properties: '@odata.context': type: string value: type: array items: type: object properties: __id: type: string label: type: string __system: type: object properties: createdAt: type: string creatorId: type: string creatorName: type: string updates: type: string updatedAt: type: string geometry: type: string species: type: string circumference_cm: type: string EntityCreateSingle: type: object properties: uuid: type: string description: (Optional) The `uuid` of the Entity that uniquely identifies the Entity. label: type: string description: Label of the Entity data: $ref: '#/components/schemas/DataExample' EntityCreateBulk: type: object properties: entities: type: array items: $ref: '#/components/schemas/EntityCreateSingle' description: A list of Entities source: $ref: '#/components/schemas/EntityBulkSource' DataExample: type: object properties: firstName: type: string example: John age: type: string example: '88' DataReceivedExample: allOf: - $ref: '#/components/schemas/DataExample' - type: object properties: label: type: string example: John (88) Form: required: - createdAt - hash - projectId - state - version - xmlFormId type: object properties: projectId: type: number description: The `id` of the project this form belongs to. example: 1.0 xmlFormId: type: string description: The `id` of this form as given in its XForms XML definition example: simple name: type: string description: The friendly name of this form. It is given by the `<title>` in the XForms XML definition. example: Simple version: type: string description: The `version` of this form as given in its XForms XML definition. If no `version` was specified in the Form, a blank string will be given. example: "2.1" enketoId: type: string description: If it exists, this is the survey ID of this Form on Enketo at `/-`. This will be the ID of the published version if it exists, otherwise it will be the draft ID. Only a cookie-authenticated user may access the preview through Enketo. example: abcdef hash: type: string description: An MD5 sum automatically computed based on the XForms XML definition. This is required for OpenRosa compliance. example: 51a93eab3a1974dbffc4c7913fa5a16a keyId: type: number description: If a public encryption key is present on the form, its numeric ID as tracked by Central is given here. example: 3.0 state: $ref: '#/components/schemas/FormState' publishedAt: type: string description: Indicates when a draft has most recently been published for this Form. If this value is `null`, this Form has never been published yet, and contains only a draft. example: 2018-01-21T00:04:11.153Z createdAt: type: string description: ISO date format example: 2018-01-19T23:58:03.395Z updatedAt: type: string description: ISO date format example: 2018-03-21T12:45:02.312Z ExtendedForm: allOf: - $ref: '#/components/schemas/Form' - type: object required: - submissions - reviewStates - entityRelated properties: submissions: type: number example: 10 description: The number of `Submission`s that have been submitted to this `Form`. reviewStates: $ref: '#/components/schemas/ReviewStateCounts' description: Additional counts of the number of submissions in various states of review. lastSubmission: type: string example: '2018-04-18T03:04:51.695Z' description: ISO date format. The timestamp of the most recent submission, if any. createdBy: $ref: '#/components/schemas/Actor' description: The full information of the Actor who created this Form. excelContentType: type: string description: If the Form was created by uploading an Excel file, this field contains the MIME type of that file. entityRelated: type: boolean description: True only if this Form is related to a Dataset. In v2022.3, this means the Form's Submissions create Entities in a Dataset. In a future version, Submissions will also be able to update existing Entities. ExtendedFormVersion: allOf: - $ref: '#/components/schemas/Form' - type: object properties: publishedBy: $ref: '#/components/schemas/Actor' description: The full information of the Actor who published this version of the Form. excelContentType: type: string description: If the Form was created by uploading an Excel file, this field contains the MIME type of that file. FormAttachment: type: object required: - name - type - exists - blobExists - datasetExists properties: name: type: string example: myfile.mp3 description: The name of the file as specified in the XForm. type: $ref: '#/components/schemas/FormAttachmentType' description: The expected type of file as specified in the XForm. exists: type: boolean example: true description: True if the server has the file or the Attachment is linked to a Dataset, otherwise false. blobExists: type: boolean example: true description: Whether the server has the file or not. datasetExists: type: boolean example: true description: Whether attachment is linked to a Dataset. updatedAt: type: string example: '2018-03-21T12:45:02.312Z' description: ISO date format. The last time this file's binary content was set (POST) or cleared (DELETE). FormAttachmentType: type: string enum: - image - audio - video - file FormState: type: string enum: - open - closing - closed Forms: type: object DraftForm: allOf: - $ref: '#/components/schemas/Form' - required: - draftToken type: object properties: draftToken: type: string description: The test token to use to submit to this draft form. See [Draft Testing Endpoints](/central-api-submission-management/#draft-submissions). example: lSpAIeksRu1CNZs7!qjAot2T17dPzkrw9B4iTtpj7OoIJBmXvnHM8z8Ka4QPEjR7 enketoId: type: string description: If it exists, this is the survey ID of this draft Form on Enketo at `/-`. Authentication is not needed to access the draft form through Enketo. example: abcdef FormKeyValue: properties: xmlFormId: type: string description: The `id` of this form as given in its XForms XML definition example: simple name: type: string description: The friendly name of this form. It is given by the `<title>` in the XForms XML definition. Returns `xmlFormId` if there is no title in the form definition. example: Simple Dataset: required: - createdAt - name - projectId type: object properties: name: type: string description: The name of the Dataset example: people createdAt: type: string description: ISO date format. example: 2018-01-19T23:58:03.395Z projectId: type: number description: The numerical ID of the Project that the Dataset belongs to. example: 1 approvalRequired: type: boolean description: Control whether a Submission should be approved before an Entity is created from it. example: true ExtendedDataset: allOf: - $ref: '#/components/schemas/Dataset' - required: - entities type: object properties: lastEntity: type: string description: ISO date format. The timestamp of the most recent entity, if any. example: 2018-04-18T03:04:51.695Z entities: type: number description: The number of Entities in the Dataset. example: 10 conflicts: type: number description: The number of Entities that have conflicts. example: 10.0 PatchAttachment: required: - dataset type: object properties: dataset: type: boolean description: true for linking Dataset and false for unlinking Dataset. example: true PublicLink: allOf: - $ref: '#/components/schemas/Actor' - type: object properties: token: type: string example: d1!E2GVHgpr4h9bpxxtqUJ7EVJ1Q$Dusm2RBXg8XyVJMCBCbvyE8cGacxUx3bcUT description: If present, this is the Token to include as the `st` query parameter for this `Public Link`. If not present, this `Public Link` has been revoked. once: type: boolean description: If set to `true`, an Enketo [single submission survey](https://blog.enketo.org/single-submission-surveys/) will be created instead of a standard one, limiting respondents to a single submission each. ExtendedPublicLink: allOf: - $ref: '#/components/schemas/PublicLink' - type: object required: - createdBy properties: createdBy: $ref: '#/components/schemas/Actor' description: The full details about the `Actor` that created this `Public Link`. Key: type: object required: - id - public properties: id: type: number example: 1 description: The numerical ID of the Key. public: type: string example: bcFeKDF3Sg8W91Uf5uxaIlM2uK0cUN9tBSGoASbC4LeIPqx65+6zmjbgUnIyiLzIjrx4CAaf9Y9LG7TAu6wKPqfbH6ZAkJTFSfjLNovbKhpOQcmO5VZGGay6yvXrX1TFW6C6RLITy74erxfUAStdtpP4nraCYqQYqn5zD4/1OmgweJt5vzGXW2ch7lrROEQhXB9lK+bjEeWx8TFW/+6ha/oRLnl6a2RBRL6mhwy3PoByNTKndB2MP4TygCJ/Ini4ivk74iSqVnoeuNJR/xUcU+kaIpZEIjxpAS2VECJU9fZvS5Gt84e5wl/t7bUKu+dlh/cUgHfk6+6bwzqGQYOe5A== description: The base64-encoded public key, with PEM envelope removed. managed: type: boolean example: true description: If true, this is a key generated by Project managed encryption. If not, this key is self-supplied. hint: type: string example: it was a secret description: The hint, if given, related to a managed encryption key. DatasetDiff: type: object required: - name properties: name: type: string example: people description: The name of the Dataset. properties: type: array items: {} description: All properties of the Dataset. DraftDatasetDiff: type: object required: - name - isNew properties: name: type: string example: people description: The name of the Dataset. isNew: type: boolean example: true description: Whether or not this Dataset is new (will be created by publishing the Draft Form). properties: type: array items: {} description: All properties of the Dataset. Property: type: object required: - name - inForm properties: name: type: string example: first_name description: The name of the Property. inForm: type: boolean example: true description: Whether or not this Property is affected by the Form. DraftProperty: type: object required: - name - inForm - isNew properties: name: type: string example: first_name description: The name of the Property. inForm: type: boolean example: true description: Whether or not this Property is affected by the form. isNew: type: boolean example: true description: Whether or not this Property is new (will be created by publishing the Draft Form). PropertyDetailed: type: object required: - name - publishedAt properties: name: type: string example: the.age description: The name of the Property. odataName: type: string example: the_age description: The name of the property as it will appear in OData. OData property names can only contain alphanumeric characters and underscores. publishedAt: type: string example: '2018-01-21T00:04:11.153Z' description: Publishing timestamp of the form that defined this property for the first time. forms: type: array description: List of forms that create the property items: $ref: '#/components/schemas/FormKeyValue' DatasetMetadata: properties: linkedForms: type: array items: $ref: '#/components/schemas/FormKeyValue' description: Forms that consume data from the Dataset sourceForms: type: array items: $ref: '#/components/schemas/FormKeyValue' description: Forms that create Entities in the Dataset properties: type: array description: All properties of the Dataset items: $ref: '#/components/schemas/PropertyDetailed' Submission: type: object required: - instanceId - submitterId - createdAt properties: instanceId: type: string example: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 description: The `instanceId` of the `Submission`, given by the Submission XML. submitterId: type: number example: 23 description: The ID of the `Actor` (`App User`, `User`, or `Public Link`) that originally submitted this `Submission`. deviceId: type: string example: imei:123456 description: The self-identified `deviceId` of the device that collected the data, sent by it upon submission to the server. The initial submission `deviceId` will be returned here. userAgent: type: string example: Enketo/3.0.4 description: The self-identified `userAgent` of the device that collected the data, sent by it upon submission to the server. The initial submission `userAgent` will be returned here. reviewState: allOf: - $ref: '#/components/schemas/SubmissionReviewState' - type: object properties: {} description: The current review state of the submission. createdAt: type: string example: '2018-01-19T23:58:03.395Z' description: ISO date format. The time that the server received the Submission. updatedAt: type: string example: '2018-03-21T12:45:02.312Z' description: ISO date format. `null` when the Submission is first created, then updated when the Submission's XML data or metadata is updated. currentVersion: $ref: '#/components/schemas/SubmissionVersion' description: The current version of the `Submission`. SubmissionVersion: type: object required: - instanceId - submitterId - createdAt - current properties: instanceId: type: string example: uuid:85cb9aff-005e-4edd-9739-dc9c1a829c44 description: The `instanceId` of the `Submission` version, given by the Submission XML. instanceName: type: string example: village third house description: The `instanceName`, if any, given by the Submission XML in the metadata section. submitterId: type: number example: 23 description: The ID of the `Actor` (`App User`, `User`, or `Public Link`) that submitted this `Submission` version. deviceId: type: string example: imei:123456 description: The self-identified `deviceId` of the device that submitted the `Submission` version. userAgent: type: string example: Enketo/3.0.4 description: The self-identified `userAgent` of the device that submitted the `Submission` version. createdAt: type: string example: '2018-01-19T23:58:03.395Z' description: ISO date format. The time that the server received the `Submission` version. current: type: boolean example: true description: Whether the version is current or not. ExtendedSubmission: allOf: - $ref: '#/components/schemas/Submission' - type: object required: - submitter properties: submitter: $ref: '#/components/schemas/Actor' description: The full details of the `Actor` that submitted this `Submission`. ExtendedSubmissionVersion: allOf: - $ref: '#/components/schemas/SubmissionVersion' - type: object required: - submitter properties: submitter: $ref: '#/components/schemas/Actor' description: The full details of the `Actor` that submitted this version of the `Submission`. formVersion: type: string example: '1.0' description: The version of the form the submission version was created against. Only returned with specific Submission Version requests. ReviewStateCounts: type: object required: - received - hasIssues - edited properties: received: type: number example: 3 description: The number of submissions receieved with no other review state. hasIssues: type: number example: 2 description: The number of submissions marked as having issues. edited: type: number example: 1 description: The number of edited submissions. SubmissionAttachment: type: object required: - name - exists properties: name: type: string example: myfile.mp3 description: The name of the file as specified in the Submission XML. exists: type: boolean example: true description: Whether the server has the file or not. SubmissionReviewState: type: string enum: - 'null' - edited - hasIssues - rejected - approved SubmissionDiffValue: type: object properties: new: type: string description: The new value of this node, which can either be a simple string, or JSON string representing a larger structural change to the Submission XML. It can also be null if this field no longer exists in the Submission. old: type: string description: The old value of this node, with similar properties to `new`. It can be null if this field did not exist previously. path: type: array items: {} description: An array representing the path (XPath) in the Submission tree for this node. It does not include the outermost path `data`. For elements that are part of repeat groups, the path element is the node name and the index (starting at 0), e.g. ['child', 2] is the third child. Audit: type: object required: - action - loggedAt properties: actorId: type: number example: 42 description: The ID of the actor, if any, that initiated the action. action: type: string example: form.create description: The action that was taken. acteeId: type: string example: 85cb9aff-005e-4edd-9739-dc9c1a829c44 description: The ID of the permissioning object against which the action was taken. details: type: object properties: {} description: Additional details about the action that vary according to the type of action. loggedAt: type: string example: '2018-04-18T23:19:14.802Z' description: ISO date format ExtendedAudit: allOf: - $ref: '#/components/schemas/Audit' - type: object properties: actor: $ref: '#/components/schemas/Actor' description: The details of the actor given by `actorId`. actee: type: object properties: {} description: The details of the actee given by `acteeId`. Depending on the action type, this could be a number of object types, including an `Actor`, a `Project`, or a `Form`. Comment: type: object required: - body - actorId properties: body: type: string example: this is my comment description: The text of the comment. actorId: type: number example: 42 description: The ID of the Actor that made the comment. ExtendedComment: allOf: - $ref: '#/components/schemas/Comment' - type: object properties: actor: $ref: '#/components/schemas/Actor' description: The details of the actor given by `actorId`. Success: type: object required: - success properties: success: type: boolean example: success: true Error400: type: object required: - code properties: code: type: number example: 400 details: type: object properties: {} description: a subobject that contains programmatically readable details about this error message: type: string example: Could not parse the given data (2 chars) as json. Error401: type: object required: - code properties: code: type: number example: 401.2 message: type: string example: Could not authenticate with the provided credentials. Error403: type: object required: - code properties: code: type: number example: 403.1 message: type: string example: The authenticated actor does not have rights to perform that action. Error404: type: object required: - code properties: code: type: number example: 404.1 message: type: string example: Could not find the resource you were looking for. Error406: type: object required: - code properties: code: type: number example: 406.1 message: type: string example: 'Requested format not acceptable; this resource allows: (application/json, json).' Error409: type: object required: - code properties: code: type: number example: 409.1 message: type: string example: A resource already exists with id value(s) of 1. Error501: type: object required: - code properties: code: type: number example: 501.1 message: type: string example: The requested feature $unsupported is not supported by this server.