# Send a message

> Message your agent exactly as the dashboard chat does, and optionally hold the request open for the reply.

Canonical: https://revnu.com/docs/agent-messages

```bash
curl -X POST -H "Authorization: Bearer $REVNU_API_TOKEN" \
  -H "content-type: application/json" \
  -d '{"text":"What did we ship this week?","waitSeconds":90,"clientRequestId":"weekly-1"}' \
  https://revnu.com/api/v1/agent/messages
```

## Body

| Field | Type | Meaning |
|---|---|---|
| `text` | string, required | Up to 4,000 characters. |
| `clientRequestId` | string | Up to 128 characters of `A-Za-z0-9_.:-`. A retry with the same id returns the original `requestId`. Never reuse an id after a `failed` message; send again with a new one. |
| `waitSeconds` | integer, 0 to 120 | Hold the request until the agent has replied or failed. |

## Responses

| Code | Meaning |
|---|---|
| 202 | `{ requestId, deduplicated, message? }`. Queued; poll [the message](/docs/agent-message-status). With `waitSeconds`, `message` is the last state seen. |
| 200 | Only with `waitSeconds`: `message` is terminal and `replies` is filled. |
| 400 | Missing or empty `text`, `text` over 8,000 bytes, a non-string client id, or a `waitSeconds` outside 0 to 120. |
| 409 | `text` over 4,000 characters, or a client id with characters outside `A-Za-z0-9_.:-`. |

## Frequently asked questions

### Which scope does this need?

`agent:message`. A token without it gets `403` with `requiredScope` in the body. `GET /me` shows a token's scopes.

### Are responses cached?

No. Every response is `Cache-Control: no-store`, so what you read is current.
