BrightshoalDocsOpen console
MenuQuickstart

Get started

Quickstart

Create an API key, create an assistant, and get its first reply over the same chat API the website widget uses. Seven requests, about ten minutes.

You will need a console account with the owner role (only owners create API keys) and either a terminal with curl or Node 18 or later. Nothing here needs a phone number: once chat works, placing a call is one more request.

Create an API key

In the console, open Settings > API keys and create a key. A key is either org-wide or pinned to one project, and either full access or read-only. For this guide, create a full-access key.

The key starts with vak_ and is shown once. Keep it on your server, never in a browser or an app.

Terminal
export MLF_API_KEY="vak_..."

Find your project

Assistants, numbers and keys live in a project. List yours and keep the id:

curl https://api.myleadsfactory.tech/api/projects \
  -H "Authorization: Bearer $MLF_API_KEY"
Response
{
  "data": [
    { "id": "proj_2f9c41d0a8b34e6f9d1c7a5b3e8f0a12", "name": "Main", "org_id": "org_..." }
  ]
}
Terminal
export MLF_PROJECT_ID="proj_2f9c41d0a8b34e6f9d1c7a5b3e8f0a12"

Create an assistant

An assistant is one agent: what it says, which models it runs on, and where it answers. This one answers web chat and records a lead when a visitor shares their details.

curl -X POST https://api.myleadsfactory.tech/api/assistants \
  -H "Authorization: Bearer $MLF_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Front desk",
    "project_id": "'"$MLF_PROJECT_ID"'",
    "config": {
      "agent": {
        "instructions": "You answer enquiries for Acme Travel. Be brief and friendly. Ask for a name and an email before you end."
      },
      "session": {
        "llm": { "provider": "openai", "model": "gpt-4o-mini" },
        "stt": { "provider": "deepgram", "model": "nova-3" },
        "tts": { "provider": "elevenlabs", "model": "eleven_flash_v2_5" }
      },
      "channels": { "web_chat": { "enabled": true, "lead_capture": { "enabled": true } } }
    }
  }'
Response 201
{
  "data": {
    "id": "asst_7d2e9b14c6a04f3e8b5d1a9c0e7f6b23",
    "name": "Front desk",
    "project_id": "proj_2f9c41d0a8b34e6f9d1c7a5b3e8f0a12",
    "version": 1,
    "config": { "...": "as sent" },
    "created_at": "2026-10-28T09:30:00.000Z"
  }
}

config.session is the voice pipeline (speech to text, the model, text to speech) used on calls. Web chat answers with channels.web_chat.llm when you set it, and openai/gpt-6.1-sol (medium reasoning) when you don't. How it fits together explains every part of the config.

Get a publishable key

Chat runs in your visitors' browsers, where a secret key must never go. A publishable key (pk_live_...) can only start chats with one assistant, from the origins you allow, so it is safe in page source.

Terminal
curl -X POST https://api.myleadsfactory.tech/api/publishable-keys \
  -H "Authorization: Bearer $MLF_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "assistant_id": "asst_7d2e9b14c6a04f3e8b5d1a9c0e7f6b23" }'
Response 201
{ "data": { "id": "wkey_...", "key": "pk_live_4b1f0c9e2a7d4e6b8c3f5a1d9e0b7c62", "assistant_id": "asst_..." } }

Say hello

Start a conversation with the publishable key. It returns a conversation token (ct_...) that authorises everything that conversation does next.

Terminal
curl -X POST https://api.myleadsfactory.tech/public/v1/conversations \
  -H "Content-Type: application/json" \
  -d '{ "widget_key": "pk_live_4b1f0c9e2a7d4e6b8c3f5a1d9e0b7c62" }'
Response 201
{
  "data": {
    "conversation_id": "conv_0c8e5f2a9b7d4c1e86f3a0d2b4c6e8f1",
    "token": "ct_...",
    "status": "open",
    "messages": []
  }
}

Send a message. The reply streams back as server-sent events: message.delta carries text as it is written and message.completed closes the turn. -N tells curl to print it as it arrives.

Terminal
curl -N -X POST https://api.myleadsfactory.tech/public/v1/conversations/conv_0c8e5f2a9b7d4c1e86f3a0d2b4c6e8f1/messages \
  -H "Authorization: Bearer ct_..." \
  -H "Content-Type: application/json" \
  -d '{ "content": "Hi, can I book a trip to Lisbon in May?" }'
Stream
event: message.accepted
data: {}

event: message.delta
data: {"text":"Lisbon in May is lovely. "}

event: message.delta
data: {"text":"Who am I speaking with?"}

event: message.completed
data: {"message":{"id":"msg_...","role":"assistant","content":"Lisbon in May is lovely. Who am I speaking with?","seq":2},"conversation":{"status":"open","taken_over":false,"lead_id":null}}

Read it back

Everything the assistant hears is yours to read with the secret key: the transcript, what it cost, and, once the visitor has shared a name and a way to reach them, the lead. Tell it your name and email in a second message, then list conversations:

Terminal
curl "https://api.myleadsfactory.tech/api/conversations?limit=1" \
  -H "Authorization: Bearer $MLF_API_KEY"

Where to go next

Stuck on quickstart?