# List forms

`GET /v1/forms`

Requires an API key with the `forms:read` scope. [About keys and scopes](/docs/api/authentication)

Returns forms in this organization, leaving archived ones out unless `archived=true`. Pass `status` to list only forms in that state. Results are cursor-paginated: pass `meta.pagination.nextCursor` back as `cursor` until it comes back `null`. The cursor is opaque — do not construct or parse one.

## Query parameters

- `limit` (integer, optional, min > 0, max 100, default `20`)
- `cursor` (string, optional, 1–2048 characters)
- `q` (string, optional, 1–200 characters)
- `status` (string, optional, one of `draft`, `published`) — Only forms in this status.
- `archived` (string, optional, one of `true`, `false`, default `"false"`) — `true` lists archived forms only; unset or `false` leaves them out.

## Returns

Returns `200 OK` with a list of `FormListItem` objects in `data`, and the next page's cursor in `meta` (see [pagination](/docs/api/pagination)). Otherwise returns an error; [Errors](/docs/api/errors) lists every code and which to retry.

- `id` (string, required, uuid)
- `publicId` (string, required) — The id the public embed and hosted page use.
- `name` (string, required)
- `source` (string, required) — Recorded on each contact the form creates.
- `status` (string, required, one of `draft`, `published`) — Whether the form accepts submissions.
- `groupId` (string | null, required, uuid) — The group every submitter is added to.
- `fields` (object[], required) — The fields, top to bottom.
  - `key` (string, required) — Where the answer goes, such as `email` or `attributes.plan`.
  - `type` (string, required, one of `email`, `text`, `textarea`, `select`, `checkbox`, `date`, `phone`) — The input the visitor sees.
  - `label` (string, required) — The text shown beside the field.
  - `placeholder` (string, optional) — Hint text shown inside the empty field.
  - `required` (boolean, required) — Whether the visitor must fill it in.
  - `options` (object[], optional) — The choices of a `select` or `checkbox` field.
    - `value` (string, required)
    - `label` (string, required)
- `allowedOrigins` (string[], required) — Site origins the embed may load from.
- `doubleOptIn` (boolean, required) — Whether submitters must confirm by email before they are subscribed.
- `captcha` (object | null, required) — Where the CAPTCHA comes from; `null` while it is off. Secrets never show.
  - One of: **KiroraCaptchaSetting**
    - `mode` ("kirora", required)
  - One of: **OwnCaptchaSetting**
    - `mode` ("own", required)
    - `siteKey` (string, required)
- `archivedAt` (string | null, required, date-time) — When it was archived; an archived form is left out of the list and stops serving.
- `createdAt` (string, required, date-time)
- `updatedAt` (string, required, date-time)

## Example

```bash
curl https://api.kirora.io/v1/forms \
  -H "Authorization: Bearer $KIRORA_API_KEY"
```

Response `200`:

```json
{
  "data": [
    {
      "id": "018f2a4e-6b1c-7d3e-9f40-37386ae05a6b",
      "publicId": "publicId_example",
      "name": "Weekend specials",
      "source": "source_example",
      "status": "draft",
      "groupId": "018f2a4e-6b1c-7d3e-9f40-532211a15a6b",
      "fields": [
        {
          "key": "key_example",
          "type": "email",
          "label": "label_example",
          "required": true
        }
      ],
      "allowedOrigins": [
        "https://example.com"
      ],
      "doubleOptIn": true,
      "captcha": {
        "mode": "kirora"
      },
      "archivedAt": "2030-03-14T09:30:00Z",
      "createdAt": "2030-03-14T09:30:00Z",
      "updatedAt": "2030-03-14T09:30:00Z"
    }
  ],
  "meta": {
    "pagination": {
      "limit": 1,
      "nextCursor": "nextCursor_example"
    }
  }
}
```
