Chatbots
Operations tagged Chatbots in the public API.
About Chatbots
A chatbot (an agent in the dashboard) is the unit everything else hangs off: knowledge is trained into one, conversations happen with one, and its widget, hosted agent page and messaging channels each serve one.
Lifecycle. POST /chatbots creates it as draft. The website widget and the hosted agent page serve only an active chatbot: POST /chatbots/{id}/activate puts it live there, POST /chatbots/{id}/deactivate takes it offline (POST /chat answers for a chatbot in any status). Training is separate: training_status follows its knowledge, and GET /chatbots/{id}/readiness reports ready once the chatbot is active and training is completed. DELETE /chatbots/{id} removes it with its knowledge, conversations, channels and plugin installations.
IDs you will meet.
id— an integer, in every/chatbots/{id}path and aschatbot_ideverywhere else (POST /chat,GET /conversations,POST /knowledge, …).slug— the chatbot's public handle, the address of its hosted agent page (/agent/{handle}), unique across the platform.GET /chatbots/by_handle/{handle}resolves it;PUT /chatbots/{id}/handlechanges it.- Access account
id— an integer naming one visitor login of acredentialedhosted page (GET /chatbots/{id}/access→accounts[].id).
IDs on this page
- Chatbot handle
<HANDLE> - String: lowercase letters and digits with single inner hyphens, 3–40 characters, never all digits.
Get it from
- GET /v1/chatbots returns it as
data[].slug - GET /v1/chatbots/{id} returns it as
slug - GET /v1/chatbots/{id}/access returns it as
handle - It is the last segment of the chatbot's hosted page address,
/agent/{handle}.
- GET /v1/chatbots returns it as
- Chatbot id
<CHATBOT_ID> - Integer.
Get it from
- GET /v1/chatbots returns it as
data[].id - POST /v1/chatbots returns it as
id - GET /v1/chatbots/by_handle/{handle} returns it as
id - Webhook chatbot.created carries it as
data.object.id - In the dashboard, it is the number in a chatbot's address:
/dashboard/chatbots/{id}.
- GET /v1/chatbots returns it as
- Access account id
<ACCOUNT_ID> - Integer.
Get it from
- POST /v1/chatbots/{id}/access/accounts returns it as
id - GET /v1/chatbots/{id}/access returns it as
accounts[].id
- POST /v1/chatbots/{id}/access/accounts returns it as
List chatbots
status, training_status or a search on the name; the filters combine. An unknown status or training_status is 422 VALIDATION_FAILED, never an empty page.- Required scope
- chatbots:read
- Idempotency
- Read-only
- Rate limits
Query parameters
statusstringnullableOptionalOnly chatbots in this lifecycle status:active,inactiveordraft.Possible values
activeinactivedraftnulltraining_statusstringnullableOptionalOnly chatbots whose knowledge training is in this state.Possible values
never_trainedpendingtrainingupdatingneeds_retrainingcompletedfailednullsearchstringnullableOptionalSubstring match on the chatbot name (two characters or more; Arabic spelling variants such as ه/ة, ي/ى and ا/أ/إ/آ match each other).Max length:
100limitintegerOptionalPage size, clamped to 1–100.Default:
20Minimum:1Maximum:100starting_afterstringOptionalCursor from a previous page'snext_cursor: returns the page after it. A cursor minted for another list,sortororderis 422INVALID_CURSOR.ending_beforestringOptionalCursor from a previous page'sprevious_cursor: returns the page before it. Wins when both cursors are sent.created[gte]stringOptionalOnly rows created on or after this instant:YYYY-MM-DD(whole UTC day) or an RFC 3339 timestamp with a zone. Anything else is 422INVALID_PARAMETER.created[lte]stringOptionalOnly rows created on or before this instant:YYYY-MM-DD(whole UTC day) or an RFC 3339 timestamp with a zone. Anything else is 422INVALID_PARAMETER.
Responses
- 200Success.
objectstringRequiredAlways
listdataarray of ChatbotResourceRequiredhas_morebooleanRequirednext_cursorstringnullableRequiredprevious_cursorstringnullableRequiredurlstringRequiredAlways
/v1/chatbots
- 400A tenant selector header named a tenant other than the API key's own (
ACCOUNT_SELECTOR_NOT_SUPPORTED): an all-digitX-Account-Idother than the key owner's id or, whileworkspaces.context_enabledis on, anX-Workspace-Idother than the key's workspace (ws_prefix optional, case-insensitive). A header naming the key's own tenant, or a non-numericX-Account-Id, is ignored; a key cannot switch tenants, so send neither.Error codesACCOUNT_SELECTOR_NOT_SUPPORTED
- 401Missing or invalid API key.
Error codesUNAUTHENTICATED
- 403The API key is missing a required scope.
Error codesACCOUNT_SUSPENDEDINSUFFICIENT_SCOPE
- 422Validation failed. See
error.details. - 429Rate limited. Honour the Retry-After header before retrying.
Error codesRATE_LIMITED
- 500Unexpected server error. Retry with the same Idempotency-Key.
Error codesSERVER_ERROR
Request
curl -X GET 'https://api.agentency.com/v1/chatbots' \
-H "Authorization: Bearer <YOUR_KEY>" \
-H "Content-Type: application/json"Response
Example 200 response
{
"object": "list",
"data": [
{
"object": "chatbot",
"id": 1,
"slug": "orders-assistant",
"name": "Orders Assistant",
"description": "Tracks orders and deliveries.",
"avatar_url": null,
"color": "bg-indigo-500",
"primary_language": "English",
"supported_languages": [],
"text_direction": "LTR",
"status": "active",
"training_status": "never_trained",
"cache_responses": true,
"last_training_date": null,
"last_active_at": null,
"template_id": null,
"response_length": "Short Response",
"audience": "customers",
"knowledge_mode": "strict",
"welcome_message": null,
"fallback_message": null,
"custom_instructions": [],
"enable_handoff": false,
"training_config": [],
"gradient_style": "from-indigo-600 to-blue-600",
"header_theme": "gradient",
"is_image_avatar": false,
"settings": [],
"lead_capture": null,
"allowed_domains": [],
"created_at": "2026-01-01T00:00:00+00:00",
"updated_at": "2026-01-01T00:00:00+00:00"
},
{
"object": "chatbot",
"id": 1,
"slug": "support-assistant",
"name": "Support Assistant",
"description": "Answers billing and shipping questions.",
"avatar_url": null,
"color": "bg-indigo-500",
"primary_language": "English",
"supported_languages": [],
"text_direction": "LTR",
"status": "active",
"training_status": "never_trained",
"cache_responses": true,
"last_training_date": null,
"last_active_at": null,
"template_id": null,
"response_length": "Short Response",
"audience": "customers",
"knowledge_mode": "strict",
"welcome_message": null,
"fallback_message": null,
"custom_instructions": [],
"enable_handoff": false,
"training_config": [],
"gradient_style": "from-indigo-600 to-blue-600",
"header_theme": "gradient",
"is_image_avatar": false,
"settings": [],
"lead_capture": null,
"allowed_domains": [
"shop.example.com"
],
"created_at": "2026-01-01T00:00:00+00:00",
"updated_at": "2026-01-01T00:00:00+00:00"
}
],
"has_more": false,
"next_cursor": null,
"previous_cursor": null,
"url": "/v1/chatbots"
}Create a chatbot
201. Only name is required; every other field takes the platform default (English, short answers, the default theme, customers audience answering in strict knowledge mode). The chatbot starts draft and never_trained: add knowledge with POST /knowledge, then POST /chatbots/{id}/activate to serve it on the widget and hosted page.
The name is unique within the account: a taken name is 409 CHATBOT_NAME_TAKEN. The plan's agent cap is checked after the name: at the cap it is 402 AGENT_LIMIT_REACHED. A retry with the same Idempotency-Key returns the chatbot the first request created.- Required scope
- chatbots:write
- Idempotency
- Accepts Idempotency-Key
- Webhook events
- chatbot.created
- Rate limits
Header parameters
Idempotency-KeystringOptionalMakes a retry safe. The first 2xx answer is stored for 24 h and replayed for the same key withIdempotency-Replayed: true; a retry while the first request runs is 409IDEMPOTENCY_IN_FLIGHT; the same key with a different payload is 422IDEMPOTENCY_KEY_REUSED; a malformed key is 400INVALID_IDEMPOTENCY_KEY.Min length:
16Max length:128Pattern:^[A-Za-z0-9_-]+$
Request body
/v1 create chatbot payload.
The field set is PINNED here (plan H4): {@see FIELDS} is the exhaustive
list of top-level keys the public contract accepts, and {@see rules()}
keeps only the dashboard rules for those keys. A rule added to the
dashboard request for a new dashboard-only field therefore never reaches
/v1 (and never appears in the generated OpenAPI document) until it is
deliberately added to this list. The per-field rules themselves are shared
so the two surfaces cannot disagree on a field they both accept.
Deliberately absent: the body idempotency_key — /v1 clients send the
Idempotency-Key header (docs/03-domains/public-api).
audience / knowledge_mode are REQUIRED on the dashboard (the intent
steps) but sometimes here ({@see OPTIONAL_ON_V1}): an API client that
never heard of them keeps creating business agents answering from their
knowledge only (customers + strict, the pre-existing behaviour).template_idintegernullableOptionalThe catalogue template to start from (an active template id);nullfor none./v1has no operation that lists templates.namestringRequiredDisplay name, at most 255 characters. Unique within the account: a taken name is 409CHATBOT_NAME_TAKEN.Max length:
255descriptionstringnullableOptionalOptional longer description.Max length:
500audiencestringOptionalWho the agent serves:customers(it speaks for the business) orpersonal(the owner's private assistant). Defaults tocustomerswhen omitted.Possible values
customerspersonalknowledge_modestringOptionalHow far answers may step outside the knowledge base:strict(knowledge only) orgeneral(general knowledge when the knowledge base is silent, flagged as such). Defaults tostrictwhen omitted.Possible values
strictgeneralprimary_languagestringOptionalContent language. Defaults toEnglishwhen omitted.Possible values
EnglishArabicSpanishFrenchGermanPortugueseHindiBengaliUrduJapaneseIndonesianTurkishRussianKoreanVietnamesetext_directionstringOptionalDerived fromprimary_language; a client-supplied value is accepted and ignored.Possible values
LTRRTLresponse_lengthstringOptionalAnswer length preset. Defaults toShort Responsewhen omitted.Possible values
Short ResponseLong Responsecache_responsesbooleannullableOptionalWhether a repeated question may be answered from the response cache instead of a new model call. Defaults totrue.welcome_messagestringnullableOptionalThe first message the widget and hosted page show, at most 2000 characters;nullfor the default greeting.Max length:
2000fallback_messagestringnullableOptionalThe reply sent when the chatbot cannot produce an answer, at most 2000 characters;nullfor the platform default.Max length:
2000custom_instructionsarray of stringnullableOptionalExtra instructions applied to every answer, one non-empty string (at most 500 characters) per instruction. The plan caps how many.Max items:
1gradient_styleany ofOptionalHeader gradient: a theme catalog token or a custom two-stop#rrggbb,#rrggbbpair. Hex input is normalised (#RGB, upper case and a missing#are accepted); alpha hex (#rrggbbaa) is refused. A pair on which no text colour (#ffffff,#1f2937,#000000) reaches 4.5:1 at both ends is refused with 422VALIDATION_FAILEDongradient_style. Defaults to the wizard default when omitted.Max length:
100header_themestringnullableOptionalHeader fill mode:gradient(usesgradient_style) orflat(usescolor). Defaults togradient.Possible values
flatgradientnullcolorany ofnullableOptionalFlat header colour: a theme catalog token or a custom#rrggbb. Hex input is normalised (#RGB, upper case and a missing#are accepted); alpha hex (#rrggbbaa) is refused. Any colour is accepted: the text colour is picked automatically (#ffffff,#1f2937or#000000) to reach WCAG AA 4.5:1. Defaults to the wizard default when omitted.Max length:
20avatarstringnullableOptionalA stored avatar reference: the path of an image this account uploaded (/uploads/avatars/…), a bundled default avatar or a hex colour;nullclears it. To upload a new image usePOST /chatbots/{id}/avatar.Max length:
500is_image_avatarbooleanOptionalWhetheravataris an uploaded image rather than a colour or default avatar.enable_handoffbooleanOptionalWhether the chatbot may hand a conversation to a human. The first handoff of a conversation emitsconversation.handoff.requested. Defaults tofalse.settingsobjectOptionalWidget / behaviour settings bag. Only the documented keys are accepted; unknown keys are a 422.lead_captureobjectOptionalOptional pre-reply lead capture configuration. Only the documented keys are accepted.
Responses
- 201
ChatbotResourceobjectstringRequiredAlways
chatbotidintegerRequiredThe chatbot id, used in every/chatbots/{id}path and aschatbot_idelsewhere.slugstringRequiredThe public handle: the hosted agent page lives at/agent/{slug}. Unique across the platform;PUT /chatbots/{id}/handlechanges it, a rename never does.namestringRequiredDisplay name, unique within the account.descriptionstringnullableRequiredYour own description of the chatbot;nullwhen none.avatar_urlstringnullableRequiredAbsolute URL of the avatar image;nullwhen the chatbot has none.colorstringRequiredFlat header colour: a theme token or a#rrggbbhex. Used whenheader_themeisflat.primary_languagestringRequiredThe language the chatbot answers in, e.g.English.supported_languagesobjectRequiredFurther languages the chatbot is set up for;[]when none.text_directionstringRequiredLTRorRTL, derived fromprimary_language.statusstringRequiredLifecycle status. The widget and hosted page serve only anactivechatbot; a new one isdraft.Possible values
activeinactivedrafttraining_statusstringRequiredWhere training of the chatbot's knowledge stands.completedonce every source is trained;never_trainedbefore any.Possible values
never_trainedpendingtrainingupdatingneeds_retrainingcompletedfailedcache_responsesbooleanRequiredWhether a repeated question may be answered from the response cache instead of a new model call.last_training_datestringnullableRequiredWhen training last completed (ISO 8601, UTC);nullbefore the first.last_active_atstringnullableRequiredWhen the chatbot last answered a chat turn (ISO 8601, UTC);nullbefore the first.template_idintegernullableRequiredThe catalogue template the chatbot was created from;nullwhen none.response_lengthstringRequiredAnswer length preset:Short ResponseorLong Response.audiencestringRequiredWho the chatbot serves:customers(it speaks for the business) orpersonal(the owner's private assistant).customersunless set at creation.knowledge_modestringRequiredHow far answers may step outside the knowledge base:strict(knowledge only) orgeneral(general knowledge when the knowledge base has nothing).strictunless set at creation.welcome_messagestringnullableRequiredThe first message the widget and hosted page show;nullfor the default greeting.fallback_messagestringnullableRequiredThe reply sent when the chatbot cannot produce an answer;nullfor the platform default.custom_instructionsobjectRequiredYour extra instructions for every answer, one string per instruction;[]when none. The plan caps how many.enable_handoffbooleanRequiredWhether the chatbot may hand a conversation to a human.training_configobjectRequiredTraining and retrieval tuning set throughPATCH /chatbots/{id};[]when never set.gradient_stylestringRequiredHeader gradient: a theme token or a#rrggbb,#rrggbbpair. Used whenheader_themeisgradient.header_themestringRequiredHeader fill:gradient(usesgradient_style) orflat(usescolor).is_image_avatarbooleanRequiredWhether the avatar is an uploaded image (POST /chatbots/{id}/avatar).settingsobjectRequiredThe widget look-and-behaviour keys set on the chatbot (PUT /chatbots/{chatbotId}/widget). A key never set is absent.lead_captureobjectnullableRequiredLead capture: whether the widget asks visitors for contact details (enabled), when (trigger), whichfields, and whether they may skip it;nullwhen never configured.allowed_domainsobjectRequiredHostnames whose pages may load the widget;[]lets it load on any site. Managed with the/chatbots/{chatbotId}/widget/domainsoperations.created_atstringnullableRequiredWhen the chatbot was created (ISO 8601, UTC).updated_atstringnullableRequiredWhen the chatbot last changed (ISO 8601, UTC).
- 400A tenant selector header named a tenant other than the API key's own (
ACCOUNT_SELECTOR_NOT_SUPPORTED): an all-digitX-Account-Idother than the key owner's id or, whileworkspaces.context_enabledis on, anX-Workspace-Idother than the key's workspace (ws_prefix optional, case-insensitive). A header naming the key's own tenant, or a non-numericX-Account-Id, is ignored; a key cannot switch tenants, so send neither. A mutation that honoursIdempotency-Keyalso returnsINVALID_IDEMPOTENCY_KEYwhen that header is not 16–128[A-Za-z0-9_-]characters.Error codesACCOUNT_SELECTOR_NOT_SUPPORTEDINVALID_IDEMPOTENCY_KEY
- 401Missing or invalid API key.
Error codesUNAUTHENTICATED
- 402A billing gate refused the request (plan limit, monthly AI budget or message credits). See
error.code.Error codesAGENT_LIMIT_REACHED
- 403The API key is missing a required scope.
Error codesACCOUNT_SUSPENDEDINSUFFICIENT_SCOPE
- 409The request conflicts with the current resource state.
Error codesCHATBOT_NAME_TAKENIDEMPOTENCY_IN_FLIGHT
- 422Validation failed. See
error.details.Error codesIDEMPOTENCY_KEY_REUSEDVALIDATION_FAILED
- 429Rate limited. Honour the Retry-After header before retrying.
Error codesRATE_LIMITED
- 500Unexpected server error. Retry with the same Idempotency-Key.
Error codesSERVER_ERROR
Request
curl -X POST 'https://api.agentency.com/v1/chatbots' \
-H "Authorization: Bearer <YOUR_KEY>" \
-H "Content-Type: application/json"
-d '{
"template_id": 1,
"name": "name",
"description": "description",
"audience": "audience",
"knowledge_mode": "knowledge_mode",
"primary_language": "primary_language",
"text_direction": "text_direction",
"response_length": "response_length"
}'Response
Example 201 response
{
"object": "chatbot",
"id": 1,
"slug": "returns-assistant",
"name": "Returns Assistant",
"description": "Handles returns and exchanges.",
"avatar_url": null,
"color": "bg-indigo-600",
"primary_language": "English",
"supported_languages": [
"English"
],
"text_direction": "LTR",
"status": "draft",
"training_status": "never_trained",
"cache_responses": true,
"last_training_date": null,
"last_active_at": null,
"template_id": null,
"response_length": "Short Response",
"audience": "customers",
"knowledge_mode": "strict",
"welcome_message": null,
"fallback_message": null,
"custom_instructions": [],
"enable_handoff": false,
"training_config": [],
"gradient_style": "from-primary-800 to-primary-600",
"header_theme": "gradient",
"is_image_avatar": false,
"settings": [],
"lead_capture": null,
"allowed_domains": [],
"created_at": "2026-01-01T00:00:00+00:00",
"updated_at": "2026-01-01T00:00:00+00:00"
}Retrieve a chatbot by handle
slug, the last segment of its hosted page address /agent/{handle}) when you have the handle but not the integer id. A handle that belongs to another account, or to no chatbot, is 404 NOT_FOUND.- Required scope
- chatbots:read
- Idempotency
- Read-only
- Rate limits
String: lowercase letters and digits with single inner hyphens, 3–40 characters, never all digits.handle(path)Chatbot handlePlaceholder in the samples:
<HANDLE>Get it from
- GET /v1/chatbots returns it as
data[].slug - GET /v1/chatbots/{id} returns it as
slug - GET /v1/chatbots/{id}/access returns it as
handle - It is the last segment of the chatbot's hosted page address,
/agent/{handle}.
- GET /v1/chatbots returns it as
Path parameters
handlestringRequiredThe chatbot's handle (slug).
Responses
- 200
ChatbotResourceobjectstringRequiredAlways
chatbotidintegerRequiredThe chatbot id, used in every/chatbots/{id}path and aschatbot_idelsewhere.slugstringRequiredThe public handle: the hosted agent page lives at/agent/{slug}. Unique across the platform;PUT /chatbots/{id}/handlechanges it, a rename never does.namestringRequiredDisplay name, unique within the account.descriptionstringnullableRequiredYour own description of the chatbot;nullwhen none.avatar_urlstringnullableRequiredAbsolute URL of the avatar image;nullwhen the chatbot has none.colorstringRequiredFlat header colour: a theme token or a#rrggbbhex. Used whenheader_themeisflat.primary_languagestringRequiredThe language the chatbot answers in, e.g.English.supported_languagesobjectRequiredFurther languages the chatbot is set up for;[]when none.text_directionstringRequiredLTRorRTL, derived fromprimary_language.statusstringRequiredLifecycle status. The widget and hosted page serve only anactivechatbot; a new one isdraft.Possible values
activeinactivedrafttraining_statusstringRequiredWhere training of the chatbot's knowledge stands.completedonce every source is trained;never_trainedbefore any.Possible values
never_trainedpendingtrainingupdatingneeds_retrainingcompletedfailedcache_responsesbooleanRequiredWhether a repeated question may be answered from the response cache instead of a new model call.last_training_datestringnullableRequiredWhen training last completed (ISO 8601, UTC);nullbefore the first.last_active_atstringnullableRequiredWhen the chatbot last answered a chat turn (ISO 8601, UTC);nullbefore the first.template_idintegernullableRequiredThe catalogue template the chatbot was created from;nullwhen none.response_lengthstringRequiredAnswer length preset:Short ResponseorLong Response.audiencestringRequiredWho the chatbot serves:customers(it speaks for the business) orpersonal(the owner's private assistant).customersunless set at creation.knowledge_modestringRequiredHow far answers may step outside the knowledge base:strict(knowledge only) orgeneral(general knowledge when the knowledge base has nothing).strictunless set at creation.welcome_messagestringnullableRequiredThe first message the widget and hosted page show;nullfor the default greeting.fallback_messagestringnullableRequiredThe reply sent when the chatbot cannot produce an answer;nullfor the platform default.custom_instructionsobjectRequiredYour extra instructions for every answer, one string per instruction;[]when none. The plan caps how many.enable_handoffbooleanRequiredWhether the chatbot may hand a conversation to a human.training_configobjectRequiredTraining and retrieval tuning set throughPATCH /chatbots/{id};[]when never set.gradient_stylestringRequiredHeader gradient: a theme token or a#rrggbb,#rrggbbpair. Used whenheader_themeisgradient.header_themestringRequiredHeader fill:gradient(usesgradient_style) orflat(usescolor).is_image_avatarbooleanRequiredWhether the avatar is an uploaded image (POST /chatbots/{id}/avatar).settingsobjectRequiredThe widget look-and-behaviour keys set on the chatbot (PUT /chatbots/{chatbotId}/widget). A key never set is absent.lead_captureobjectnullableRequiredLead capture: whether the widget asks visitors for contact details (enabled), when (trigger), whichfields, and whether they may skip it;nullwhen never configured.allowed_domainsobjectRequiredHostnames whose pages may load the widget;[]lets it load on any site. Managed with the/chatbots/{chatbotId}/widget/domainsoperations.created_atstringnullableRequiredWhen the chatbot was created (ISO 8601, UTC).updated_atstringnullableRequiredWhen the chatbot last changed (ISO 8601, UTC).
- 400A tenant selector header named a tenant other than the API key's own (
ACCOUNT_SELECTOR_NOT_SUPPORTED): an all-digitX-Account-Idother than the key owner's id or, whileworkspaces.context_enabledis on, anX-Workspace-Idother than the key's workspace (ws_prefix optional, case-insensitive). A header naming the key's own tenant, or a non-numericX-Account-Id, is ignored; a key cannot switch tenants, so send neither.Error codesACCOUNT_SELECTOR_NOT_SUPPORTED
- 401Missing or invalid API key.
Error codesUNAUTHENTICATED
- 403The API key is missing a required scope.
Error codesACCOUNT_SUSPENDEDINSUFFICIENT_SCOPE
- 404The resource does not exist on this account.
Error codesNOT_FOUND
- 429Rate limited. Honour the Retry-After header before retrying.
Error codesRATE_LIMITED
- 500Unexpected server error. Retry with the same Idempotency-Key.
Error codesSERVER_ERROR
Request
curl -X GET 'https://api.agentency.com/v1/chatbots/by_handle/<HANDLE>' \
-H "Authorization: Bearer <YOUR_KEY>" \
-H "Content-Type: application/json"Response
Example 200 response
{
"object": "chatbot",
"id": 1,
"slug": "support-assistant",
"name": "Support Assistant",
"description": "Answers billing and shipping questions.",
"avatar_url": null,
"color": "bg-indigo-500",
"primary_language": "English",
"supported_languages": [],
"text_direction": "LTR",
"status": "active",
"training_status": "never_trained",
"cache_responses": true,
"last_training_date": null,
"last_active_at": null,
"template_id": null,
"response_length": "Short Response",
"audience": "customers",
"knowledge_mode": "strict",
"welcome_message": null,
"fallback_message": null,
"custom_instructions": [],
"enable_handoff": false,
"training_config": [],
"gradient_style": "from-indigo-600 to-blue-600",
"header_theme": "gradient",
"is_image_avatar": false,
"settings": [],
"lead_capture": null,
"allowed_domains": [
"shop.example.com"
],
"created_at": "2026-01-01T00:00:00+00:00",
"updated_at": "2026-01-01T00:00:00+00:00"
}Retrieve a chatbot
name, slug), answer behaviour (audience, knowledge_mode, response_length, messages and instructions), appearance, widget settings, lead_capture and the widget allowlist. A chatbot of another account is 404 NOT_FOUND.- Required scope
- chatbots:read
- Idempotency
- Read-only
- Rate limits
Integer.id(path)Chatbot idPlaceholder in the samples:
<CHATBOT_ID>Get it from
- GET /v1/chatbots returns it as
data[].id - POST /v1/chatbots returns it as
id - GET /v1/chatbots/by_handle/{handle} returns it as
id - Webhook chatbot.created carries it as
data.object.id - In the dashboard, it is the number in a chatbot's address:
/dashboard/chatbots/{id}.
- GET /v1/chatbots returns it as
Path parameters
idintegerRequiredThe chatbot id.
Responses
- 200
ChatbotResourceobjectstringRequiredAlways
chatbotidintegerRequiredThe chatbot id, used in every/chatbots/{id}path and aschatbot_idelsewhere.slugstringRequiredThe public handle: the hosted agent page lives at/agent/{slug}. Unique across the platform;PUT /chatbots/{id}/handlechanges it, a rename never does.namestringRequiredDisplay name, unique within the account.descriptionstringnullableRequiredYour own description of the chatbot;nullwhen none.avatar_urlstringnullableRequiredAbsolute URL of the avatar image;nullwhen the chatbot has none.colorstringRequiredFlat header colour: a theme token or a#rrggbbhex. Used whenheader_themeisflat.primary_languagestringRequiredThe language the chatbot answers in, e.g.English.supported_languagesobjectRequiredFurther languages the chatbot is set up for;[]when none.text_directionstringRequiredLTRorRTL, derived fromprimary_language.statusstringRequiredLifecycle status. The widget and hosted page serve only anactivechatbot; a new one isdraft.Possible values
activeinactivedrafttraining_statusstringRequiredWhere training of the chatbot's knowledge stands.completedonce every source is trained;never_trainedbefore any.Possible values
never_trainedpendingtrainingupdatingneeds_retrainingcompletedfailedcache_responsesbooleanRequiredWhether a repeated question may be answered from the response cache instead of a new model call.last_training_datestringnullableRequiredWhen training last completed (ISO 8601, UTC);nullbefore the first.last_active_atstringnullableRequiredWhen the chatbot last answered a chat turn (ISO 8601, UTC);nullbefore the first.template_idintegernullableRequiredThe catalogue template the chatbot was created from;nullwhen none.response_lengthstringRequiredAnswer length preset:Short ResponseorLong Response.audiencestringRequiredWho the chatbot serves:customers(it speaks for the business) orpersonal(the owner's private assistant).customersunless set at creation.knowledge_modestringRequiredHow far answers may step outside the knowledge base:strict(knowledge only) orgeneral(general knowledge when the knowledge base has nothing).strictunless set at creation.welcome_messagestringnullableRequiredThe first message the widget and hosted page show;nullfor the default greeting.fallback_messagestringnullableRequiredThe reply sent when the chatbot cannot produce an answer;nullfor the platform default.custom_instructionsobjectRequiredYour extra instructions for every answer, one string per instruction;[]when none. The plan caps how many.enable_handoffbooleanRequiredWhether the chatbot may hand a conversation to a human.training_configobjectRequiredTraining and retrieval tuning set throughPATCH /chatbots/{id};[]when never set.gradient_stylestringRequiredHeader gradient: a theme token or a#rrggbb,#rrggbbpair. Used whenheader_themeisgradient.header_themestringRequiredHeader fill:gradient(usesgradient_style) orflat(usescolor).is_image_avatarbooleanRequiredWhether the avatar is an uploaded image (POST /chatbots/{id}/avatar).settingsobjectRequiredThe widget look-and-behaviour keys set on the chatbot (PUT /chatbots/{chatbotId}/widget). A key never set is absent.lead_captureobjectnullableRequiredLead capture: whether the widget asks visitors for contact details (enabled), when (trigger), whichfields, and whether they may skip it;nullwhen never configured.allowed_domainsobjectRequiredHostnames whose pages may load the widget;[]lets it load on any site. Managed with the/chatbots/{chatbotId}/widget/domainsoperations.created_atstringnullableRequiredWhen the chatbot was created (ISO 8601, UTC).updated_atstringnullableRequiredWhen the chatbot last changed (ISO 8601, UTC).
- 400A tenant selector header named a tenant other than the API key's own (
ACCOUNT_SELECTOR_NOT_SUPPORTED): an all-digitX-Account-Idother than the key owner's id or, whileworkspaces.context_enabledis on, anX-Workspace-Idother than the key's workspace (ws_prefix optional, case-insensitive). A header naming the key's own tenant, or a non-numericX-Account-Id, is ignored; a key cannot switch tenants, so send neither.Error codesACCOUNT_SELECTOR_NOT_SUPPORTED
- 401Missing or invalid API key.
Error codesUNAUTHENTICATED
- 403The API key is missing a required scope.
Error codesACCOUNT_SUSPENDEDINSUFFICIENT_SCOPE
- 404The resource does not exist on this account.
Error codesNOT_FOUND
- 429Rate limited. Honour the Retry-After header before retrying.
Error codesRATE_LIMITED
- 500Unexpected server error. Retry with the same Idempotency-Key.
Error codesSERVER_ERROR
Request
curl -X GET 'https://api.agentency.com/v1/chatbots/<CHATBOT_ID>' \
-H "Authorization: Bearer <YOUR_KEY>" \
-H "Content-Type: application/json"Response
Example 200 response
{
"object": "chatbot",
"id": 1,
"slug": "support-assistant",
"name": "Support Assistant",
"description": "Answers billing and shipping questions.",
"avatar_url": null,
"color": "bg-indigo-500",
"primary_language": "English",
"supported_languages": [],
"text_direction": "LTR",
"status": "active",
"training_status": "never_trained",
"cache_responses": true,
"last_training_date": null,
"last_active_at": null,
"template_id": null,
"response_length": "Short Response",
"audience": "customers",
"knowledge_mode": "strict",
"welcome_message": null,
"fallback_message": null,
"custom_instructions": [],
"enable_handoff": false,
"training_config": [],
"gradient_style": "from-indigo-600 to-blue-600",
"header_theme": "gradient",
"is_image_avatar": false,
"settings": [],
"lead_capture": null,
"allowed_domains": [
"shop.example.com"
],
"created_at": "2026-01-01T00:00:00+00:00",
"updated_at": "2026-01-01T00:00:00+00:00"
}Update a chatbot
settings is merged key by key into the stored settings (keys you omit keep their value); every other field replaces its value. Renaming to a name another chatbot of the account already has is 409 CHATBOT_NAME_TAKEN; a rename never changes the handle (slug), so shared links keep working.
status can be set here too, but only POST /chatbots/{id}/activate and /deactivate emit chatbot.activated / chatbot.deactivated; this operation emits chatbot.updated.- Required scope
- chatbots:write
- Idempotency
- Accepts Idempotency-Key
- Webhook events
- chatbot.updated
- Rate limits
Integer.id(path)Chatbot idPlaceholder in the samples:
<CHATBOT_ID>Get it from
- GET /v1/chatbots returns it as
data[].id - POST /v1/chatbots returns it as
id - GET /v1/chatbots/by_handle/{handle} returns it as
id - Webhook chatbot.created carries it as
data.object.id - In the dashboard, it is the number in a chatbot's address:
/dashboard/chatbots/{id}.
- GET /v1/chatbots returns it as
Path parameters
idintegerRequiredThe chatbot id.
Header parameters
Idempotency-KeystringOptionalMakes a retry safe. The first 2xx answer is stored for 24 h and replayed for the same key withIdempotency-Replayed: true; a retry while the first request runs is 409IDEMPOTENCY_IN_FLIGHT; the same key with a different payload is 422IDEMPOTENCY_KEY_REUSED; a malformed key is 400INVALID_IDEMPOTENCY_KEY.Min length:
16Max length:128Pattern:^[A-Za-z0-9_-]+$
Request body
/v1 update chatbot payload. Field set is pinned on this class so a
dashboard FormRequest tweak cannot silently widen the public contract.namestringOptionalDisplay name, at most 255 characters. Renaming to a name another chatbot of the account has is 409CHATBOT_NAME_TAKEN. The handle (slug) does not change.Max length:
255descriptionstringnullableOptionalOptional longer description.Max length:
500primary_languagestringOptionalThe language the chatbot answers in. Omit it to keep the current one;text_directionfollows it.Possible values
EnglishArabicSpanishFrenchGermanPortugueseHindiBengaliUrduJapaneseIndonesianTurkishRussianKoreanVietnamesesupported_languagesarray of stringOptionalFurther languages the chatbot is set up for, from the same list asprimary_language. Replaces the stored list.text_directionstringOptionalDerived fromprimary_language; a client-supplied value is accepted and ignored.Possible values
LTRRTLresponse_lengthstringOptionalAnswer length preset:Short ResponseorLong Response.Possible values
Short ResponseLong ResponseaudiencestringOptionalWho the agent serves:customers(it speaks for the business) orpersonal(the owner's private assistant).Possible values
customerspersonalknowledge_modestringOptionalHow far answers may step outside the knowledge base:strict(knowledge only) orgeneral(general knowledge when the knowledge base is silent, flagged as such).Possible values
strictgeneralwelcome_messagestringnullableOptionalThe first message the widget and hosted page show, at most 2000 characters;nullfor the default greeting.Max length:
2000fallback_messagestringnullableOptionalThe reply sent when the chatbot cannot produce an answer, at most 2000 characters;nullfor the platform default.Max length:
2000custom_instructionsarray of stringOptionalExtra instructions applied to every answer, one non-empty string (at most 500 characters) per instruction. The plan caps how many. Replaces the stored list.Max items:
1enable_handoffbooleanOptionalWhether the chatbot may hand a conversation to a human. The first handoff of a conversation emitsconversation.handoff.requested.cache_responsesbooleanOptionalWhether a repeated question may be answered from the response cache instead of a new model call.gradient_styleany ofOptionalHeader gradient: a theme catalog token or a custom two-stop#rrggbb,#rrggbbpair. Hex input is normalised (#RGB, upper case and a missing#are accepted); alpha hex (#rrggbbaa) is refused. A pair on which no text colour (#ffffff,#1f2937,#000000) reaches 4.5:1 at both ends is refused with 422VALIDATION_FAILEDongradient_style. Defaults to the wizard default when omitted.Max length:
100header_themestringOptionalHeader fill:gradient(usesgradient_style) orflat(usescolor).Possible values
flatgradientavatarstringnullableOptionalA stored avatar reference: the path of an image this account uploaded (/uploads/avatars/…), a bundled default avatar or a hex colour;nullclears it. To upload a new image usePOST /chatbots/{id}/avatar.Max length:
512colorany ofOptionalFlat header colour: a theme catalog token or a custom#rrggbb. Hex input is normalised (#RGB, upper case and a missing#are accepted); alpha hex (#rrggbbaa) is refused. Any colour is accepted: the text colour is picked automatically (#ffffff,#1f2937or#000000) to reach WCAG AA 4.5:1. Defaults to the wizard default when omitted.Max length:
20is_image_avatarbooleanOptionalWhetheravataris an uploaded image rather than a colour or default avatar.settingsobjectOptionalWidget / behaviour settings bag. Only the documented keys are accepted; unknown keys are a 422.training_configarray of stringOptionalTraining and retrieval tuning. Replaces the stored value; read it back astraining_config.allowed_domainsarray of stringOptionalThe complete widget allowlist, with the same hostname rules and cap asPUT /chatbots/{chatbotId}/widget/domains. Prefer the widget domain operations: they change one host at a time and never drop a host an active plugin installation owns.Max items:
50statusstringOptionalLifecycle status:draft,activeorinactive. Setting it here emits onlychatbot.updated;POST /chatbots/{id}/activateand/deactivatealso emitchatbot.activated/chatbot.deactivated.Possible values
draftactiveinactivetemplate_idintegerOptionalThe catalogue template the chatbot is based on (an active template id)./v1has no operation that lists templates.lead_captureobjectOptionalOptional pre-reply lead capture configuration. Only the documented keys are accepted.
Responses
- 200
ChatbotResourceobjectstringRequiredAlways
chatbotidintegerRequiredThe chatbot id, used in every/chatbots/{id}path and aschatbot_idelsewhere.slugstringRequiredThe public handle: the hosted agent page lives at/agent/{slug}. Unique across the platform;PUT /chatbots/{id}/handlechanges it, a rename never does.namestringRequiredDisplay name, unique within the account.descriptionstringnullableRequiredYour own description of the chatbot;nullwhen none.avatar_urlstringnullableRequiredAbsolute URL of the avatar image;nullwhen the chatbot has none.colorstringRequiredFlat header colour: a theme token or a#rrggbbhex. Used whenheader_themeisflat.primary_languagestringRequiredThe language the chatbot answers in, e.g.English.supported_languagesobjectRequiredFurther languages the chatbot is set up for;[]when none.text_directionstringRequiredLTRorRTL, derived fromprimary_language.statusstringRequiredLifecycle status. The widget and hosted page serve only anactivechatbot; a new one isdraft.Possible values
activeinactivedrafttraining_statusstringRequiredWhere training of the chatbot's knowledge stands.completedonce every source is trained;never_trainedbefore any.Possible values
never_trainedpendingtrainingupdatingneeds_retrainingcompletedfailedcache_responsesbooleanRequiredWhether a repeated question may be answered from the response cache instead of a new model call.last_training_datestringnullableRequiredWhen training last completed (ISO 8601, UTC);nullbefore the first.last_active_atstringnullableRequiredWhen the chatbot last answered a chat turn (ISO 8601, UTC);nullbefore the first.template_idintegernullableRequiredThe catalogue template the chatbot was created from;nullwhen none.response_lengthstringRequiredAnswer length preset:Short ResponseorLong Response.audiencestringRequiredWho the chatbot serves:customers(it speaks for the business) orpersonal(the owner's private assistant).customersunless set at creation.knowledge_modestringRequiredHow far answers may step outside the knowledge base:strict(knowledge only) orgeneral(general knowledge when the knowledge base has nothing).strictunless set at creation.welcome_messagestringnullableRequiredThe first message the widget and hosted page show;nullfor the default greeting.fallback_messagestringnullableRequiredThe reply sent when the chatbot cannot produce an answer;nullfor the platform default.custom_instructionsobjectRequiredYour extra instructions for every answer, one string per instruction;[]when none. The plan caps how many.enable_handoffbooleanRequiredWhether the chatbot may hand a conversation to a human.training_configobjectRequiredTraining and retrieval tuning set throughPATCH /chatbots/{id};[]when never set.gradient_stylestringRequiredHeader gradient: a theme token or a#rrggbb,#rrggbbpair. Used whenheader_themeisgradient.header_themestringRequiredHeader fill:gradient(usesgradient_style) orflat(usescolor).is_image_avatarbooleanRequiredWhether the avatar is an uploaded image (POST /chatbots/{id}/avatar).settingsobjectRequiredThe widget look-and-behaviour keys set on the chatbot (PUT /chatbots/{chatbotId}/widget). A key never set is absent.lead_captureobjectnullableRequiredLead capture: whether the widget asks visitors for contact details (enabled), when (trigger), whichfields, and whether they may skip it;nullwhen never configured.allowed_domainsobjectRequiredHostnames whose pages may load the widget;[]lets it load on any site. Managed with the/chatbots/{chatbotId}/widget/domainsoperations.created_atstringnullableRequiredWhen the chatbot was created (ISO 8601, UTC).updated_atstringnullableRequiredWhen the chatbot last changed (ISO 8601, UTC).
- 400A tenant selector header named a tenant other than the API key's own (
ACCOUNT_SELECTOR_NOT_SUPPORTED): an all-digitX-Account-Idother than the key owner's id or, whileworkspaces.context_enabledis on, anX-Workspace-Idother than the key's workspace (ws_prefix optional, case-insensitive). A header naming the key's own tenant, or a non-numericX-Account-Id, is ignored; a key cannot switch tenants, so send neither. A mutation that honoursIdempotency-Keyalso returnsINVALID_IDEMPOTENCY_KEYwhen that header is not 16–128[A-Za-z0-9_-]characters.Error codesACCOUNT_SELECTOR_NOT_SUPPORTEDINVALID_IDEMPOTENCY_KEY
- 401Missing or invalid API key.
Error codesUNAUTHENTICATED
- 403The API key is missing a required scope.
Error codesACCOUNT_SUSPENDEDINSUFFICIENT_SCOPE
- 404The resource does not exist on this account.
Error codesNOT_FOUND
- 409The request conflicts with the current resource state.
Error codesCHATBOT_NAME_TAKENIDEMPOTENCY_IN_FLIGHT
- 422Validation failed. See
error.details.Error codesIDEMPOTENCY_KEY_REUSEDVALIDATION_FAILED
- 429Rate limited. Honour the Retry-After header before retrying.
Error codesRATE_LIMITED
- 500Unexpected server error. Retry with the same Idempotency-Key.
Error codesSERVER_ERROR
Request
curl -X PATCH 'https://api.agentency.com/v1/chatbots/<CHATBOT_ID>' \
-H "Authorization: Bearer <YOUR_KEY>" \
-H "Content-Type: application/json"
-d '{
"name": "name",
"description": "description",
"primary_language": "primary_language",
"supported_languages": [],
"text_direction": "text_direction",
"response_length": "response_length",
"audience": "audience",
"knowledge_mode": "knowledge_mode"
}'Response
Example 200 response
{
"object": "chatbot",
"id": 1,
"slug": "orders-assistant",
"name": "Orders Assistant",
"description": "Tracks orders and deliveries.",
"avatar_url": null,
"color": "bg-indigo-500",
"primary_language": "English",
"supported_languages": [],
"text_direction": "LTR",
"status": "active",
"training_status": "never_trained",
"cache_responses": true,
"last_training_date": null,
"last_active_at": null,
"template_id": null,
"response_length": "Short Response",
"audience": "customers",
"knowledge_mode": "strict",
"welcome_message": "Hi! Ask me about orders, shipping or refunds.",
"fallback_message": null,
"custom_instructions": [],
"enable_handoff": false,
"training_config": [],
"gradient_style": "from-indigo-600 to-blue-600",
"header_theme": "gradient",
"is_image_avatar": false,
"settings": {
"widget_position": "bottom-left"
},
"lead_capture": null,
"allowed_domains": [],
"created_at": "2026-01-01T00:00:00+00:00",
"updated_at": "2026-01-01T00:00:00+00:00"
}Delete a chatbot
DELETE /chatbots/{chatbotId}/channels/{platform}) if their webhooks should be removed. A key limited to chosen chatbots needs admin access on this one.- Required scope
- chatbots:write
- Idempotency
- Accepts Idempotency-Key
- Webhook events
- chatbot.deleted
- Rate limits
Integer.id(path)Chatbot idPlaceholder in the samples:
<CHATBOT_ID>Get it from
- GET /v1/chatbots returns it as
data[].id - POST /v1/chatbots returns it as
id - GET /v1/chatbots/by_handle/{handle} returns it as
id - Webhook chatbot.created carries it as
data.object.id - In the dashboard, it is the number in a chatbot's address:
/dashboard/chatbots/{id}.
- GET /v1/chatbots returns it as
Path parameters
idintegerRequiredThe chatbot id.
Header parameters
Idempotency-KeystringOptionalMakes a retry safe. The first 2xx answer is stored for 24 h and replayed for the same key withIdempotency-Replayed: true; a retry while the first request runs is 409IDEMPOTENCY_IN_FLIGHT; the same key with a different payload is 422IDEMPOTENCY_KEY_REUSED; a malformed key is 400INVALID_IDEMPOTENCY_KEY.Min length:
16Max length:128Pattern:^[A-Za-z0-9_-]+$
Responses
- 200Success.
objectstringRequiredAlways
chatbotidintegerRequireddeletedbooleanRequired
- 400A tenant selector header named a tenant other than the API key's own (
ACCOUNT_SELECTOR_NOT_SUPPORTED): an all-digitX-Account-Idother than the key owner's id or, whileworkspaces.context_enabledis on, anX-Workspace-Idother than the key's workspace (ws_prefix optional, case-insensitive). A header naming the key's own tenant, or a non-numericX-Account-Id, is ignored; a key cannot switch tenants, so send neither. A mutation that honoursIdempotency-Keyalso returnsINVALID_IDEMPOTENCY_KEYwhen that header is not 16–128[A-Za-z0-9_-]characters.Error codesACCOUNT_SELECTOR_NOT_SUPPORTEDINVALID_IDEMPOTENCY_KEY
- 401Missing or invalid API key.
Error codesUNAUTHENTICATED
- 403The API key is missing a required scope.
Error codesACCOUNT_SUSPENDEDINSUFFICIENT_SCOPE
- 404The resource does not exist on this account.
Error codesNOT_FOUND
- 409The request conflicts with the current resource state.
Error codesIDEMPOTENCY_IN_FLIGHT
- 422Validation failed. See
error.details.Error codesIDEMPOTENCY_KEY_REUSED
- 429Rate limited. Honour the Retry-After header before retrying.
Error codesRATE_LIMITED
- 500Unexpected server error. Retry with the same Idempotency-Key.
Error codesSERVER_ERROR
Request
curl -X DELETE 'https://api.agentency.com/v1/chatbots/<CHATBOT_ID>' \
-H "Authorization: Bearer <YOUR_KEY>" \
-H "Content-Type: application/json"Response
Example 200 response
{
"object": "chatbot",
"id": 1,
"deleted": true
}Check whether a chatbot is ready
ready is true only when status is active and training_status is completed. Poll it after creating a chatbot and adding knowledge, or subscribe to knowledge.dataset.trained instead.
ready: false does not block POST /chat, which answers for a chatbot in any status: it means the widget and hosted page do not serve the chatbot yet, or its knowledge is not fully trained (any training_status other than completed).- Required scope
- chatbots:read
- Idempotency
- Read-only
- Rate limits
Integer.id(path)Chatbot idPlaceholder in the samples:
<CHATBOT_ID>Get it from
- GET /v1/chatbots returns it as
data[].id - POST /v1/chatbots returns it as
id - GET /v1/chatbots/by_handle/{handle} returns it as
id - Webhook chatbot.created carries it as
data.object.id - In the dashboard, it is the number in a chatbot's address:
/dashboard/chatbots/{id}.
- GET /v1/chatbots returns it as
Path parameters
idintegerRequiredThe chatbot id.
Responses
- 200Success.
objectstringRequiredAlways
chatbot_readinessidintegerRequiredThe chatbot id.statusstringRequiredThe chatbot's lifecycle status:active,inactiveordraft.training_statusstringRequiredWhere training of the chatbot's knowledge stands.documents_countintegerRequiredKnowledge documents the chatbot holds.knowledge_size_bytesintegerRequiredSize of the chatbot's knowledge, the measure the plan's knowledge quota counts: extracted text characters, one byte each.readybooleanRequiredtruewhenstatusisactiveandtraining_statusiscompleted.
- 400A tenant selector header named a tenant other than the API key's own (
ACCOUNT_SELECTOR_NOT_SUPPORTED): an all-digitX-Account-Idother than the key owner's id or, whileworkspaces.context_enabledis on, anX-Workspace-Idother than the key's workspace (ws_prefix optional, case-insensitive). A header naming the key's own tenant, or a non-numericX-Account-Id, is ignored; a key cannot switch tenants, so send neither.Error codesACCOUNT_SELECTOR_NOT_SUPPORTED
- 401Missing or invalid API key.
Error codesUNAUTHENTICATED
- 403The API key is missing a required scope.
Error codesACCOUNT_SUSPENDEDINSUFFICIENT_SCOPE
- 404The resource does not exist on this account.
Error codesNOT_FOUND
- 429Rate limited. Honour the Retry-After header before retrying.
Error codesRATE_LIMITED
- 500Unexpected server error. Retry with the same Idempotency-Key.
Error codesSERVER_ERROR
Request
curl -X GET 'https://api.agentency.com/v1/chatbots/<CHATBOT_ID>/readiness' \
-H "Authorization: Bearer <YOUR_KEY>" \
-H "Content-Type: application/json"Response
Example 200 response
{
"object": "chatbot_readiness",
"id": 1,
"status": "active",
"training_status": "never_trained",
"documents_count": 0,
"knowledge_size_bytes": 500,
"ready": false
}Retrieve a chatbot's hosted page access
/agent/{handle}): whether the page is published (hosted_page_enabled), the access mode and whether its gate is on, whether a share secret or password is set (never their values), and the visitor logins of credentialed mode.- Required scope
- chatbots:read
- Idempotency
- Read-only
- Rate limits
Integer.id(path)Chatbot idPlaceholder in the samples:
<CHATBOT_ID>Get it from
- GET /v1/chatbots returns it as
data[].id - POST /v1/chatbots returns it as
id - GET /v1/chatbots/by_handle/{handle} returns it as
id - Webhook chatbot.created carries it as
data.object.id - In the dashboard, it is the number in a chatbot's address:
/dashboard/chatbots/{id}.
- GET /v1/chatbots returns it as
Path parameters
idintegerRequiredThe chatbot id.
Responses
- 200
AgentAccessResourcechatbot_idintegerRequiredThe chatbot this access configuration belongs to.handlestringRequiredThe chatbot's public handle: its hosted page lives at/agent/{handle}.hosted_page_enabledbooleanRequiredWhether the hosted agent page is published at all. Whilefalsethe page is offline whatevermodesays.modestringRequiredWho may open the hosted page:public(anyone with the link),secret(the link plus the share secret),password(a shared password) orcredentialed(one of the visitor logins inaccounts).Possible values
publicsecretpasswordcredentialedenabledbooleanRequiredWhether the gate ofmodeis on. Alwaysfalseinpublicmode; a disabled gate behaves likepublic.has_secretbooleanRequiredWhether a share secret is stored. The secret itself is returned once, by thePUT /chatbots/{id}/accessthat minted it.has_passwordbooleanRequiredWhether a shared password is stored forpasswordmode. The password is never returned.token_versionintegerRequiredRevocation epoch of the visitor access tokens.PUT /chatbots/{id}/accesswithrevoke: trueraises it, which signs every visitor out.max_accountsintegerRequiredHow many visitor loginsaccountsmay hold.accountsarray of AgentAccessAccountResourceOptionalThe visitor logins ofcredentialedmode, managed withPOSTandDELETE /chatbots/{id}/access/accounts.objectstringRequiredAlways
chatbot_accessidintegerRequiredThe chatbot id (the same value aschatbot_id).
- 400A tenant selector header named a tenant other than the API key's own (
ACCOUNT_SELECTOR_NOT_SUPPORTED): an all-digitX-Account-Idother than the key owner's id or, whileworkspaces.context_enabledis on, anX-Workspace-Idother than the key's workspace (ws_prefix optional, case-insensitive). A header naming the key's own tenant, or a non-numericX-Account-Id, is ignored; a key cannot switch tenants, so send neither.Error codesACCOUNT_SELECTOR_NOT_SUPPORTED
- 401Missing or invalid API key.
Error codesUNAUTHENTICATED
- 403The API key is missing a required scope.
Error codesACCOUNT_SUSPENDEDINSUFFICIENT_SCOPE
- 404The resource does not exist on this account.
Error codesNOT_FOUND
- 429Rate limited. Honour the Retry-After header before retrying.
Error codesRATE_LIMITED
- 500Unexpected server error. Retry with the same Idempotency-Key.
Error codesSERVER_ERROR
Request
curl -X GET 'https://api.agentency.com/v1/chatbots/<CHATBOT_ID>/access' \
-H "Authorization: Bearer <YOUR_KEY>" \
-H "Content-Type: application/json"Response
Example 200 response
{
"chatbot_id": 1,
"handle": "support-assistant",
"hosted_page_enabled": true,
"mode": "public",
"enabled": false,
"has_secret": false,
"has_password": false,
"token_version": 1,
"max_accounts": 100,
"accounts": [
{
"id": 1,
"identifier_type": "email",
"identifier": "support-lead@example.com",
"label": "Support lead",
"enabled": true,
"last_login_at": null,
"created_at": "2026-01-01T00:00:00+00:00"
}
],
"object": "chatbot_access",
"id": 1
}Set a chatbot's hosted page access
mode and enabled are required on every call; password and hosted_page_enabled keep their stored value when omitted.
secret mode: the first switch to it, or regenerate_secret: true, mints a share secret and returns it once as secret; store it, it is never shown again.
password mode needs a password, sent now or already stored; an empty string clears it.
credentialed mode needs at least one enabled visitor login (POST /chatbots/{id}/access/accounts).
revoke: true signs every visitor out by raising token_version.
A body that would leave the gate unusable (password mode with no password, credentialed mode with no enabled login) is 422 VALIDATION_FAILED. It emits no webhook event.- Required scope
- chatbots:write
- Idempotency
- Accepts Idempotency-Key
- Webhook events
- None
- Rate limits
Integer.id(path)Chatbot idPlaceholder in the samples:
<CHATBOT_ID>Get it from
- GET /v1/chatbots returns it as
data[].id - POST /v1/chatbots returns it as
id - GET /v1/chatbots/by_handle/{handle} returns it as
id - Webhook chatbot.created carries it as
data.object.id - In the dashboard, it is the number in a chatbot's address:
/dashboard/chatbots/{id}.
- GET /v1/chatbots returns it as
Path parameters
idintegerRequiredThe chatbot id.
Header parameters
Idempotency-KeystringOptionalMakes a retry safe. The first 2xx answer is stored for 24 h and replayed for the same key withIdempotency-Replayed: true; a retry while the first request runs is 409IDEMPOTENCY_IN_FLIGHT; the same key with a different payload is 422IDEMPOTENCY_KEY_REUSED; a malformed key is 400INVALID_IDEMPOTENCY_KEY.Min length:
16Max length:128Pattern:^[A-Za-z0-9_-]+$
Request body
/v1 access payload. Field set is pinned on this class so a
dashboard FormRequest tweak cannot silently widen the public contract.
hosted_page_enabled is deliberately part of it (owner decision
2026-09-19): an API key holding chatbots:write may publish / unpublish
the hosted page like the dashboard does.modestringRequiredWho may open the hosted page:public(anyone with the link),secret(the link plus a share secret),password(a shared password) orcredentialed(a visitor login).Possible values
publicsecretpasswordcredentialedenabledbooleanRequiredWhether the gate ofmodeis on. A disabled gate behaves likepublic;publicis always stored as disabled.passwordstringnullableOptionalThe shared password ofpasswordmode, at least 8 characters. Omit it to keep the stored one; an empty string clears it. Refused in any other mode.Min length:
8Max length:200regenerate_secretbooleanOptionaltruemints a new share secret, returned once assecret. Only withmode: secret; switching tosecretmode with no stored secret mints one anyway.revokebooleanOptionaltruesigns every visitor out: issued visitor access tokens stop working (token_versionrises).hosted_page_enabledbooleanOptionalPublishes (true) or unpublishes (false) the hosted agent page. Omit it to keep the current value.
Responses
- 200Success.
chatbot_idintegerRequiredThe chatbot this access configuration belongs to.handlestringRequiredThe chatbot's public handle: its hosted page lives at/agent/{handle}.hosted_page_enabledbooleanRequiredWhether the hosted agent page is published at all. Whilefalsethe page is offline whatevermodesays.modestringRequiredWho may open the hosted page:public(anyone with the link),secret(the link plus the share secret),password(a shared password) orcredentialed(one of the visitor logins inaccounts).Possible values
publicsecretpasswordcredentialedenabledbooleanRequiredWhether the gate ofmodeis on. Alwaysfalseinpublicmode; a disabled gate behaves likepublic.has_secretbooleanRequiredWhether a share secret is stored. The secret itself is returned once, by thePUT /chatbots/{id}/accessthat minted it.has_passwordbooleanRequiredWhether a shared password is stored forpasswordmode. The password is never returned.token_versionintegerRequiredRevocation epoch of the visitor access tokens.PUT /chatbots/{id}/accesswithrevoke: trueraises it, which signs every visitor out.max_accountsintegerRequiredHow many visitor loginsaccountsmay hold.accountsarray of AgentAccessAccountResourceOptionalThe visitor logins ofcredentialedmode, managed withPOSTandDELETE /chatbots/{id}/access/accounts.objectstringRequiredAlways
chatbot_accessidintegerRequiredThe chatbot id (the same value aschatbot_id).secretstringOptionalThe share secret, present only on the response of the request that minted it. It is never returned again.
- 400A tenant selector header named a tenant other than the API key's own (
ACCOUNT_SELECTOR_NOT_SUPPORTED): an all-digitX-Account-Idother than the key owner's id or, whileworkspaces.context_enabledis on, anX-Workspace-Idother than the key's workspace (ws_prefix optional, case-insensitive). A header naming the key's own tenant, or a non-numericX-Account-Id, is ignored; a key cannot switch tenants, so send neither. A mutation that honoursIdempotency-Keyalso returnsINVALID_IDEMPOTENCY_KEYwhen that header is not 16–128[A-Za-z0-9_-]characters.Error codesACCOUNT_SELECTOR_NOT_SUPPORTEDINVALID_IDEMPOTENCY_KEY
- 401Missing or invalid API key.
Error codesUNAUTHENTICATED
- 403The API key is missing a required scope.
Error codesACCOUNT_SUSPENDEDINSUFFICIENT_SCOPE
- 404The resource does not exist on this account.
Error codesNOT_FOUND
- 409The request conflicts with the current resource state.
Error codesIDEMPOTENCY_IN_FLIGHT
- 422Validation failed. See
error.details.Error codesIDEMPOTENCY_KEY_REUSEDVALIDATION_FAILED
- 429Rate limited. Honour the Retry-After header before retrying.
Error codesRATE_LIMITED
- 500Unexpected server error. Retry with the same Idempotency-Key.
Error codesSERVER_ERROR
Request
curl -X PUT 'https://api.agentency.com/v1/chatbots/<CHATBOT_ID>/access' \
-H "Authorization: Bearer <YOUR_KEY>" \
-H "Content-Type: application/json"
-d '{
"mode": "mode",
"enabled": true,
"password": "password",
"regenerate_secret": true,
"revoke": true,
"hosted_page_enabled": true
}'Response
Example 200 response
{
"chatbot_id": 1,
"handle": "acme-orders",
"hosted_page_enabled": true,
"mode": "credentialed",
"enabled": false,
"has_secret": false,
"has_password": false,
"token_version": 2,
"max_accounts": 100,
"accounts": [],
"object": "chatbot_access",
"id": 1
}Activate a chatbot
status to active, which puts the chatbot live on its website widget and hosted agent page, and returns it. Activating an already active chatbot succeeds and emits chatbot.activated again. It does not train the chatbot: check GET /chatbots/{id}/readiness.- Required scope
- chatbots:write
- Idempotency
- Accepts Idempotency-Key
- Webhook events
- chatbot.activated
- Rate limits
Integer.id(path)Chatbot idPlaceholder in the samples:
<CHATBOT_ID>Get it from
- GET /v1/chatbots returns it as
data[].id - POST /v1/chatbots returns it as
id - GET /v1/chatbots/by_handle/{handle} returns it as
id - Webhook chatbot.created carries it as
data.object.id - In the dashboard, it is the number in a chatbot's address:
/dashboard/chatbots/{id}.
- GET /v1/chatbots returns it as
Path parameters
idintegerRequiredThe chatbot id.
Header parameters
Idempotency-KeystringOptionalMakes a retry safe. The first 2xx answer is stored for 24 h and replayed for the same key withIdempotency-Replayed: true; a retry while the first request runs is 409IDEMPOTENCY_IN_FLIGHT; the same key with a different payload is 422IDEMPOTENCY_KEY_REUSED; a malformed key is 400INVALID_IDEMPOTENCY_KEY.Min length:
16Max length:128Pattern:^[A-Za-z0-9_-]+$
Responses
- 200
ChatbotResourceobjectstringRequiredAlways
chatbotidintegerRequiredThe chatbot id, used in every/chatbots/{id}path and aschatbot_idelsewhere.slugstringRequiredThe public handle: the hosted agent page lives at/agent/{slug}. Unique across the platform;PUT /chatbots/{id}/handlechanges it, a rename never does.namestringRequiredDisplay name, unique within the account.descriptionstringnullableRequiredYour own description of the chatbot;nullwhen none.avatar_urlstringnullableRequiredAbsolute URL of the avatar image;nullwhen the chatbot has none.colorstringRequiredFlat header colour: a theme token or a#rrggbbhex. Used whenheader_themeisflat.primary_languagestringRequiredThe language the chatbot answers in, e.g.English.supported_languagesobjectRequiredFurther languages the chatbot is set up for;[]when none.text_directionstringRequiredLTRorRTL, derived fromprimary_language.statusstringRequiredLifecycle status. The widget and hosted page serve only anactivechatbot; a new one isdraft.Possible values
activeinactivedrafttraining_statusstringRequiredWhere training of the chatbot's knowledge stands.completedonce every source is trained;never_trainedbefore any.Possible values
never_trainedpendingtrainingupdatingneeds_retrainingcompletedfailedcache_responsesbooleanRequiredWhether a repeated question may be answered from the response cache instead of a new model call.last_training_datestringnullableRequiredWhen training last completed (ISO 8601, UTC);nullbefore the first.last_active_atstringnullableRequiredWhen the chatbot last answered a chat turn (ISO 8601, UTC);nullbefore the first.template_idintegernullableRequiredThe catalogue template the chatbot was created from;nullwhen none.response_lengthstringRequiredAnswer length preset:Short ResponseorLong Response.audiencestringRequiredWho the chatbot serves:customers(it speaks for the business) orpersonal(the owner's private assistant).customersunless set at creation.knowledge_modestringRequiredHow far answers may step outside the knowledge base:strict(knowledge only) orgeneral(general knowledge when the knowledge base has nothing).strictunless set at creation.welcome_messagestringnullableRequiredThe first message the widget and hosted page show;nullfor the default greeting.fallback_messagestringnullableRequiredThe reply sent when the chatbot cannot produce an answer;nullfor the platform default.custom_instructionsobjectRequiredYour extra instructions for every answer, one string per instruction;[]when none. The plan caps how many.enable_handoffbooleanRequiredWhether the chatbot may hand a conversation to a human.training_configobjectRequiredTraining and retrieval tuning set throughPATCH /chatbots/{id};[]when never set.gradient_stylestringRequiredHeader gradient: a theme token or a#rrggbb,#rrggbbpair. Used whenheader_themeisgradient.header_themestringRequiredHeader fill:gradient(usesgradient_style) orflat(usescolor).is_image_avatarbooleanRequiredWhether the avatar is an uploaded image (POST /chatbots/{id}/avatar).settingsobjectRequiredThe widget look-and-behaviour keys set on the chatbot (PUT /chatbots/{chatbotId}/widget). A key never set is absent.lead_captureobjectnullableRequiredLead capture: whether the widget asks visitors for contact details (enabled), when (trigger), whichfields, and whether they may skip it;nullwhen never configured.allowed_domainsobjectRequiredHostnames whose pages may load the widget;[]lets it load on any site. Managed with the/chatbots/{chatbotId}/widget/domainsoperations.created_atstringnullableRequiredWhen the chatbot was created (ISO 8601, UTC).updated_atstringnullableRequiredWhen the chatbot last changed (ISO 8601, UTC).
- 400A tenant selector header named a tenant other than the API key's own (
ACCOUNT_SELECTOR_NOT_SUPPORTED): an all-digitX-Account-Idother than the key owner's id or, whileworkspaces.context_enabledis on, anX-Workspace-Idother than the key's workspace (ws_prefix optional, case-insensitive). A header naming the key's own tenant, or a non-numericX-Account-Id, is ignored; a key cannot switch tenants, so send neither. A mutation that honoursIdempotency-Keyalso returnsINVALID_IDEMPOTENCY_KEYwhen that header is not 16–128[A-Za-z0-9_-]characters.Error codesACCOUNT_SELECTOR_NOT_SUPPORTEDINVALID_IDEMPOTENCY_KEY
- 401Missing or invalid API key.
Error codesUNAUTHENTICATED
- 403The API key is missing a required scope.
Error codesACCOUNT_SUSPENDEDINSUFFICIENT_SCOPE
- 404The resource does not exist on this account.
Error codesNOT_FOUND
- 409The request conflicts with the current resource state.
Error codesIDEMPOTENCY_IN_FLIGHT
- 422Validation failed. See
error.details.Error codesIDEMPOTENCY_KEY_REUSED
- 429Rate limited. Honour the Retry-After header before retrying.
Error codesRATE_LIMITED
- 500Unexpected server error. Retry with the same Idempotency-Key.
Error codesSERVER_ERROR
Request
curl -X POST 'https://api.agentency.com/v1/chatbots/<CHATBOT_ID>/activate' \
-H "Authorization: Bearer <YOUR_KEY>" \
-H "Content-Type: application/json"Response
Example 200 response
{
"object": "chatbot",
"id": 1,
"slug": "orders-assistant",
"name": "Orders Assistant",
"description": "Tracks orders and deliveries.",
"avatar_url": null,
"color": "bg-indigo-500",
"primary_language": "English",
"supported_languages": [],
"text_direction": "LTR",
"status": "active",
"training_status": "never_trained",
"cache_responses": true,
"last_training_date": null,
"last_active_at": null,
"template_id": null,
"response_length": "Short Response",
"audience": "customers",
"knowledge_mode": "strict",
"welcome_message": "Hi! Ask me about orders, shipping or refunds.",
"fallback_message": null,
"custom_instructions": [],
"enable_handoff": false,
"training_config": [],
"gradient_style": "from-indigo-600 to-blue-600",
"header_theme": "gradient",
"is_image_avatar": false,
"settings": {
"widget_position": "bottom-left"
},
"lead_capture": null,
"allowed_domains": [],
"created_at": "2026-01-01T00:00:00+00:00",
"updated_at": "2026-01-01T00:00:00+00:00"
}Deactivate a chatbot
status to inactive, which takes the chatbot offline on its website widget and hosted agent page, and returns it. Its knowledge, conversations and channels are kept, and POST /chat still answers for it. Deactivating an inactive chatbot succeeds and emits chatbot.deactivated again.- Required scope
- chatbots:write
- Idempotency
- Accepts Idempotency-Key
- Webhook events
- chatbot.deactivated
- Rate limits
Integer.id(path)Chatbot idPlaceholder in the samples:
<CHATBOT_ID>Get it from
- GET /v1/chatbots returns it as
data[].id - POST /v1/chatbots returns it as
id - GET /v1/chatbots/by_handle/{handle} returns it as
id - Webhook chatbot.created carries it as
data.object.id - In the dashboard, it is the number in a chatbot's address:
/dashboard/chatbots/{id}.
- GET /v1/chatbots returns it as
Path parameters
idintegerRequiredThe chatbot id.
Header parameters
Idempotency-KeystringOptionalMakes a retry safe. The first 2xx answer is stored for 24 h and replayed for the same key withIdempotency-Replayed: true; a retry while the first request runs is 409IDEMPOTENCY_IN_FLIGHT; the same key with a different payload is 422IDEMPOTENCY_KEY_REUSED; a malformed key is 400INVALID_IDEMPOTENCY_KEY.Min length:
16Max length:128Pattern:^[A-Za-z0-9_-]+$
Responses
- 200
ChatbotResourceobjectstringRequiredAlways
chatbotidintegerRequiredThe chatbot id, used in every/chatbots/{id}path and aschatbot_idelsewhere.slugstringRequiredThe public handle: the hosted agent page lives at/agent/{slug}. Unique across the platform;PUT /chatbots/{id}/handlechanges it, a rename never does.namestringRequiredDisplay name, unique within the account.descriptionstringnullableRequiredYour own description of the chatbot;nullwhen none.avatar_urlstringnullableRequiredAbsolute URL of the avatar image;nullwhen the chatbot has none.colorstringRequiredFlat header colour: a theme token or a#rrggbbhex. Used whenheader_themeisflat.primary_languagestringRequiredThe language the chatbot answers in, e.g.English.supported_languagesobjectRequiredFurther languages the chatbot is set up for;[]when none.text_directionstringRequiredLTRorRTL, derived fromprimary_language.statusstringRequiredLifecycle status. The widget and hosted page serve only anactivechatbot; a new one isdraft.Possible values
activeinactivedrafttraining_statusstringRequiredWhere training of the chatbot's knowledge stands.completedonce every source is trained;never_trainedbefore any.Possible values
never_trainedpendingtrainingupdatingneeds_retrainingcompletedfailedcache_responsesbooleanRequiredWhether a repeated question may be answered from the response cache instead of a new model call.last_training_datestringnullableRequiredWhen training last completed (ISO 8601, UTC);nullbefore the first.last_active_atstringnullableRequiredWhen the chatbot last answered a chat turn (ISO 8601, UTC);nullbefore the first.template_idintegernullableRequiredThe catalogue template the chatbot was created from;nullwhen none.response_lengthstringRequiredAnswer length preset:Short ResponseorLong Response.audiencestringRequiredWho the chatbot serves:customers(it speaks for the business) orpersonal(the owner's private assistant).customersunless set at creation.knowledge_modestringRequiredHow far answers may step outside the knowledge base:strict(knowledge only) orgeneral(general knowledge when the knowledge base has nothing).strictunless set at creation.welcome_messagestringnullableRequiredThe first message the widget and hosted page show;nullfor the default greeting.fallback_messagestringnullableRequiredThe reply sent when the chatbot cannot produce an answer;nullfor the platform default.custom_instructionsobjectRequiredYour extra instructions for every answer, one string per instruction;[]when none. The plan caps how many.enable_handoffbooleanRequiredWhether the chatbot may hand a conversation to a human.training_configobjectRequiredTraining and retrieval tuning set throughPATCH /chatbots/{id};[]when never set.gradient_stylestringRequiredHeader gradient: a theme token or a#rrggbb,#rrggbbpair. Used whenheader_themeisgradient.header_themestringRequiredHeader fill:gradient(usesgradient_style) orflat(usescolor).is_image_avatarbooleanRequiredWhether the avatar is an uploaded image (POST /chatbots/{id}/avatar).settingsobjectRequiredThe widget look-and-behaviour keys set on the chatbot (PUT /chatbots/{chatbotId}/widget). A key never set is absent.lead_captureobjectnullableRequiredLead capture: whether the widget asks visitors for contact details (enabled), when (trigger), whichfields, and whether they may skip it;nullwhen never configured.allowed_domainsobjectRequiredHostnames whose pages may load the widget;[]lets it load on any site. Managed with the/chatbots/{chatbotId}/widget/domainsoperations.created_atstringnullableRequiredWhen the chatbot was created (ISO 8601, UTC).updated_atstringnullableRequiredWhen the chatbot last changed (ISO 8601, UTC).
- 400A tenant selector header named a tenant other than the API key's own (
ACCOUNT_SELECTOR_NOT_SUPPORTED): an all-digitX-Account-Idother than the key owner's id or, whileworkspaces.context_enabledis on, anX-Workspace-Idother than the key's workspace (ws_prefix optional, case-insensitive). A header naming the key's own tenant, or a non-numericX-Account-Id, is ignored; a key cannot switch tenants, so send neither. A mutation that honoursIdempotency-Keyalso returnsINVALID_IDEMPOTENCY_KEYwhen that header is not 16–128[A-Za-z0-9_-]characters.Error codesACCOUNT_SELECTOR_NOT_SUPPORTEDINVALID_IDEMPOTENCY_KEY
- 401Missing or invalid API key.
Error codesUNAUTHENTICATED
- 403The API key is missing a required scope.
Error codesACCOUNT_SUSPENDEDINSUFFICIENT_SCOPE
- 404The resource does not exist on this account.
Error codesNOT_FOUND
- 409The request conflicts with the current resource state.
Error codesIDEMPOTENCY_IN_FLIGHT
- 422Validation failed. See
error.details.Error codesIDEMPOTENCY_KEY_REUSED
- 429Rate limited. Honour the Retry-After header before retrying.
Error codesRATE_LIMITED
- 500Unexpected server error. Retry with the same Idempotency-Key.
Error codesSERVER_ERROR
Request
curl -X POST 'https://api.agentency.com/v1/chatbots/<CHATBOT_ID>/deactivate' \
-H "Authorization: Bearer <YOUR_KEY>" \
-H "Content-Type: application/json"Response
Example 200 response
{
"object": "chatbot",
"id": 1,
"slug": "orders-assistant",
"name": "Orders Assistant",
"description": "Tracks orders and deliveries.",
"avatar_url": null,
"color": "bg-indigo-500",
"primary_language": "English",
"supported_languages": [],
"text_direction": "LTR",
"status": "inactive",
"training_status": "never_trained",
"cache_responses": true,
"last_training_date": null,
"last_active_at": null,
"template_id": null,
"response_length": "Short Response",
"audience": "customers",
"knowledge_mode": "strict",
"welcome_message": "Hi! Ask me about orders, shipping or refunds.",
"fallback_message": null,
"custom_instructions": [],
"enable_handoff": false,
"training_config": [],
"gradient_style": "from-indigo-600 to-blue-600",
"header_theme": "gradient",
"is_image_avatar": false,
"settings": {
"widget_position": "bottom-left"
},
"lead_capture": null,
"allowed_domains": [],
"created_at": "2026-01-01T00:00:00+00:00",
"updated_at": "2026-01-01T00:00:00+00:00"
}Change a chatbot's handle
slug), which is the address of its hosted agent page: /agent/{handle}. Handles are unique across the platform, so one another chatbot holds — on any account — is 422 VALIDATION_FAILED on handle. Setting the current handle again changes nothing.
The old address stops working at once: update every link you shared. It emits no webhook event.- Required scope
- chatbots:write
- Idempotency
- Accepts Idempotency-Key
- Webhook events
- None
- Rate limits
Integer.id(path)Chatbot idPlaceholder in the samples:
<CHATBOT_ID>Get it from
- GET /v1/chatbots returns it as
data[].id - POST /v1/chatbots returns it as
id - GET /v1/chatbots/by_handle/{handle} returns it as
id - Webhook chatbot.created carries it as
data.object.id - In the dashboard, it is the number in a chatbot's address:
/dashboard/chatbots/{id}.
- GET /v1/chatbots returns it as
Path parameters
idintegerRequiredThe chatbot id.
Header parameters
Idempotency-KeystringOptionalMakes a retry safe. The first 2xx answer is stored for 24 h and replayed for the same key withIdempotency-Replayed: true; a retry while the first request runs is 409IDEMPOTENCY_IN_FLIGHT; the same key with a different payload is 422IDEMPOTENCY_KEY_REUSED; a malformed key is 400INVALID_IDEMPOTENCY_KEY.Min length:
16Max length:128Pattern:^[A-Za-z0-9_-]+$
Request body
/v1 update chatbot handle payload. Field set is pinned on this class so a
dashboard FormRequest tweak cannot silently widen the public contract.handlestringRequiredThe new handle: lowercase letters and digits with single inner hyphens, 3–40 characters, not all digits and not a reserved word. Unique across the platform: one another chatbot holds is 422VALIDATION_FAILED. So is one another account released — by renaming or deleting its chatbot — in the last 90 days by default; a handle your account released stays yours to take back.Min length:
3Max length:40Pattern:^[a-z0-9]+(?:-[a-z0-9]+)*$
Responses
- 200
ChatbotResourceobjectstringRequiredAlways
chatbotidintegerRequiredThe chatbot id, used in every/chatbots/{id}path and aschatbot_idelsewhere.slugstringRequiredThe public handle: the hosted agent page lives at/agent/{slug}. Unique across the platform;PUT /chatbots/{id}/handlechanges it, a rename never does.namestringRequiredDisplay name, unique within the account.descriptionstringnullableRequiredYour own description of the chatbot;nullwhen none.avatar_urlstringnullableRequiredAbsolute URL of the avatar image;nullwhen the chatbot has none.colorstringRequiredFlat header colour: a theme token or a#rrggbbhex. Used whenheader_themeisflat.primary_languagestringRequiredThe language the chatbot answers in, e.g.English.supported_languagesobjectRequiredFurther languages the chatbot is set up for;[]when none.text_directionstringRequiredLTRorRTL, derived fromprimary_language.statusstringRequiredLifecycle status. The widget and hosted page serve only anactivechatbot; a new one isdraft.Possible values
activeinactivedrafttraining_statusstringRequiredWhere training of the chatbot's knowledge stands.completedonce every source is trained;never_trainedbefore any.Possible values
never_trainedpendingtrainingupdatingneeds_retrainingcompletedfailedcache_responsesbooleanRequiredWhether a repeated question may be answered from the response cache instead of a new model call.last_training_datestringnullableRequiredWhen training last completed (ISO 8601, UTC);nullbefore the first.last_active_atstringnullableRequiredWhen the chatbot last answered a chat turn (ISO 8601, UTC);nullbefore the first.template_idintegernullableRequiredThe catalogue template the chatbot was created from;nullwhen none.response_lengthstringRequiredAnswer length preset:Short ResponseorLong Response.audiencestringRequiredWho the chatbot serves:customers(it speaks for the business) orpersonal(the owner's private assistant).customersunless set at creation.knowledge_modestringRequiredHow far answers may step outside the knowledge base:strict(knowledge only) orgeneral(general knowledge when the knowledge base has nothing).strictunless set at creation.welcome_messagestringnullableRequiredThe first message the widget and hosted page show;nullfor the default greeting.fallback_messagestringnullableRequiredThe reply sent when the chatbot cannot produce an answer;nullfor the platform default.custom_instructionsobjectRequiredYour extra instructions for every answer, one string per instruction;[]when none. The plan caps how many.enable_handoffbooleanRequiredWhether the chatbot may hand a conversation to a human.training_configobjectRequiredTraining and retrieval tuning set throughPATCH /chatbots/{id};[]when never set.gradient_stylestringRequiredHeader gradient: a theme token or a#rrggbb,#rrggbbpair. Used whenheader_themeisgradient.header_themestringRequiredHeader fill:gradient(usesgradient_style) orflat(usescolor).is_image_avatarbooleanRequiredWhether the avatar is an uploaded image (POST /chatbots/{id}/avatar).settingsobjectRequiredThe widget look-and-behaviour keys set on the chatbot (PUT /chatbots/{chatbotId}/widget). A key never set is absent.lead_captureobjectnullableRequiredLead capture: whether the widget asks visitors for contact details (enabled), when (trigger), whichfields, and whether they may skip it;nullwhen never configured.allowed_domainsobjectRequiredHostnames whose pages may load the widget;[]lets it load on any site. Managed with the/chatbots/{chatbotId}/widget/domainsoperations.created_atstringnullableRequiredWhen the chatbot was created (ISO 8601, UTC).updated_atstringnullableRequiredWhen the chatbot last changed (ISO 8601, UTC).
- 400A tenant selector header named a tenant other than the API key's own (
ACCOUNT_SELECTOR_NOT_SUPPORTED): an all-digitX-Account-Idother than the key owner's id or, whileworkspaces.context_enabledis on, anX-Workspace-Idother than the key's workspace (ws_prefix optional, case-insensitive). A header naming the key's own tenant, or a non-numericX-Account-Id, is ignored; a key cannot switch tenants, so send neither. A mutation that honoursIdempotency-Keyalso returnsINVALID_IDEMPOTENCY_KEYwhen that header is not 16–128[A-Za-z0-9_-]characters.Error codesACCOUNT_SELECTOR_NOT_SUPPORTEDINVALID_IDEMPOTENCY_KEY
- 401Missing or invalid API key.
Error codesUNAUTHENTICATED
- 403The API key is missing a required scope.
Error codesACCOUNT_SUSPENDEDINSUFFICIENT_SCOPE
- 404The resource does not exist on this account.
Error codesNOT_FOUND
- 409The request conflicts with the current resource state.
Error codesIDEMPOTENCY_IN_FLIGHT
- 422Validation failed. See
error.details.Error codesIDEMPOTENCY_KEY_REUSEDVALIDATION_FAILED
- 429Rate limited. Honour the Retry-After header before retrying.
Error codesRATE_LIMITED
- 500Unexpected server error. Retry with the same Idempotency-Key.
Error codesSERVER_ERROR
Request
curl -X PUT 'https://api.agentency.com/v1/chatbots/<CHATBOT_ID>/handle' \
-H "Authorization: Bearer <YOUR_KEY>" \
-H "Content-Type: application/json"
-d '{
"handle": "handle"
}'Response
Example 200 response
{
"object": "chatbot",
"id": 1,
"slug": "acme-orders",
"name": "Orders Assistant",
"description": "Tracks orders and deliveries.",
"avatar_url": null,
"color": "bg-indigo-500",
"primary_language": "English",
"supported_languages": [],
"text_direction": "LTR",
"status": "inactive",
"training_status": "never_trained",
"cache_responses": true,
"last_training_date": null,
"last_active_at": null,
"template_id": null,
"response_length": "Short Response",
"audience": "customers",
"knowledge_mode": "strict",
"welcome_message": "Hi! Ask me about orders, shipping or refunds.",
"fallback_message": null,
"custom_instructions": [],
"enable_handoff": false,
"training_config": [],
"gradient_style": "from-indigo-600 to-blue-600",
"header_theme": "gradient",
"is_image_avatar": false,
"settings": {
"widget_position": "bottom-left"
},
"lead_capture": null,
"allowed_domains": [],
"created_at": "2026-01-01T00:00:00+00:00",
"updated_at": "2026-01-01T00:00:00+00:00"
}Add a hosted page login
credentialed hosted page and returns it with 201 (never the password). The identifier must be unique on the chatbot, and the chatbot holds at most max_accounts logins; either refusal is 422 VALIDATION_FAILED on identifier. The login only gates the page once mode is credentialed. It emits no webhook event.- Required scope
- chatbots:write
- Idempotency
- Accepts Idempotency-Key
- Webhook events
- None
- Rate limits
Integer.id(path)Chatbot idPlaceholder in the samples:
<CHATBOT_ID>Get it from
- GET /v1/chatbots returns it as
data[].id - POST /v1/chatbots returns it as
id - GET /v1/chatbots/by_handle/{handle} returns it as
id - Webhook chatbot.created carries it as
data.object.id - In the dashboard, it is the number in a chatbot's address:
/dashboard/chatbots/{id}.
- GET /v1/chatbots returns it as
Path parameters
idintegerRequiredThe chatbot id.
Header parameters
Idempotency-KeystringOptionalMakes a retry safe. The first 2xx answer is stored for 24 h and replayed for the same key withIdempotency-Replayed: true; a retry while the first request runs is 409IDEMPOTENCY_IN_FLIGHT; the same key with a different payload is 422IDEMPOTENCY_KEY_REUSED; a malformed key is 400INVALID_IDEMPOTENCY_KEY.Min length:
16Max length:128Pattern:^[A-Za-z0-9_-]+$
Request body
/v1 store agent access account payload. Field set is pinned on this class so a
dashboard FormRequest tweak cannot silently widen the public contract.identifier_typestringRequiredWhat the visitor signs in with:username,emailorphone.Possible values
usernameemailphoneidentifierstringRequiredThe username, email address or phone number, at most 190 characters, in the formatidentifier_typenames. Unique on the chatbot.Max length:
190labelstringnullableOptionalYour own note on who this login is for, at most 120 characters.Max length:
120passwordstringRequiredThe visitor's password, 8–200 characters. Stored hashed and never returned.Min length:
8Max length:200enabledbooleanOptionalWhether the login may sign in. Defaults totrue.
Responses
- 201
AgentAccessAccountobjectstringRequiredAlways
agent_access_accountidintegerRequiredThe access account id, forDELETE /chatbots/{id}/access/accounts/{accountId}.identifier_typestringRequiredWhat the visitor signs in with: ausername, anemailor aphonenumber.Possible values
usernameemailphoneidentifierstringRequiredThe username, email or phone number the visitor signs in with.labelstringnullableRequiredYour own note on who this login is for;nullwhen none.enabledbooleanRequiredWhether this login may sign in.last_login_atstringnullableRequiredWhen the visitor last signed in with this login (ISO 8601);nullwhen never.created_atstringnullableRequiredWhen the login was created (ISO 8601).
- 400A tenant selector header named a tenant other than the API key's own (
ACCOUNT_SELECTOR_NOT_SUPPORTED): an all-digitX-Account-Idother than the key owner's id or, whileworkspaces.context_enabledis on, anX-Workspace-Idother than the key's workspace (ws_prefix optional, case-insensitive). A header naming the key's own tenant, or a non-numericX-Account-Id, is ignored; a key cannot switch tenants, so send neither. A mutation that honoursIdempotency-Keyalso returnsINVALID_IDEMPOTENCY_KEYwhen that header is not 16–128[A-Za-z0-9_-]characters.Error codesACCOUNT_SELECTOR_NOT_SUPPORTEDINVALID_IDEMPOTENCY_KEY
- 401Missing or invalid API key.
Error codesUNAUTHENTICATED
- 403The API key is missing a required scope.
Error codesACCOUNT_SUSPENDEDINSUFFICIENT_SCOPE
- 404The resource does not exist on this account.
Error codesNOT_FOUND
- 409The request conflicts with the current resource state.
Error codesIDEMPOTENCY_IN_FLIGHT
- 422Validation failed. See
error.details.Error codesIDEMPOTENCY_KEY_REUSEDVALIDATION_FAILED
- 429Rate limited. Honour the Retry-After header before retrying.
Error codesRATE_LIMITED
- 500Unexpected server error. Retry with the same Idempotency-Key.
Error codesSERVER_ERROR
Request
curl -X POST 'https://api.agentency.com/v1/chatbots/<CHATBOT_ID>/access/accounts' \
-H "Authorization: Bearer <YOUR_KEY>" \
-H "Content-Type: application/json"
-d '{
"identifier_type": "identifier_type",
"identifier": "identifier",
"label": "label",
"password": "password",
"enabled": true
}'Response
Example 201 response
{
"object": "agent_access_account",
"id": 1,
"identifier_type": "email",
"identifier": "reviewer@example.com",
"label": "QA reviewer",
"enabled": true,
"last_login_at": null,
"created_at": "2026-01-01T00:00:00+00:00"
}Remove a hosted page login
credentialed mode leaves no one able to open the page until you add another or change the mode. It emits no webhook event.- Required scope
- chatbots:write
- Idempotency
- Accepts Idempotency-Key
- Webhook events
- None
- Rate limits
Integer.id(path)Chatbot idPlaceholder in the samples:
<CHATBOT_ID>Get it from
- GET /v1/chatbots returns it as
data[].id - POST /v1/chatbots returns it as
id - GET /v1/chatbots/by_handle/{handle} returns it as
id - Webhook chatbot.created carries it as
data.object.id - In the dashboard, it is the number in a chatbot's address:
/dashboard/chatbots/{id}.
- GET /v1/chatbots returns it as
Integer.accountId(path)Access account idPlaceholder in the samples:
<ACCOUNT_ID>Get it from
- POST /v1/chatbots/{id}/access/accounts returns it as
id - GET /v1/chatbots/{id}/access returns it as
accounts[].id
- POST /v1/chatbots/{id}/access/accounts returns it as
Path parameters
idintegerRequiredThe chatbot id.accountIdintegerRequiredThe access account id.
Header parameters
Idempotency-KeystringOptionalMakes a retry safe. The first 2xx answer is stored for 24 h and replayed for the same key withIdempotency-Replayed: true; a retry while the first request runs is 409IDEMPOTENCY_IN_FLIGHT; the same key with a different payload is 422IDEMPOTENCY_KEY_REUSED; a malformed key is 400INVALID_IDEMPOTENCY_KEY.Min length:
16Max length:128Pattern:^[A-Za-z0-9_-]+$
Responses
- 200Success.
objectstringRequiredAlways
agent_access_accountidintegerRequireddeletedbooleanRequired
- 400A tenant selector header named a tenant other than the API key's own (
ACCOUNT_SELECTOR_NOT_SUPPORTED): an all-digitX-Account-Idother than the key owner's id or, whileworkspaces.context_enabledis on, anX-Workspace-Idother than the key's workspace (ws_prefix optional, case-insensitive). A header naming the key's own tenant, or a non-numericX-Account-Id, is ignored; a key cannot switch tenants, so send neither. A mutation that honoursIdempotency-Keyalso returnsINVALID_IDEMPOTENCY_KEYwhen that header is not 16–128[A-Za-z0-9_-]characters.Error codesACCOUNT_SELECTOR_NOT_SUPPORTEDINVALID_IDEMPOTENCY_KEY
- 401Missing or invalid API key.
Error codesUNAUTHENTICATED
- 403The API key is missing a required scope.
Error codesACCOUNT_SUSPENDEDINSUFFICIENT_SCOPE
- 404The resource does not exist on this account.
Error codesNOT_FOUND
- 409The request conflicts with the current resource state.
Error codesIDEMPOTENCY_IN_FLIGHT
- 422Validation failed. See
error.details.Error codesIDEMPOTENCY_KEY_REUSED
- 429Rate limited. Honour the Retry-After header before retrying.
Error codesRATE_LIMITED
- 500Unexpected server error. Retry with the same Idempotency-Key.
Error codesSERVER_ERROR
Request
curl -X DELETE 'https://api.agentency.com/v1/chatbots/<CHATBOT_ID>/access/accounts/<ACCOUNT_ID>' \
-H "Authorization: Bearer <YOUR_KEY>" \
-H "Content-Type: application/json"Response
Example 200 response
{
"object": "agent_access_account",
"id": 1,
"deleted": true
}Upload a chatbot avatar
multipart/form-data (field file), makes it the chatbot's avatar and returns the chatbot with the new avatar_url and is_image_avatar: true. The previous uploaded avatar is deleted when no other chatbot uses it.- Required scope
- chatbots:write
- Idempotency
- Accepts Idempotency-Key
- Webhook events
- chatbot.updated
- Rate limits
Integer.id(path)Chatbot idPlaceholder in the samples:
<CHATBOT_ID>Get it from
- GET /v1/chatbots returns it as
data[].id - POST /v1/chatbots returns it as
id - GET /v1/chatbots/by_handle/{handle} returns it as
id - Webhook chatbot.created carries it as
data.object.id - In the dashboard, it is the number in a chatbot's address:
/dashboard/chatbots/{id}.
- GET /v1/chatbots returns it as
Path parameters
idintegerRequiredThe chatbot id.
Header parameters
Idempotency-KeystringOptionalMakes a retry safe. The first 2xx answer is stored for 24 h and replayed for the same key withIdempotency-Replayed: true; a retry while the first request runs is 409IDEMPOTENCY_IN_FLIGHT; the same key with a different payload is 422IDEMPOTENCY_KEY_REUSED; a malformed key is 400INVALID_IDEMPOTENCY_KEY.Min length:
16Max length:128Pattern:^[A-Za-z0-9_-]+$
Request body
filestringRequiredThe image, sent asmultipart/form-data: JPEG, PNG, GIF or WebP, by default at most 5 MB and 4096 × 4096 pixels.Format:
binary
Responses
- 200
ChatbotResourceobjectstringRequiredAlways
chatbotidintegerRequiredThe chatbot id, used in every/chatbots/{id}path and aschatbot_idelsewhere.slugstringRequiredThe public handle: the hosted agent page lives at/agent/{slug}. Unique across the platform;PUT /chatbots/{id}/handlechanges it, a rename never does.namestringRequiredDisplay name, unique within the account.descriptionstringnullableRequiredYour own description of the chatbot;nullwhen none.avatar_urlstringnullableRequiredAbsolute URL of the avatar image;nullwhen the chatbot has none.colorstringRequiredFlat header colour: a theme token or a#rrggbbhex. Used whenheader_themeisflat.primary_languagestringRequiredThe language the chatbot answers in, e.g.English.supported_languagesobjectRequiredFurther languages the chatbot is set up for;[]when none.text_directionstringRequiredLTRorRTL, derived fromprimary_language.statusstringRequiredLifecycle status. The widget and hosted page serve only anactivechatbot; a new one isdraft.Possible values
activeinactivedrafttraining_statusstringRequiredWhere training of the chatbot's knowledge stands.completedonce every source is trained;never_trainedbefore any.Possible values
never_trainedpendingtrainingupdatingneeds_retrainingcompletedfailedcache_responsesbooleanRequiredWhether a repeated question may be answered from the response cache instead of a new model call.last_training_datestringnullableRequiredWhen training last completed (ISO 8601, UTC);nullbefore the first.last_active_atstringnullableRequiredWhen the chatbot last answered a chat turn (ISO 8601, UTC);nullbefore the first.template_idintegernullableRequiredThe catalogue template the chatbot was created from;nullwhen none.response_lengthstringRequiredAnswer length preset:Short ResponseorLong Response.audiencestringRequiredWho the chatbot serves:customers(it speaks for the business) orpersonal(the owner's private assistant).customersunless set at creation.knowledge_modestringRequiredHow far answers may step outside the knowledge base:strict(knowledge only) orgeneral(general knowledge when the knowledge base has nothing).strictunless set at creation.welcome_messagestringnullableRequiredThe first message the widget and hosted page show;nullfor the default greeting.fallback_messagestringnullableRequiredThe reply sent when the chatbot cannot produce an answer;nullfor the platform default.custom_instructionsobjectRequiredYour extra instructions for every answer, one string per instruction;[]when none. The plan caps how many.enable_handoffbooleanRequiredWhether the chatbot may hand a conversation to a human.training_configobjectRequiredTraining and retrieval tuning set throughPATCH /chatbots/{id};[]when never set.gradient_stylestringRequiredHeader gradient: a theme token or a#rrggbb,#rrggbbpair. Used whenheader_themeisgradient.header_themestringRequiredHeader fill:gradient(usesgradient_style) orflat(usescolor).is_image_avatarbooleanRequiredWhether the avatar is an uploaded image (POST /chatbots/{id}/avatar).settingsobjectRequiredThe widget look-and-behaviour keys set on the chatbot (PUT /chatbots/{chatbotId}/widget). A key never set is absent.lead_captureobjectnullableRequiredLead capture: whether the widget asks visitors for contact details (enabled), when (trigger), whichfields, and whether they may skip it;nullwhen never configured.allowed_domainsobjectRequiredHostnames whose pages may load the widget;[]lets it load on any site. Managed with the/chatbots/{chatbotId}/widget/domainsoperations.created_atstringnullableRequiredWhen the chatbot was created (ISO 8601, UTC).updated_atstringnullableRequiredWhen the chatbot last changed (ISO 8601, UTC).
- 400A tenant selector header named a tenant other than the API key's own (
ACCOUNT_SELECTOR_NOT_SUPPORTED): an all-digitX-Account-Idother than the key owner's id or, whileworkspaces.context_enabledis on, anX-Workspace-Idother than the key's workspace (ws_prefix optional, case-insensitive). A header naming the key's own tenant, or a non-numericX-Account-Id, is ignored; a key cannot switch tenants, so send neither. A mutation that honoursIdempotency-Keyalso returnsINVALID_IDEMPOTENCY_KEYwhen that header is not 16–128[A-Za-z0-9_-]characters.Error codesACCOUNT_SELECTOR_NOT_SUPPORTEDINVALID_IDEMPOTENCY_KEY
- 401Missing or invalid API key.
Error codesUNAUTHENTICATED
- 403The API key is missing a required scope.
Error codesACCOUNT_SUSPENDEDINSUFFICIENT_SCOPE
- 404The resource does not exist on this account.
Error codesNOT_FOUND
- 409The request conflicts with the current resource state.
Error codesIDEMPOTENCY_IN_FLIGHT
- 422Validation failed. See
error.details.Error codesIDEMPOTENCY_KEY_REUSEDVALIDATION_FAILED
- 429Rate limited. Honour the Retry-After header before retrying.
Error codesRATE_LIMITED
- 500Unexpected server error. Retry with the same Idempotency-Key.
Error codesSERVER_ERROR
Request
curl -X POST 'https://api.agentency.com/v1/chatbots/<CHATBOT_ID>/avatar' \
-H "Authorization: Bearer <YOUR_KEY>" \
-H "Content-Type: application/json"
-d '{
"file": "file"
}'Response
Example 200 response
{
"object": "chatbot",
"id": 1,
"slug": "acme-orders",
"name": "Orders Assistant",
"description": "Tracks orders and deliveries.",
"avatar_url": "https://api.agentency.test/uploads/avatars/u1/3f/2a/9c/3f2a9c4e-6b1d-4e8a-9f27-5c0d8e1b7a46.png",
"color": "bg-indigo-500",
"primary_language": "English",
"supported_languages": [],
"text_direction": "LTR",
"status": "inactive",
"training_status": "never_trained",
"cache_responses": true,
"last_training_date": null,
"last_active_at": null,
"template_id": null,
"response_length": "Short Response",
"audience": "customers",
"knowledge_mode": "strict",
"welcome_message": "Hi! Ask me about orders, shipping or refunds.",
"fallback_message": null,
"custom_instructions": [],
"enable_handoff": false,
"training_config": [],
"gradient_style": "from-indigo-600 to-blue-600",
"header_theme": "gradient",
"is_image_avatar": true,
"settings": {
"widget_position": "bottom-left"
},
"lead_capture": null,
"allowed_domains": [],
"created_at": "2026-01-01T00:00:00+00:00",
"updated_at": "2026-01-01T00:00:00+00:00"
}Remove a chatbot avatar
avatar_url: null, is_image_avatar: false) so the widget shows its default, and returns the chatbot. The uploaded image is deleted when no other chatbot uses it.- Required scope
- chatbots:write
- Idempotency
- Accepts Idempotency-Key
- Webhook events
- chatbot.updated
- Rate limits
Integer.id(path)Chatbot idPlaceholder in the samples:
<CHATBOT_ID>Get it from
- GET /v1/chatbots returns it as
data[].id - POST /v1/chatbots returns it as
id - GET /v1/chatbots/by_handle/{handle} returns it as
id - Webhook chatbot.created carries it as
data.object.id - In the dashboard, it is the number in a chatbot's address:
/dashboard/chatbots/{id}.
- GET /v1/chatbots returns it as
Path parameters
idintegerRequiredThe chatbot id.
Header parameters
Idempotency-KeystringOptionalMakes a retry safe. The first 2xx answer is stored for 24 h and replayed for the same key withIdempotency-Replayed: true; a retry while the first request runs is 409IDEMPOTENCY_IN_FLIGHT; the same key with a different payload is 422IDEMPOTENCY_KEY_REUSED; a malformed key is 400INVALID_IDEMPOTENCY_KEY.Min length:
16Max length:128Pattern:^[A-Za-z0-9_-]+$
Responses
- 200
ChatbotResourceobjectstringRequiredAlways
chatbotidintegerRequiredThe chatbot id, used in every/chatbots/{id}path and aschatbot_idelsewhere.slugstringRequiredThe public handle: the hosted agent page lives at/agent/{slug}. Unique across the platform;PUT /chatbots/{id}/handlechanges it, a rename never does.namestringRequiredDisplay name, unique within the account.descriptionstringnullableRequiredYour own description of the chatbot;nullwhen none.avatar_urlstringnullableRequiredAbsolute URL of the avatar image;nullwhen the chatbot has none.colorstringRequiredFlat header colour: a theme token or a#rrggbbhex. Used whenheader_themeisflat.primary_languagestringRequiredThe language the chatbot answers in, e.g.English.supported_languagesobjectRequiredFurther languages the chatbot is set up for;[]when none.text_directionstringRequiredLTRorRTL, derived fromprimary_language.statusstringRequiredLifecycle status. The widget and hosted page serve only anactivechatbot; a new one isdraft.Possible values
activeinactivedrafttraining_statusstringRequiredWhere training of the chatbot's knowledge stands.completedonce every source is trained;never_trainedbefore any.Possible values
never_trainedpendingtrainingupdatingneeds_retrainingcompletedfailedcache_responsesbooleanRequiredWhether a repeated question may be answered from the response cache instead of a new model call.last_training_datestringnullableRequiredWhen training last completed (ISO 8601, UTC);nullbefore the first.last_active_atstringnullableRequiredWhen the chatbot last answered a chat turn (ISO 8601, UTC);nullbefore the first.template_idintegernullableRequiredThe catalogue template the chatbot was created from;nullwhen none.response_lengthstringRequiredAnswer length preset:Short ResponseorLong Response.audiencestringRequiredWho the chatbot serves:customers(it speaks for the business) orpersonal(the owner's private assistant).customersunless set at creation.knowledge_modestringRequiredHow far answers may step outside the knowledge base:strict(knowledge only) orgeneral(general knowledge when the knowledge base has nothing).strictunless set at creation.welcome_messagestringnullableRequiredThe first message the widget and hosted page show;nullfor the default greeting.fallback_messagestringnullableRequiredThe reply sent when the chatbot cannot produce an answer;nullfor the platform default.custom_instructionsobjectRequiredYour extra instructions for every answer, one string per instruction;[]when none. The plan caps how many.enable_handoffbooleanRequiredWhether the chatbot may hand a conversation to a human.training_configobjectRequiredTraining and retrieval tuning set throughPATCH /chatbots/{id};[]when never set.gradient_stylestringRequiredHeader gradient: a theme token or a#rrggbb,#rrggbbpair. Used whenheader_themeisgradient.header_themestringRequiredHeader fill:gradient(usesgradient_style) orflat(usescolor).is_image_avatarbooleanRequiredWhether the avatar is an uploaded image (POST /chatbots/{id}/avatar).settingsobjectRequiredThe widget look-and-behaviour keys set on the chatbot (PUT /chatbots/{chatbotId}/widget). A key never set is absent.lead_captureobjectnullableRequiredLead capture: whether the widget asks visitors for contact details (enabled), when (trigger), whichfields, and whether they may skip it;nullwhen never configured.allowed_domainsobjectRequiredHostnames whose pages may load the widget;[]lets it load on any site. Managed with the/chatbots/{chatbotId}/widget/domainsoperations.created_atstringnullableRequiredWhen the chatbot was created (ISO 8601, UTC).updated_atstringnullableRequiredWhen the chatbot last changed (ISO 8601, UTC).
- 400A tenant selector header named a tenant other than the API key's own (
ACCOUNT_SELECTOR_NOT_SUPPORTED): an all-digitX-Account-Idother than the key owner's id or, whileworkspaces.context_enabledis on, anX-Workspace-Idother than the key's workspace (ws_prefix optional, case-insensitive). A header naming the key's own tenant, or a non-numericX-Account-Id, is ignored; a key cannot switch tenants, so send neither. A mutation that honoursIdempotency-Keyalso returnsINVALID_IDEMPOTENCY_KEYwhen that header is not 16–128[A-Za-z0-9_-]characters.Error codesACCOUNT_SELECTOR_NOT_SUPPORTEDINVALID_IDEMPOTENCY_KEY
- 401Missing or invalid API key.
Error codesUNAUTHENTICATED
- 403The API key is missing a required scope.
Error codesACCOUNT_SUSPENDEDINSUFFICIENT_SCOPE
- 404The resource does not exist on this account.
Error codesNOT_FOUND
- 409The request conflicts with the current resource state.
Error codesIDEMPOTENCY_IN_FLIGHT
- 422Validation failed. See
error.details.Error codesIDEMPOTENCY_KEY_REUSED
- 429Rate limited. Honour the Retry-After header before retrying.
Error codesRATE_LIMITED
- 500Unexpected server error. Retry with the same Idempotency-Key.
Error codesSERVER_ERROR
Request
curl -X DELETE 'https://api.agentency.com/v1/chatbots/<CHATBOT_ID>/avatar' \
-H "Authorization: Bearer <YOUR_KEY>" \
-H "Content-Type: application/json"Response
Example 200 response
{
"object": "chatbot",
"id": 1,
"slug": "acme-orders",
"name": "Orders Assistant",
"description": "Tracks orders and deliveries.",
"avatar_url": null,
"color": "bg-indigo-500",
"primary_language": "English",
"supported_languages": [],
"text_direction": "LTR",
"status": "inactive",
"training_status": "never_trained",
"cache_responses": true,
"last_training_date": null,
"last_active_at": null,
"template_id": null,
"response_length": "Short Response",
"audience": "customers",
"knowledge_mode": "strict",
"welcome_message": "Hi! Ask me about orders, shipping or refunds.",
"fallback_message": null,
"custom_instructions": [],
"enable_handoff": false,
"training_config": [],
"gradient_style": "from-indigo-600 to-blue-600",
"header_theme": "gradient",
"is_image_avatar": false,
"settings": {
"widget_position": "bottom-left"
},
"lead_capture": null,
"allowed_domains": [],
"created_at": "2026-01-01T00:00:00+00:00",
"updated_at": "2026-01-01T00:00:00+00:00"
}