WhatsAble
API v1AI bots

Create an AI bot

posthttps://api.whatsable.app/v1/ai-bots
Build a request to copy

This page never sends a request. Fill in the fields, then copy the request and run it from your server.

Request
curl -X POST 'https://api.whatsable.app/v1/ai-bots' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "Sales",
  "mission": "Answer questions about our shoes and help customers order.",
  "tone": "Warm and brief.",
  "instructions": "Answer in the customer'\''s language. Never promise a delivery date.",
  "time_zone": "America/Argentina/Buenos_Aires",
  "proactive": {
    "enabled": true,
    "first_delay_minutes": 120,
    "window_minutes": 1440
  }
}'

Creates an AI bot. The bot starts as a draft, which answers no one, unless you set status. It answers on a number only after PUT /v1/numbers/{id}/ai-bot assigns it.

Authorization

bearerAuth
headerAuthorizationBearer <nfy_live_<32 characters>>

An API key from Settings > API keys, sent as Authorization: Bearer <key>.

Header Parameters

Idempotency-Key?string

Any string up to 255 characters. A repeat with the same key and body answers the stored response; with another body, 409 idempotency_key_reused.

Lengthlength <= 255

Request Body

application/json
  1. body

A bot to create, a draft unless status says otherwise. Every field left out takes the dashboard editor's default, and the rules between fields are checked against what the bot will hold.

name*string

Shown in the dashboard. Unique in the organization, ignoring case and accents.

Length1 <= length <= 60
mission*string

What the bot is for. Part of its prompt on every turn.

Lengthlength <= 20000
tone*string

How it speaks. Part of its prompt on every turn.

Lengthlength <= 300
instructions*string

The organization's own instructions to the bot. Part of its prompt on every turn.

Lengthlength <= 80000
knowledge?|

Facts the bot may state, pasted as text. Uploaded documents are knowledge files instead.

status?string

draft (answers no one), active or archived. Only an archived bot can be deleted.

Value in"draft""active""archived"
time_zone?string

The IANA time zone the bot tells time in, and that quiet hours are read in.

Length1 <= length <= 64
debounce_seconds?integer

How long the bot waits after a customer's message for more before it answers.

Range0 <= value <= 300
reply_message_mode?string

single: one WhatsApp message per reply. multiple: as many as the bot chooses.

Value in"single""multiple"
handoff_keywords?array<>

Words in a customer's message that hand the conversation to a person.

Itemsitems <= 25
handoff_instructions?|

When the bot should hand the conversation to a person. Read by the bot, never sent to the customer.

notify_on_handoff?boolean

Stored for a team notification on handoff, which is not sent yet.

resume_policy?string

When the bot answers again after a person took over: never, new_session (the customer writes after the window closed) or timer (after resume_after_seconds).

Value in"never""new_session""timer"
resume_after_seconds?|

With resume_policy: "timer", how long after a person took over the bot answers again. Required for timer.

label_permissions?

Which labels the bot may add to or remove from a contact. Fields left out are kept.

proactive?

Follow-ups the bot sends on its own when a customer goes quiet. Fields left out are kept.

Response Body

The bot.

application/json
  1. response

An AI bot: its prompt, its handoff rules, the labels it may use and its follow-ups. Organization-wide: it can answer on any number.

object*string
id*string
Length1 <= length <= 64
name*string

Shown in the dashboard. Unique in the organization, ignoring case and accents.

mission*string

What the bot is for. Part of its prompt on every turn.

tone*string

How it speaks. Part of its prompt on every turn.

instructions*string

The organization's own instructions to the bot. Part of its prompt on every turn.

knowledge*|

Facts the bot may state, pasted as text. Uploaded documents are knowledge files instead.

status*string

draft (answers no one), active or archived. Only an archived bot can be deleted.

Value in"draft""active""archived"
time_zone*string

The IANA time zone the bot tells time in, and that quiet hours are read in.

debounce_seconds*integer

How long the bot waits after a customer's message for more before it answers.

Range-9007199254740991 <= value <= 9007199254740991
reply_message_mode*string

single: one WhatsApp message per reply. multiple: as many as the bot chooses.

Value in"single""multiple"
handoff_keywords*array<string>

Words in a customer's message that hand the conversation to a person.

handoff_instructions*|

When the bot should hand the conversation to a person. Read by the bot, never sent to the customer.

notify_on_handoff*boolean

Stored for a team notification on handoff, which is not sent yet.

resume_policy*string

When the bot answers again after a person took over: never, new_session (the customer writes after the window closed) or timer (after resume_after_seconds).

Value in"never""new_session""timer"
resume_after_seconds*|

With resume_policy: "timer", how long after a person took over the bot answers again. Required for timer.

label_permissions*

Which labels the bot may add to or remove from a contact.

proactive*

Follow-ups the bot sends on its own when a customer goes quiet.

number_ids*array<>

The numbers this key may use that answer with this bot by default.

created_at*string
Formatdate-time
updated_at*string

When its configuration last changed. The ETag header carries the same version.

Formatdate-time
Example Request
curl -X POST 'https://api.whatsable.app/v1/ai-bots' \  -H 'Content-Type: application/json' \  -d '{  "name": "Sales",  "mission": "Answer questions about our shoes and help customers order.",  "tone": "Warm and brief.",  "instructions": "Answer in the customer'\''s language. Never promise a delivery date.",  "time_zone": "America/Argentina/Buenos_Aires",  "proactive": {    "enabled": true,    "first_delay_minutes": 120,    "window_minutes": 1440  }}'
Example Response
{  "object": "ai_bot",  "id": "cm2v8b1a00001qz8h3j4k5l6m",  "name": "Sales",  "mission": "Answer questions about our shoes and help customers order.",  "tone": "Warm and brief.",  "instructions": "Answer in the customer's language. Never promise a delivery date.",  "knowledge": "We ship to Argentina and Uruguay. Returns within 30 days.",  "status": "active",  "time_zone": "America/Argentina/Buenos_Aires",  "debounce_seconds": 5,  "reply_message_mode": "single",  "handoff_keywords": [    "human",    "agent"  ],  "handoff_instructions": "Hand over when the customer asks for a refund.",  "notify_on_handoff": true,  "resume_policy": "timer",  "resume_after_seconds": 3600,  "label_permissions": {    "add_enabled": true,    "remove_enabled": false,    "add_max_per_turn": null,    "remove_max_per_turn": null,    "instructions": "Add \"Hot lead\" when the customer asks for a price.",    "grant_mode": "listed",    "allowed_label_ids": [      "cm2v8l1a00001qz8h2b3c4d5e"    ]  },  "proactive": {    "enabled": true,    "instructions": "Remind them of the item they asked about.",    "first_delay_minutes": 240,    "window_minutes": 7200,    "max_follow_ups": 3,    "cooldown_minutes": 0,    "distribution": "front_loaded",    "quiet_start_hour": 22,    "quiet_end_hour": 8,    "quiet_days": [      0    ],    "after_broadcast": false,    "after_operator_reply": true,    "template_authoring": false,    "template_cap_per_week": 2  },  "number_ids": [    "cm2v8a1b20002qz8h9i0j1k2l"  ],  "created_at": "2026-09-01T12:00:00Z",  "updated_at": "2026-10-20T19:51:21Z"}