> For the complete documentation index, see [llms.txt](https://docs.tryterra.co/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.tryterra.co/developer-tools/terra-cli/raw-requests.md).

# Raw API requests

Reach any Terra admin API or data API endpoint by path with terra api and terra data-api.

`terra api <path>` sends a request to any endpoint on the admin API, including ones without a generated command. `terra data-api <path>` is the same command pointed at the data API, which has no generated commands at all.

```bash
terra api /me
terra api /environments -q limit=5
terra api /environments -X POST -d dev_id=dev-new -d name=Staging
terra api /company -X PATCH --body '{"display_name":"Acme"}'
terra api /tokens/tok_123 -X DELETE
```

The path is relative to the configured base URL and must start with `/`.

Reach for a generated command first. It validates input before sending, formats output, and knows which operations are destructive. Use `terra api` for endpoints with no command yet, or to see exactly what the API returns.

## Two APIs

|            | Admin API                                                                                           | Data API                                                 |
| ---------- | --------------------------------------------------------------------------------------------------- | -------------------------------------------------------- |
| Covers     | Your account: environments, API keys, providers, destinations, users, webhook events, team, billing | Your users' health data and the flow that connects them  |
| Credential | Admin token from `terra login`                                                                      | Environment API key, fetched for you by `terra data-api` |
| Commands   | Generated commands such as `terra environments list`, plus `terra api <path>`                       | `terra data-api <path>` only                             |

Most commands use the admin API. The two credentials are not interchangeable.

## Which endpoints have a command

```bash
terra api list              # every admin endpoint, and the command covering it
terra api list --uncovered  # only endpoints with no command
terra api list --data-api   # the data API's endpoints
```

Name a path to see what one endpoint takes. With `--format json`, that is the full description: parameters, body fields, and response fields.

```bash
terra api list /me --format json
terra api list --data-api /sleep --format json
```

## Method

`-X`, `--method` takes GET, POST, PUT, PATCH, or DELETE, and defaults to GET. A body flag does not change the method. `terra api /environments -d dev_id=x` is a usage error rather than an inferred POST, so a command that reads like a query cannot turn out to be a mutation.

## Body, query, and headers

Three ways to send a body. They are mutually exclusive.

```bash
-d key=value            # repeatable, builds a flat JSON object
--body '{"a":{"b":1}}'  # raw JSON, for anything nested
--body-file body.json   # from a file, or - for stdin
```

```bash
-q key=value    # query parameter, repeatable
-H name:value   # header, repeatable
```

## Validation

The path and method are checked against the pinned API description before anything is sent. A typo is answered with the endpoint you probably meant rather than a 404.

```
$ terra data-api /sleeep
terra: /sleeep is not an endpoint on the data API. Did you mean "/sleep"?
```

Nothing else is checked. Query and body values are sent as typed and the API decides. The description can lag what is deployed, so `--no-verify` sends the request exactly as typed. That is what an endpoint newer than the pin needs.

## Pagination and inspection

`--paginate` collects a cursor-paginated list and renders one document in the selected format. It buffers records before printing, including for `--format ndjson`. It needs `--method GET`. `--max-pages` caps it at 10 pages by default, and `0` removes the limit.

```bash
terra api /environments --paginate
```

`-i` prints the status line and response headers to stderr, so the body stays pipeable. They print for a failed request too.

```bash
terra api /me -i | jq .token_id
```

`--jq` filters the response. There is no `--select` on the raw commands, because the response fields are not known for every path.

A DELETE confirms before it is sent. Pass `--yes` to skip the prompt, which is required where there is no terminal.

## The data API

The data API is the other half of Terra: the wearable data your users' providers send (activity, sleep, body, daily, nutrition, workouts) and the flow that links a user to a provider.

```bash
terra data-api /integrations
terra data-api /userInfo -q user_id=8f2a1c00-0000-4000-8000-000000000001
terra data-api /sleep -q user_id=8f2a1c00-0000-4000-8000-000000000001 -q start_date=2026-08-01 -q to_webhook=false
terra data-api /auth/generateWidgetSession -X POST -d reference_id=user-42
```

The identifiers above are examples; replace them with your user's ID. `/auth/generateWidgetSession` is a legacy endpoint. Terra accounts created after 3 September 2026 receive HTTP 410 and must use `POST https://access.tryterra.co/api/widget/session` instead. See [Terra widget setup](https://docs.tryterra.co/unified-api/user-authentication/implementation-terra-widget).

Two things differ from `terra api`.

**Requests target one environment.** The command takes `--env` and resolves it as any generated command does: the flag, then `TERRA_ENV`, then the configured default.

**The credential is the environment's API key**, not your admin token. The CLI fetches the key for you, which needs the `keys:read` scope. The default `terra login` leaves that scope out, so either log in again with `terra login --scope keys:read`, or set `TERRA_API_KEY` to supply the key directly and skip the lookup. The key is only ever sent, never printed.

{% hint style="warning" %}
Reading data needs `-q to_webhook=false`. The API's default is to send the response to your configured webhook and answer with an acknowledgement. The CLI recognizes that acknowledgement and says so on stderr, but it does not add the parameter for you.
{% endhint %}

`TERRA_DATA_BASE_URL` points the data API somewhere else. Without it the address is derived from the configured base URL.
