Create a conversation
Opens a conversation for a chat thread in your tool. Linking a `customer` (by phone or email) gives the agent per-customer memory and workflow context; `external_id` maps the conversation to your thread id and enables the shortcut `POST /v1/messages`. Returns `409 external_id_taken` (with `error.existing_id`) when a live conversation already exists under the same `external_id` — post messages to that one, or end it first. An ended conversation frees its `external_id` for reuse.
Authorization
AuthorizationRequiredBearer <token>Send your API key in the Authorization header on every request:
Authorization: Bearer sk_live_.... Keys are created in the admin UI under
Settings → API Keys and are project-scoped.
In: header
Request Body
application/jsonRequiredexternal_idstringYour chat tool's thread id. Optional but recommended — it enables POST /v1/messages and idempotent thread mapping.
255customerobjectLink the conversation to a customer record (created if new). Gives the agent per-customer memory and workflow context.
metadataobjectHeader Parameters
Idempotency-KeystringMake POST/PATCH requests safe to retry. Same key + same body within 24 hours replays the original response. See Idempotency.
255Response Body
Conversation created.
TypeScript Definitions
Use the response body type in TypeScript.
idRequiredstringConversation identifier prefixed with conv_.
objectRequiredstring"conversation"statusRequiredstringactive — the agent replies to posted messages.
handed_off — the agent invoked a human handoff; posted messages
return 409 conversation_handed_off until the conversation is ended.
ended — closed (explicitly, by the agent, or after 30 minutes idle).
"active" | "ended" | "handed_off"external_idstring | null | nullYour chat tool's own thread identifier (max 255 characters). Unique per project among live conversations; reusable after the previous conversation under it has ended.
customer_idstring | null | nullThe linked customer (cust_…), when the conversation was created with a customer block.
metadataobjectFree-form key/value bag supplied at creation, echoed back verbatim.
created_atRequiredstring"date-time"last_message_atstring | null | null"date-time"ended_atstring | null | null"date-time"Validation failed.
TypeScript Definitions
Use the response body type in TypeScript.
errorRequiredobjectResource conflict.
TypeScript Definitions
Use the response body type in TypeScript.
errorRequiredobjectcurl -X POST "https://api.meetdolores.ai/v1/conversations" \
-H "Idempotency-Key: string" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"external_id": "intercom-thread-829311",
"customer": {
"phone": "+14155551234"
},
"metadata": {
"widget": "pricing-page"
}
}'const body = JSON.stringify({
"external_id": "intercom-thread-829311",
"customer": {
"phone": "+14155551234"
},
"metadata": {
"widget": "pricing-page"
}
})
fetch("https://api.meetdolores.ai/v1/conversations", {
headers: {
"Idempotency-Key": "string",
"Authorization": "Bearer <token>"
},
body
})package main
import (
"fmt"
"net/http"
"io/ioutil"
"strings"
)
func main() {
url := "https://api.meetdolores.ai/v1/conversations"
body := strings.NewReader(`{
"external_id": "intercom-thread-829311",
"customer": {
"phone": "+14155551234"
},
"metadata": {
"widget": "pricing-page"
}
}`)
req, _ := http.NewRequest("POST", url, body)
req.Header.Add("Idempotency-Key", "string")
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
fmt.Println(res)
fmt.Println(string(body))
}import requests
url = "https://api.meetdolores.ai/v1/conversations"
body = {
"external_id": "intercom-thread-829311",
"customer": {
"phone": "+14155551234"
},
"metadata": {
"widget": "pricing-page"
}
}
response = requests.request("POST", url, json = body, headers = {
"Idempotency-Key": "string",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
})
print(response.text)require 'net/http'
require 'json'
require 'uri'
uri = URI('https://api.meetdolores.ai/v1/conversations')
req = Net::HTTP::Post.new(uri, {
'Authorization' => "Bearer #{ENV['DOLORES_API_KEY']}",
'Content-Type' => 'application/json',
})
req.body = {
external_id: "intercom-thread-829311",
customer: {
phone: "+14155551234"
},
metadata: {
widget: "pricing-page"
}
}.to_json
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
puts res.body<?php
$ch = curl_init('https://api.meetdolores.ai/v1/conversations');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('DOLORES_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'external_id' => 'intercom-thread-829311',
'customer' => [
'phone' => '+14155551234'
],
'metadata' => [
'widget' => 'pricing-page'
]
]),
]);
echo curl_exec($ch);{
"id": "conv_01J8ZKW2M4NBCDEFGHJKMNPQRS",
"object": "conversation",
"status": "active",
"external_id": "intercom-thread-829311",
"customer_id": "string",
"metadata": {},
"created_at": "2019-08-24T14:15:22Z",
"last_message_at": "2019-08-24T14:15:22Z",
"ended_at": "2019-08-24T14:15:22Z"
}{
"error": {
"type": "invalid_request_error",
"code": "phone_invalid_format",
"message": "Phone must be in E.164 format (e.g. +15551234567).",
"param": "phone",
"request_id": "req_01HXY7P3K9ABCDEFGHJKMNPQRS"
}
}{
"error": {
"type": "invalid_request_error",
"code": "phone_invalid_format",
"message": "string",
"param": "string",
"request_id": "string"
}
}