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

# List entities

> List the brands this DataSource carries, by brand list

API versions: v1 (current) https://docs.odysseysignal.com/api/reference/list-entities.md

`GET /v1/signals/{signal_id}/datasources/{datasource_id}/entities`

A roster belongs to a brand list, not to a DataSet — the data project says how it is read and the same answer serves every DataSet scoped to that list. Grouped rather than flattened because a brand id is unique only within its list.

Authentication: an API key in `X-Api-Key`, or `Authorization: Bearer <token>`.

## Parameters

### Path parameters

- `signal_id` (string, required)
- `datasource_id` (string, required)

## Example request

```bash
curl "https://api.odysseysignal.app/v1/signals/{signal_id}/datasources/{datasource_id}/entities" \
  -H "X-Api-Key: $ODYSSEY_API_KEY"
```

## Response 200

Content: `application/json`. The brands a DataSource carries, grouped by brand list.

**Grouped, never flattened.** A brand id is unique only *within* its list:
id 2 can be one brand under `primary` and another under `secondary`, so
there is no total roster. `count` is how many entries are listed, not how
many distinct brands exist.

The roster belongs to the brand list, so it is listed once here and serves
every DataSet scoped to that list.

- `environment` (string, nullable): The data environment the answer was read in, `prod` or `test`: the one Odyssey set on the Signal, or the one an Odyssey person picked for this call.
- `datasource_id` (string, required)
- `count` (integer, required)
- `brand_lists` (array of objects, required)
  - `id` (string, required): The brand list id. Also the suffix of a perception dataset id.
  - `label` (string, nullable): What the list is called.
  - `dataset_ids` (array of string, required): DataSets on this DataSource scoped to this list. More than one is normal — a perception dataset and the conversations dataset commonly share a roster.
  - `count` (integer, required)
  - `entities` (array of objects, required)
    - `id` (string or integer, required)
    - `label` (string, required)
    - `group` (string, nullable)
    - `type` (string, nullable)
    - `description` (string, nullable)
    - `demand_space` (object, nullable): For an attribute: the demand space the survey assigns it to. Absent where there is none.
      - `id` (integer, required)
      - `label` (string, required)

## Errors

Errors are `application/problem+json` (RFC 9457): `type`, `title`, `status`, `detail` and, for some, more fields that say how to fix the call. The `type` is `https://api.odysseysignal.app/problems/<code>`.

| Status | Code | When |
|---|---|---|
| 400 | `invalid-request` | The request is not valid for this DataSet; `detail` says why. |
| 401 | `unauthorized` | No credential, or one that is not accepted. |
| 403 | `forbidden` | The credential is valid but does not cover what was asked. |
| 404 | `not-found` | Nothing there, or nothing this credential may read. |
| 422 | `validation-failed` | The request does not match the contract; `errors` lists each field. |
| 429 | `rate_limited` | Too many requests, or the monthly quota is used up. |
| 503 | `unavailable` | A service behind the API did not answer; try again. |
