> ## Documentation Index
> Fetch the complete documentation index at: https://docs.replyful.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Bring your own chatbot

> Run your own chatbot, keep every chat as a Replyful ticket, and hand over to a human agent with three API calls

If you have built your own chatbot, you can still use Replyful for the tickets. Your bot writes each chat to Replyful as it happens. When it cannot help, one call gives the ticket to your team, who reply by email from the Replyful inbox.

You need a **Read & write** live [API key](https://docs.replyful.com/api-reference/authentication.md) and a chat channel. Create a chat channel in Replyful for your bot and give it a name your agents will recognise; you never have to install its widget.

## The flow

**1. Customer writes: create the ticket**

[`POST /v1/tickets`](https://docs.replyful.com/api-reference/tickets/create) with the first message. Keep the returned ticket `id` and the `id` of its conversation.

**2. Each turn: add a message**

[`POST /v1/conversations/{id}/messages`](https://docs.replyful.com/api-reference/conversations/create-message) for every line: `role: "user"` for the customer, `role: "assistant"` for your bot.

**3. Your bot gives up: hand over**

[`POST /v1/tickets/{id}/handover`](https://docs.replyful.com/api-reference/tickets/handover). The ticket lands in **Needs response** and an agent replies by email, so tell the customer to check their inbox.

Already have the whole chat? Send every message in the first call and hand over right after.

A chat your bot solves needs no further call: a quiet ticket resolves itself after the time set on the chat channel.

## Who the customer is

Send what you know in `requester` when you create the ticket.

| Your bot knows | Send | Result |
| - | - | - |
| The signed-in user | `externalId` (your user ID), plus name and email | One contact per user, reused on every chat. |
| Only an email | `email` | With `verified: true`, one contact per address. Otherwise a new contact per chat. |
| Nothing | No `requester` | An anonymous contact. Give an email at handover. |

Set `email.verified` to `true` only when you have checked that the person owns the address. It tells Replyful that personal data may be sent there.

Together with `externalId`, an email is only accepted with `verified: true`. If you have not checked a signed-in user's address, leave the email out; a request that sends it unverified is refused.

## Safe retries

Send an `Idempotency-Key` header (any unique string, such as a UUID) on every `POST`. If the same key and body arrive again within 24 hours, you get the first response back with `Idempotent-Replay: true` and nothing runs twice. The same key with a different body returns `409 idempotency_key_reused`.

Your own chat ID in `externalId` is a second guard: a ticket with an ID you already used is refused with `409 ticket_external_id_taken`, and the message names the existing ticket.

A `5xx` response is never remembered, so retrying it runs the request again. One case needs care: when you create a ticket with several messages and get a `5xx`, the ticket and its first messages may already be saved. Always send `externalId` with a transcript. The retry then returns `409 ticket_external_id_taken` with the ticket's ID; [read its messages](https://docs.replyful.com/api-reference/conversations/messages.md) and [add](https://docs.replyful.com/api-reference/conversations/create-message.md) the ones that are missing.

## Good to know

* Your bot's replies are stored as AI replies and count in reporting. They are not billed as Replyful AI usage.
* After handover, `assistant` messages are refused so your bot cannot talk over the agent. `user` messages are still accepted.
* Handover uses the chat channel's handover settings to pick the email channel. With a single email channel there is nothing to set up.
* Test keys cannot write yet.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.