# List notes

`GET /notes`

- Base: `GET https://portal.watcheye.com.au/api/v1/notes`

Returns notes for the calling account. Results are paginated.

Notes are always attached to an entity (and the entity's program). Notes created in the
context of an event additionally carry an `event_uuid`. Use the filters to narrow to a
specific entity, program, event, or to a specific author or author type.

## Filters

The following filters can be applied via the `filter[...]` query parameters:

- `entity_uuid` - only notes for the given entity
- `event_uuid` - only notes attached to the given event
- `program_uuid` - only notes for entities in the given program
- `created_by` - one of `user` (only notes authored by any portal user on this account)
  or `api_key` (only notes authored by any API key on this account). Use this for the
  coarse "human vs automation" distinction.
- `created_by_user_uuid` - only notes authored by the given portal user. The uuid must
  be a user on the calling account; otherwise the result is an empty page.
- `created_by_api_key_uuid` - only notes authored by the given API key. The uuid must
  be an API key on the calling account; otherwise the result is an empty page.
- `created_at_from` - inclusive lower bound on note creation time (ISO 8601)
- `created_at_to` - inclusive upper bound on note creation time (ISO 8601)

The top-level `archived` query parameter accepts `true` (only archived) or `false` (only
non-archived); omitting it returns both. (Archive is a portal-only operation - the API
surfaces the state but does not currently expose archive/unarchive endpoints.)

Filters that target a uuid (entity, event, program) return an empty page when the target
uuid does not exist on the calling account, identical to the behaviour for a uuid that
does not exist at all.

## Sorting

The `sort` query parameter accepts `created_at` (default: `-created_at`, newest first) or
`updated_at`. Prefix with `-` for descending order.

## Parameters

| Name | In | Type | Description |
|------|----|------|-------------|
| `page` | query | integer | The page of results to return, starting at 1. Example: `1` |
| `per_page` | query | integer | The number of notes per page (defaults to 30, max 500) Example: `30` |
| `filter[entity_uuid]` | query | string (uuid) | Only records for the given entity. |
| `filter[event_uuid]` | query | string (uuid) | Only notes attached to the given event. |
| `filter[program_uuid]` | query | string (uuid) | Only records for entities in the given program. |
| `filter[created_by]` | query | string | Filter to notes authored by any portal user (`user`) or any API key (`api_key`) on this account. Enum: `user`, `api_key` |
| `filter[created_by_user_uuid]` | query | string (uuid) | Filter to notes authored by a specific portal user. |
| `filter[created_by_api_key_uuid]` | query | string (uuid) | Filter to notes authored by a specific API key. |
| `filter[created_at_from]` | query | string (date-time) | Inclusive lower bound on `created_at` (ISO 8601). Example: `2025-01-01T00:00:00Z` |
| `filter[created_at_to]` | query | string (date-time) | Inclusive upper bound on `created_at` (ISO 8601). Example: `2025-12-31T23:59:59Z` |
| `sort` | query | string | Field to sort by; prefix with `-` for descending order Enum: `created_at`, `-created_at`, `updated_at`, `-updated_at` Example: `-created_at` |
| `archived` | query | boolean | Filter by archive status. * `true` - only archived notes * `false` - only non-archived notes Note: The API will accept the string 'true' or the number 1 for true and the string 'false' or the number 0 for false as well as the boolean values. |

## Responses

### 200 Notes list response

Content type: `application/json`

| Field | Type | Description |
|-------|------|-------------|
| `data` | array of objects | An array of notes |
| `data[].uuid` | string (uuid) | The note's UUID Example: `7c1c0a8e-2b9f-4f0e-8d1a-1e2b3c4d5e6f` |
| `data[].note_number` | string | A short obfuscated public identifier for the note (e.g. "N-A1-B2C-3D4") Example: `N-A1-B2C-3D4` |
| `data[].note_text` | string | The free-text content of the note (max 5000 characters) Example: `Confirmed match against verified passport details.` |
| `data[].created_by` | object or null | Identifies who created the note. The `type` discriminator picks the shape of the remaining fields: * `{ type: "user", uuid, username }` - a portal user created the note. The portal user (or an account manager) can edit/delete it through the portal. The API cannot edit or delete user-authored notes. * `{ type: "api_key", uuid, label }` - an API key on this account created the note. The API can manage these notes via the PATCH and DELETE endpoints. The portal cannot edit or delete API-key-authored notes. * `null` - rare legacy notes from before actor attribution was recorded; treat as read-only. |
| `data[].created_by.type` | string | Discriminator for the actor type. Enum: `user`, `api_key` |
| `data[].created_by.uuid` | string (uuid) | UUID of the user or API key that created the note. |
| `data[].created_by.username` | string | Username of the portal user. Present only when `type` is `user`. |
| `data[].created_by.label` | string | Label of the API key. Present only when `type` is `api_key`. |
| `data[].is_immutable` | boolean | When true, the note is an immutable audit-trail entry and cannot be edited or deleted by any actor through any channel. PATCH and DELETE requests against an immutable note return 403. Example: `false` |
| `data[].entity_uuid` | string (uuid) | UUID of the entity this note is attached to |
| `data[].program_uuid` | string (uuid) | UUID of the program the entity belongs to |
| `data[].event_uuid` | string (uuid) or null | UUID of the event this note is attached to, if any. Notes created via the [Events PATCH](/docs/reference/event.update) endpoint with a `note` field carry an `event_uuid`; notes created via [POST /v1/entities/{uuid}/notes](/docs/reference/note.create) do not. |
| `data[].archived_at` | string (date-time) or null | ISO 8601 timestamp at which the note was archived in the portal (null if not archived) |
| `data[].created_at` | string (date-time) | Example: `2025-01-01T00:00:00Z` |
| `data[].updated_at` | string (date-time) | Example: `2025-01-01T00:00:00Z` |
| `meta` | object |  |
| `meta.current_page` | integer | Example: `1` |
| `meta.per_page` | integer | Example: `30` |
| `meta.total` | integer | Example: `1` |
| `meta.last_page` | integer | Example: `1` |
| `api_reference` | string (uuid) |  |

**Sample response**

```json
{
    "data": [
        {
            "uuid": "7c1c0a8e-2b9f-4f0e-8d1a-1e2b3c4d5e6f",
            "note_number": "N-A1-B2C-3D4",
            "note_text": "Confirmed match against verified passport details.",
            "created_by": {
                "type": "user",
                "uuid": "00000000-0000-0000-0000-000000000000",
                "username": "string",
                "label": "string"
            },
            "is_immutable": false,
            "entity_uuid": "00000000-0000-0000-0000-000000000000",
            "program_uuid": "00000000-0000-0000-0000-000000000000",
            "event_uuid": "00000000-0000-0000-0000-000000000000",
            "archived_at": "2024-01-01T00:00:00Z",
            "created_at": "2025-01-01T00:00:00Z",
            "updated_at": "2025-01-01T00:00:00Z"
        }
    ],
    "meta": {
        "current_page": 1,
        "per_page": 30,
        "total": 1,
        "last_page": 1
    },
    "api_reference": "00000000-0000-0000-0000-000000000000"
}
```

Standard error responses: 400, 401, 403, 429, 5XX (see [Common error responses](/docs/reference/general/common-error-responses.md))

