InkBotDocs

Replies

Send a message, follow the reply, steer or stop it, and answer approvals and questions.

A turn is one reply. Sending a message starts a turn and returns its id straight away. Follow it on the events socket, or poll GET /bots/{id} until runningTurnId is gone.

Send a message

POST /bots/{id}/messages

Field Type
text string The message
attachments array Optional. Each { "name", "mediaType", "kind", "data" }, with kind one of Image, Pdf, Text, and data the file's bytes in base64
replyToId string Optional. The id of the message this one replies to
worksIn string Optional. Auto, Browser, Computer or ThisPc for this message only
curl -s -X POST $INKBOT/api/bots/scout/messages \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{ "text": "Find three recent papers on speculative decoding." }'
{ "turnId": "6c1e…", "message": { "id": "a41f…", "fromUser": true, "text": "Find three recent papers on speculative decoding.", "at": "2026-10-30T14:02:11+00:00" } }

Sending to a bot that's already replying fails with an error. Steer the running reply instead, or wait.

Respond

POST /bots/{id}/respond with {} runs a reply to the chat as it is, when its last message is yours. Use it after editing a message or truncating to regenerate. Returns the same { turnId, message }.

Steer

POST /turns/{turnId}/steer

{ "id": "q1", "text": "Only papers from 2026, please." }

Returns { "accepted": true } when the reply takes the message at its next step (its step id is steer-q1). It's false when the reply can't take messages midway (Claude Code and Grok Build replies, group chats, or a reply that already ended). Send it as a normal message then.

Stop

POST /turns/{turnId}/stop returns 204. The reply ends with outcome Stopped.

Approvals

When a bot asks for approval, an ApprovalRequested event carries an ApprovalPrompt, which is also in the conversation's pendingApprovals. Answer it:

POST /approvals/{approvalId}

{ "choice": "AllowOnce" }
choice
AllowOnce Just this action
AllowForChat This kind of action for the rest of the conversation
AllowCommand Add the prompt's commandPattern to the host's allowlist, and allow
Deny Don't allow it

An approval nobody answers resolves as TimedOut after the server's waiting time (see PUT /settings/approval-timeout).

Questions

A QuestionAsked event carries a QuestionPrompt with one to four questions (also in pendingQuestions). Answer them in order:

POST /questions/{questionId}

{
  "answers": [
    { "chosen": ["PostgreSQL"] },
    { "chosen": [], "text": "Friday at the latest" }
  ]
}

chosen holds option labels (several for a question with multiple: true); text is a free answer. Send { "skipped": true } to let the bot decide. Unanswered questions count as skipped after the waiting time.

A complete exchange

# 1. Send
TURN=$(curl -s -X POST $INKBOT/api/bots/scout/messages -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" -d '{"text":"Summarize README.md"}' | jq -r .turnId)

# 2. Wait for it to finish (or listen on /api/events)
while curl -s $INKBOT/api/bots/scout -H "Authorization: Bearer $TOKEN" | jq -e '.runningTurnId' >/dev/null; do sleep 2; done

# 3. Read the reply
curl -s $INKBOT/api/bots/scout -H "Authorization: Bearer $TOKEN" | jq -r '.messages[-1].text'