Run a text-message chat
This guide covers a text conversation that a person starts: they text your Resia number, and a Chat Agent answers.
You do not send POST /v1/chats for this chat. Resia starts it when the first text arrives.
Before you start
- Complete Get access.
- Keep the same Bash terminal open, with
RESIA_API_BASEandRESIA_API_KEYset. - Use a Resia number that your organization owns. The agent's replies need that number on an active 10DLC campaign; see Register for 10DLC texting. The assignment below is refused until the number shows as
ASSIGNEDon that campaign; see See which numbers are on a campaign.
Create a Chat Agent for texts to your number
The person's text opens the chat, so the agent answers it. For a first test, use an agent that needs no inputs. Do not add STOP, HELP, or other opt-out text. On SMS, Resia adds that notice itself.
cat > inbound-chat-agent.json <<'JSON'
{
"name": "My first inbound text agent",
"instructions": "You answer questions from patients who text the clinic. Answer in short, plain sentences. End the chat when the patient has no more questions.",
"input_schema": {"type": "object", "properties": {}, "additionalProperties": false},
"analysis_prompt": "Record the patient's main question.",
"analysis_schema": {
"type": "object",
"properties": {"question": {"type": "string"}},
"required": ["question"],
"additionalProperties": false
}
}
JSON
curl --fail-with-body --silent --show-error \
"$RESIA_API_BASE/v1/chat-agents" \
--header "Authorization: Bearer $RESIA_API_KEY" \
--header 'Content-Type: application/json' \
--data-binary @inbound-chat-agent.json \
--output inbound-chat-agent-response.json
jq '{id, review_status, is_active}' inbound-chat-agent-response.json
Expected result: HTTP 201, an id, and the agent's review state.
Continue only when review_status is approved and is_active is true.
API reference: Create a Chat Agent.
Assign the agent to your number
This action changes which Chat Agent answers new texts to the selected number. A number can have an inbound Call Agent and an inbound Chat Agent at the same time. This request changes only the Chat Agent.
read -r -p 'Your Resia number, including + and country code: ' RESIA_PHONE_NUMBER
CHAT_AGENT_ID=$(jq -er '.id' inbound-chat-agent-response.json)
jq -n --arg agent "$CHAT_AGENT_ID" \
'{inbound_chat_agent_id: $agent}' > inbound-chat-assignment.json
curl --fail-with-body --silent --show-error \
--request PATCH "$RESIA_API_BASE/v1/phone-numbers/$RESIA_PHONE_NUMBER" \
--header "Authorization: Bearer $RESIA_API_KEY" \
--header 'Content-Type: application/json' \
--data-binary @inbound-chat-assignment.json
Expected result: HTTP 200 with the selected inbound_chat_agent_id.
If the number is not ASSIGNED on an active 10DLC campaign, the response is 422, because the agent's replies would fail at the carrier. Attach the number with Put a number on a campaign, wait until it shows as ASSIGNED, and retry.
If the agent needs inputs and has no inbound_input_webhook_url, the response is 422, because a text that starts a chat has no inputs of its own.
Add the webhook below, or assign an agent that needs no inputs.
API reference: Assign an inbound agent.
Test it
- Text the Resia number from another phone.
- List the agent's chats and find the new one.
- Read that chat to see the transcript.
curl --fail-with-body --silent --show-error \
"$RESIA_API_BASE/v1/chats?chat_agent_id=$CHAT_AGENT_ID&limit=5" \
--header "Authorization: Bearer $RESIA_API_KEY" \
--output inbound-chats.json
jq '.items[] | {id, status, participant_handle}' inbound-chats.json
Expected result: A new chat with status active and your phone number as participant_handle.
Later texts from the same person go to the same chat until it ends.
To stop answering texts on the number, send {"inbound_chat_agent_id": null} through the same PATCH operation.
API reference: List chats and Read one chat.
Choose who can text: the inbound webhook
Without a webhook, anyone who texts the number starts a chat.
To give the agent information about the person, or to answer only people you know, set inbound_input_webhook_url on the Chat Agent with Replace a Chat Agent.
When a text starts a new chat, Resia sends this to your HTTPS URL before the agent answers:
{
"type": "chat.incoming",
"chat": {
"channel": "sms",
"participant_handle": "+12125550142",
"agent_handle": "+16465550175"
}
}
It never contains the text. Later texts in the same chat do not send it.
Reply within 30 seconds with HTTP 200 and this envelope, where inputs matches the agent's input_schema:
{"inputs": {}}
An agent that declares patient_name receives {"inputs": {"patient_name": "Ada"}}, and its instructions can use $patient_name.
Any other answer starts no chat, and Resia sends no reply: another status such as 404, no answer within 30 seconds, an unreadable body, or inputs that do not match.
So the webhook is an allow list. Answer 200 for a person you know and 404 for anyone else.
Your webhook must tolerate duplicate requests without side effects.
This differs from a call. When an inbound call's webhook fails, a Call Agent that needs no inputs still answers.
API reference: The chat.incoming event.
If something fails
422when you assign the agent and the message names 10DLC: the number is notASSIGNEDon an active campaign yet. See which numbers are on a campaign.422when you assign the agent: the agent needs inputs and has noinbound_input_webhook_url.- No chat after a text: check the number assignment and that the agent is active. If a webhook is set, inspect request logs for its response or timeout.
- A chat, but no reply reaches the phone: check that the number is on an active 10DLC campaign.

