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

# Submissions

> Everything your agent captured: leads, bookings, quotes, payments

Every time a tool runs during a conversation, a **submission** is recorded — the
input the agent collected, the result, the channel it came from, and the page the
visitor was on. Leads, bookings, quote requests and payment links all land here,
whatever tool produced them.

This is the endpoint to poll if you sync into a CRM, and the one to read when
someone asks "did that lead actually arrive?". For push instead of poll, see
[Webhooks](/api-reference/endpoints/webhooks).

## GET /tenants/{slug}/submissions

List submissions, most recent first.

**Required scope:** `conversations:read`

```bash theme={null}
curl "https://api.animam.ai/tenants/my-company/submissions?status=NEW&toolType=SUBMIT_FORM" \
  -H "Authorization: Bearer ak_your_token"
```

### Query parameters

| Parameter     | Type     | Description                                                                               |
| ------------- | -------- | ----------------------------------------------------------------------------------------- |
| `toolType`    | string   | Filter by tool type — `SUBMIT_FORM`, `BOOK_MEETING`, `GENERATE_QUOTE`, …                  |
| `toolId`      | uuid     | Filter by one specific tool                                                               |
| `status`      | string   | `NEW`, `CONTACTED` or `RESOLVED`                                                          |
| `channel`     | string   | `web` (chat widget), `voice`, `api` (an agent called us), `form` (standalone form widget) |
| `search`      | string   | Case-insensitive search across the collected fields — min. 2 characters                   |
| `from` / `to` | ISO date | Creation window                                                                           |
| `page`        | int      | Default `1`                                                                               |
| `limit`       | int      | Default `30`, max `100`                                                                   |

<Warning>
  The type filter is `toolType`, not `type`. An unknown parameter is ignored
  rather than rejected, so `?type=SUBMIT_FORM` silently returns **every** type —
  a quiet way to conclude you have more leads than you do. Invalid *values* do get
  rejected with `400`.
</Warning>

### Response

```json theme={null}
{
  "submissions": [
    {
      "id": "b2d0…",
      "createdAt": "2026-07-30T11:24:50.900Z",
      "channel": "web",
      "status": "NEW",
      "input": { "name": "Marie Durand", "email": "marie@example.com", "message": "Is the house still available?" },
      "result": { "success": true, "message": "Request captured." },
      "conversationId": "c-42",
      "visitorUserId": null,
      "pageUrl": "https://your-site.com/listings/42",
      "tool": { "name": "contact_form", "type": "SUBMIT_FORM" }
    }
  ],
  "pagination": { "page": 1, "limit": 30, "total": 128, "pages": 5 },
  "stats": { "total": 128, "new": 12, "today": 3, "byChannel": { "web": 119, "form": 9 } }
}
```

`input` holds the fields **your** tool declared, under your own field names — see
[SUBMIT\_FORM config format](/api-reference/endpoints/tools#submit-form-config-format).

`stats` is computed on **page 1 only** (it counts the whole tenant, not the
current filter, except for `toolType`). Don't expect it while paginating.

`conversationId` is present whenever the submission came from a conversation
rather than the standalone form. Fetch the thread with
[GET /tenants/{slug}/conversations/{id}](/api-reference/endpoints/conversations)
to see what was said around the capture.

## PUT /tenants/{slug}/submissions/{id}

Move a submission along: `NEW` → `CONTACTED` → `RESOLVED`.

**Required scope:** `conversations:write`

```bash theme={null}
curl -X PUT https://api.animam.ai/tenants/my-company/submissions/b2d0… \
  -H "Authorization: Bearer ak_your_token" \
  -H "Content-Type: application/json" \
  -d '{"status": "CONTACTED"}'
```

Any other value returns `400`. The status is free of side effects on our side —
nothing is re-sent, nothing is deleted — it exists so your team (or your CRM)
can tell what has been handled.

Each change fires a `submission.updated` webhook carrying both `status` and
`previousStatus`, which is what makes a two-way sync possible: your CRM marks it
contacted, your other tools hear about it.

## DELETE /tenants/{slug}/submissions/{id}

Remove a submission permanently.

**Required scope:** `conversations:write`

Use it to honour an erasure request (GDPR art. 17) — the captured contact details
live in `input`, so deleting the submission is what actually removes them. Note
that the conversation it came from is a separate record.

## Status meaning

| Status      | Meaning                           |
| ----------- | --------------------------------- |
| `NEW`       | captured, nobody has acted on it  |
| `CONTACTED` | someone reached out               |
| `RESOLVED`  | closed — sold, booked, or dropped |

Submissions are created with `NEW`. Nothing moves them automatically: no delay,
no reminder, no expiry. If a lead sits in `NEW` for a week, that is a report
about your follow-up, not about the agent — which is the point of keeping the
column.
