# Attest an action

Source: https://langbot.ai/docs/api/receipts/attest

`POST /v1/receipts/attest`

Record and sign that you acted on an event, bound to the event's hash.

**Auth.** An API token: `Authorization: Bearer lb_…` ([create one](https://langbot.ai/app/tokens)). Signed-in web sessions work too.

**Limits.** Counts against your plan's API requests (60, 600 or 3,000 a minute on Free, Builder and Standard).

## Parameters

### Body

| Name | Type | Required | Description |
|---|---|---|---|
| `evt_id` | string | yes | The event you acted on (`evt_…`). |
| `hash` | string | no | The event hash you hold; refused with `409` when it differs from the record. |
| `action` | object | yes | Your action as JSON, at most 4 KiB. Private to you; never put venue credentials in it. |
| `t_acted` | integer | no | When you acted, ms epoch; default the time of the call. |

## Request

**curl**

```bash
curl -X POST "https://api.langbot.ai/v1/receipts/attest" \
  -H "Authorization: Bearer $LANGBOT_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"evt_id": "evt_01K7Q0000000000000000000A2", "hash": "5d0e05c3…", "action": {"side": "yes", "qty": 20, "price": 0.57}, "t_acted": 1760050125000}'
```

**Python**

```python
from langbot import LangbotClient

async with LangbotClient() as lb:  # reads LANGBOT_API_TOKEN
    row = await lb.attest("evt_01K7Q0000000000000000000A2", {"side": "yes", "qty": 20}, t_acted=1760050125000)
    print(row["id"], row["signature"])
```

**TypeScript**

```ts
const res = await fetch("https://api.langbot.ai/v1/receipts/attest", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LANGBOT_API_TOKEN}`, "Content-Type": "application/json" },
  body: JSON.stringify({"evt_id": "evt_01K7Q0000000000000000000A2", "hash": "5d0e05c3\u2026", "action": {"side": "yes", "qty": 20, "price": 0.57}, "t_acted": 1760050125000}),
});
console.log(await res.json());
```

## Response

`201 Created`

```json
{ "id": "att_01K7Q…", "user_id": "usr_…", "evt_id": "evt_01K7Q0000000000000000000A2", "event_hash": "5d0e05c3…", "action_hash": "9f2c…", "t_acted": 1760050125000, "created_at": 1760050125500, "key_id": "56475aa75463474c", "signature": "…" }
```

## Errors

| Status | `code` | When |
|---|---|---|
| 404 | `not_found` | Unknown event. |
| 409 | `conflict` | `hash` does not match the record. |
| 413 | `too_large` | `action` is over 4 KiB. |
| 401 | `auth_required` | No token was sent. |
| 401 | `token_invalid` | The token was not recognised (mistyped, revoked or expired). |
| 422 | `validation_error` | A parameter failed validation; `detail[].loc` names it. |
| 429 | `rate_limited` | Over your request budget; wait `Retry-After` seconds. |

Every error body is `{"detail": …, "code": "…"}`; branch on `code`. All codes: [Errors](https://langbot.ai/docs/api#errors).
