> ## Documentation Index
> Fetch the complete documentation index at: https://docs.corsair.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# CommCare plugin

> Global health data collection platform with CommCare HQ - list and read submitted forms and cases, manage mobile workers and groups, pull report data and lookup tables, submit XForms and run bulk form actions.

Use **CommCare** through Corsair: one client, typed API calls.

Generate an API key in CommCare HQ under Account Settings, API Keys (the key belongs to your CommCare username). Because ApiKey auth is user-scoped, every operation takes the project `domain` and that `username` as inputs. Things to know before you call:

* **API access needs a plan.** The JSON APIs require a Standard plan or above; on a free project they answer 401 "Your current subscription does not have access to this feature" (or 403). `ota.restore` is the exception: it works on a free project.
* **Every endpoint is scoped to one project.** All requests go to `https://www.commcarehq.org/a/{domain}/...`. There is no plugin-level `domain` or `username` option: pass both on every call.
* **Two pagination styles.** Most listings use `limit` and `offset` with a `meta.total_count`; `cases.list` pages oldest-to-newest by cursor: pass the `nextCursor` it answers as `cursor` until `nextCursor` is absent.
* **Async bulk actions.** `forms.bulkAction` accepts up to 5000 form ids for archive, unarchive or permanent delete, and answers a job id; follow with `forms.bulkActionStatus` until status is `complete` or `failed`. `complete` does not mean every form succeeded: compare `succeeded` with `requested` and read `skipped`. A form must be archived before it can be deleted.
* **Writes.** `submissions.submit` posts OpenRosa XForm XML to the receiver. HQ answers 201 even when it could not process the form; the call fails in that case (nature `submit_error` or `processing_failure`) and otherwise returns the `message` and its `nature`. `users.create` provisions a worker account with an initial password.
* **Delete is permanent.** `users.delete` removes a worker account, and `forms.bulkAction` with action `delete` permanently removes forms.
* **OTA restore auth.** `ota.restore` pulls the full case-restore XML. The docs show worker Basic credentials, but HQ also accepts the ApiKey header and restores the account that owns the key, so a web user's key returns that user's restore, not a mobile worker's. HQ puts the owner's password hash in the restore's registration block; the plugin replaces it with `[removed]` before returning the XML.

**What you get:**

* 32 typed API operations

## Setup

**1. Install**

```bash npm theme={null}
npm install corsair @corsair-dev/commcare better-sqlite3
npm install --save-dev @types/better-sqlite3
```

```bash yarn theme={null}
yarn add corsair @corsair-dev/commcare better-sqlite3
yarn add --dev @types/better-sqlite3
```

```bash pnpm theme={null}
pnpm install corsair @corsair-dev/commcare better-sqlite3
pnpm install --save-dev @types/better-sqlite3
```

```bash bun theme={null}
bun add corsair @corsair-dev/commcare better-sqlite3
bun add --dev @types/better-sqlite3
```

**2. Add the plugin**

```ts corsair.ts theme={null}
import Database from 'better-sqlite3';
import { createCorsair } from 'corsair';
import { commcare } from '@corsair-dev/commcare';

export const corsair = createCorsair({
	plugins: [
		commcare(),
	],
	database: new Database('corsair.db'),
	kek: process.env.CORSAIR_KEK!,
	multiTenancy: true,
	hub: {
		projectApiKey: process.env.CORSAIR_API_KEY!,
		signingSecret: process.env.CORSAIR_SIGNING_SECRET!,
	},
});
```

With `multiTenancy: true`, scope calls with `corsair.withTenant(id)`. See [Quick start](https://docs.corsair.dev/quick-start.md) for KEK + Hub keys, and [Multi-tenancy](https://docs.corsair.dev/concepts/multi-tenancy.md) for account isolation.

**3. Choose authentication**

> [tab] API Key (Recommended)
>
> No setup required yet. When you make your first request as a tenant, Corsair prompts for the API key.
>
> ```ts theme={null}
> commcare()
> ```
>
> More: [API Key](https://docs.corsair.dev/concepts/api-key)

**4. Connect a tenant**

Mint a connect link and send the tenant to it. Hub hosts the page and delivers the result to your app — see [Connect / OAuth](https://docs.corsair.dev/management/connect).

```ts theme={null}
const { connectUrl } = await corsair.manage.connect.createLink({
	plugin: 'commcare',
	tenantId: 'acme',
});
// redirect the user's browser to connectUrl
```

## Example API calls

**List open cases of a type**

```ts theme={null}
const tenant = corsair.withTenant('acme');
await tenant.commcare.api.cases.list({
	username: 'jdoe@my-project.commcarehq.org',
	domain: 'my-project',
	caseType: 'patient',
	closed: false,
});
```

**Add a mobile worker**

```ts theme={null}
const tenant = corsair.withTenant('acme');
await tenant.commcare.api.users.create({
	username: 'jdoe@my-project.commcarehq.org',
	domain: 'my-project',
	workerUsername: 'new.worker@my-project.commcarehq.org',
	password: 'change-me-1',
	firstName: 'Jordan',
	lastName: 'Lee',
});
```

See the full list on the [API](https://docs.corsair.dev/plugins/commcare/api.md) page.

## What's next

> [card] [API reference](https://docs.corsair.dev/plugins/commcare/api.md)
>
> Every `commcare.api.*` operation with input and output types.

> [card] [Connect / OAuth](https://docs.corsair.dev/management/connect)
>
> createLink, Hub delivery, and tenant connect flows.

> [card] [Use with agents](https://docs.corsair.dev/mcp-adapters/mcp-adapters)
>
> Expose this plugin's operations as MCP tools.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.