# Send a follow-up

`POST /o/{org}/p/{project}/sessions/{session}/messages`

Delivers a message to the session's agent. A parked resumable sandbox
is woken first. When a turn is still running, the message is queued and
delivered when the turn ends: the answer is then `202` with its place in
the queue. Ephemeral sessions take no queued messages.

## Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `org` | path | string | yes | The org's slug or id. A caller with no role in the org gets `404`. |
| `project` | path | string | yes | A Project's handle (name) or id, resolved inside `{org}` — OR the reserved sentinel `_` meaning "no Project" (a direct-repo / repo-less dispatch on `POST`; "no Project constraint, resolve by session id alone" everywhere else). A real handle that doesn't match the session's actual Project is `404`.  |
| `session` | path | string | yes | The session's full id (`execution_id`). |

## Request body

- `content` (string, required): The message. At most 256 KiB.

## Example: example

```bash
curl -X POST "https://api.prix.dev/o/$RUSH_ORG/p/_/sessions/$SESSION_ID/messages" \
  -H "Authorization: Bearer $RUSH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Also add a regression test for the timezone case."
  }'
```

```typescript
const org = process.env.RUSH_ORG;
const sessionId = process.env.SESSION_ID;

const res = await fetch(`https://api.prix.dev/o/${org}/p/_/sessions/${sessionId}/messages`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.RUSH_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    content: "Also add a regression test for the timezone case.",
  }),
});

console.log(res.status, await res.json());
```

```python
import os

import requests

org = os.environ["RUSH_ORG"]
session_id = os.environ["SESSION_ID"]

res = requests.post(
    f"https://api.prix.dev/o/{org}/p/_/sessions/{session_id}/messages",
    headers={"Authorization": f"Bearer {os.environ['RUSH_API_KEY']}"},
    json={
        "content": "Also add a regression test for the timezone case.",
    },
)

print(res.status_code, res.json())
```

## Responses

### 200

Delivered to the agent.

- `ok` (boolean, required)
- `status` (string, required)

### 202

Queued behind the running turn.

- `ok` (boolean, required)
- `status` (string, required)
- `message_id` (string, required)
- `position` (integer, required): 1-based place in the queue.

### 400

No `content`, or `content` over its size limit (`CONTENT_TOO_LARGE`).

### 401

No bearer, an unknown, revoked or expired one, or an API key on a route keys cannot call.

### 402

The plan does not cover more usage (same codes as starting a session).

### 404

No such resource for the caller, including one that exists in an org the caller cannot see.

### 409

The session cannot take a message: it is closed (`TASK_TERMINAL`), not
started yet, ephemeral with a turn running (`PERSISTENCE_MODE_CONFLICT`),
or its run cannot be continued (`CONTINUATION_UNSUPPORTED`).

### 429

The queue already holds 20 messages (`QUEUE_FULL`).

## Example response (200)

```json
{
  "ok": true,
  "status": "message_sent"
}
```
