curl --request POST \
--url https://api.devic.ai/v1/assistants/{identifier}/messages \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"message": "What solar panels do you recommend?",
"chatUid": "550e8400-e29b-41d4-a716-446655440000",
"userName": "John Doe",
"tags": [
"support",
"onboarding"
],
"files": [
{
"name": "invoice.pdf",
"donwloadUrl": "https://files.devic.ai/uploads/invoice.pdf",
"fileType": "DOCUMENT"
}
],
"images": [
{
"imageUrl": "https://files.devic.ai/uploads/roof.jpg"
}
],
"metadata": {
"promptTemplateParams": {
"companyName": "Acme Corp"
},
"source": "web-widget"
},
"tenantId": "tenant_12345",
"subtenantId": "user_67890",
"previousConversation": [
{
"message": "Hello",
"role": "user"
},
{
"message": "Hi there!",
"role": "assistant"
}
],
"enabledTools": [
"get_weather",
"calculator"
],
"disabledIntegrations": [
"gmail"
],
"provider": "open-ai",
"model": "gpt-4.1",
"tools": [
{
"type": "function",
"function": {
"name": "get_user_location",
"description": "Get the current user location",
"parameters": {
"type": "object",
"properties": {},
"required": [
"<string>"
]
}
}
}
],
"transcriptId": "550e8400-e29b-41d4-a716-446655440000"
}
'import requests
url = "https://api.devic.ai/v1/assistants/{identifier}/messages"
payload = {
"message": "What solar panels do you recommend?",
"chatUid": "550e8400-e29b-41d4-a716-446655440000",
"userName": "John Doe",
"tags": ["support", "onboarding"],
"files": [
{
"name": "invoice.pdf",
"donwloadUrl": "https://files.devic.ai/uploads/invoice.pdf",
"fileType": "DOCUMENT"
}
],
"images": [{ "imageUrl": "https://files.devic.ai/uploads/roof.jpg" }],
"metadata": {
"promptTemplateParams": { "companyName": "Acme Corp" },
"source": "web-widget"
},
"tenantId": "tenant_12345",
"subtenantId": "user_67890",
"previousConversation": [
{
"message": "Hello",
"role": "user"
},
{
"message": "Hi there!",
"role": "assistant"
}
],
"enabledTools": ["get_weather", "calculator"],
"disabledIntegrations": ["gmail"],
"provider": "open-ai",
"model": "gpt-4.1",
"tools": [
{
"type": "function",
"function": {
"name": "get_user_location",
"description": "Get the current user location",
"parameters": {
"type": "object",
"properties": {},
"required": ["<string>"]
}
}
}
],
"transcriptId": "550e8400-e29b-41d4-a716-446655440000"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
message: 'What solar panels do you recommend?',
chatUid: '550e8400-e29b-41d4-a716-446655440000',
userName: 'John Doe',
tags: ['support', 'onboarding'],
files: [
{
name: 'invoice.pdf',
donwloadUrl: 'https://files.devic.ai/uploads/invoice.pdf',
fileType: 'DOCUMENT'
}
],
images: [{imageUrl: 'https://files.devic.ai/uploads/roof.jpg'}],
metadata: {promptTemplateParams: {companyName: 'Acme Corp'}, source: 'web-widget'},
tenantId: 'tenant_12345',
subtenantId: 'user_67890',
previousConversation: [{message: 'Hello', role: 'user'}, {message: 'Hi there!', role: 'assistant'}],
enabledTools: ['get_weather', 'calculator'],
disabledIntegrations: ['gmail'],
provider: 'open-ai',
model: 'gpt-4.1',
tools: [
{
type: 'function',
function: {
name: 'get_user_location',
description: 'Get the current user location',
parameters: {type: 'object', properties: {}, required: ['<string>']}
}
}
],
transcriptId: '550e8400-e29b-41d4-a716-446655440000'
})
};
fetch('https://api.devic.ai/v1/assistants/{identifier}/messages', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.devic.ai/v1/assistants/{identifier}/messages",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'message' => 'What solar panels do you recommend?',
'chatUid' => '550e8400-e29b-41d4-a716-446655440000',
'userName' => 'John Doe',
'tags' => [
'support',
'onboarding'
],
'files' => [
[
'name' => 'invoice.pdf',
'donwloadUrl' => 'https://files.devic.ai/uploads/invoice.pdf',
'fileType' => 'DOCUMENT'
]
],
'images' => [
[
'imageUrl' => 'https://files.devic.ai/uploads/roof.jpg'
]
],
'metadata' => [
'promptTemplateParams' => [
'companyName' => 'Acme Corp'
],
'source' => 'web-widget'
],
'tenantId' => 'tenant_12345',
'subtenantId' => 'user_67890',
'previousConversation' => [
[
'message' => 'Hello',
'role' => 'user'
],
[
'message' => 'Hi there!',
'role' => 'assistant'
]
],
'enabledTools' => [
'get_weather',
'calculator'
],
'disabledIntegrations' => [
'gmail'
],
'provider' => 'open-ai',
'model' => 'gpt-4.1',
'tools' => [
[
'type' => 'function',
'function' => [
'name' => 'get_user_location',
'description' => 'Get the current user location',
'parameters' => [
'type' => 'object',
'properties' => [
],
'required' => [
'<string>'
]
]
]
]
],
'transcriptId' => '550e8400-e29b-41d4-a716-446655440000'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.devic.ai/v1/assistants/{identifier}/messages"
payload := strings.NewReader("{\n \"message\": \"What solar panels do you recommend?\",\n \"chatUid\": \"550e8400-e29b-41d4-a716-446655440000\",\n \"userName\": \"John Doe\",\n \"tags\": [\n \"support\",\n \"onboarding\"\n ],\n \"files\": [\n {\n \"name\": \"invoice.pdf\",\n \"donwloadUrl\": \"https://files.devic.ai/uploads/invoice.pdf\",\n \"fileType\": \"DOCUMENT\"\n }\n ],\n \"images\": [\n {\n \"imageUrl\": \"https://files.devic.ai/uploads/roof.jpg\"\n }\n ],\n \"metadata\": {\n \"promptTemplateParams\": {\n \"companyName\": \"Acme Corp\"\n },\n \"source\": \"web-widget\"\n },\n \"tenantId\": \"tenant_12345\",\n \"subtenantId\": \"user_67890\",\n \"previousConversation\": [\n {\n \"message\": \"Hello\",\n \"role\": \"user\"\n },\n {\n \"message\": \"Hi there!\",\n \"role\": \"assistant\"\n }\n ],\n \"enabledTools\": [\n \"get_weather\",\n \"calculator\"\n ],\n \"disabledIntegrations\": [\n \"gmail\"\n ],\n \"provider\": \"open-ai\",\n \"model\": \"gpt-4.1\",\n \"tools\": [\n {\n \"type\": \"function\",\n \"function\": {\n \"name\": \"get_user_location\",\n \"description\": \"Get the current user location\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {},\n \"required\": [\n \"<string>\"\n ]\n }\n }\n }\n ],\n \"transcriptId\": \"550e8400-e29b-41d4-a716-446655440000\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.devic.ai/v1/assistants/{identifier}/messages")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"message\": \"What solar panels do you recommend?\",\n \"chatUid\": \"550e8400-e29b-41d4-a716-446655440000\",\n \"userName\": \"John Doe\",\n \"tags\": [\n \"support\",\n \"onboarding\"\n ],\n \"files\": [\n {\n \"name\": \"invoice.pdf\",\n \"donwloadUrl\": \"https://files.devic.ai/uploads/invoice.pdf\",\n \"fileType\": \"DOCUMENT\"\n }\n ],\n \"images\": [\n {\n \"imageUrl\": \"https://files.devic.ai/uploads/roof.jpg\"\n }\n ],\n \"metadata\": {\n \"promptTemplateParams\": {\n \"companyName\": \"Acme Corp\"\n },\n \"source\": \"web-widget\"\n },\n \"tenantId\": \"tenant_12345\",\n \"subtenantId\": \"user_67890\",\n \"previousConversation\": [\n {\n \"message\": \"Hello\",\n \"role\": \"user\"\n },\n {\n \"message\": \"Hi there!\",\n \"role\": \"assistant\"\n }\n ],\n \"enabledTools\": [\n \"get_weather\",\n \"calculator\"\n ],\n \"disabledIntegrations\": [\n \"gmail\"\n ],\n \"provider\": \"open-ai\",\n \"model\": \"gpt-4.1\",\n \"tools\": [\n {\n \"type\": \"function\",\n \"function\": {\n \"name\": \"get_user_location\",\n \"description\": \"Get the current user location\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {},\n \"required\": [\n \"<string>\"\n ]\n }\n }\n }\n ],\n \"transcriptId\": \"550e8400-e29b-41d4-a716-446655440000\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.devic.ai/v1/assistants/{identifier}/messages")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"message\": \"What solar panels do you recommend?\",\n \"chatUid\": \"550e8400-e29b-41d4-a716-446655440000\",\n \"userName\": \"John Doe\",\n \"tags\": [\n \"support\",\n \"onboarding\"\n ],\n \"files\": [\n {\n \"name\": \"invoice.pdf\",\n \"donwloadUrl\": \"https://files.devic.ai/uploads/invoice.pdf\",\n \"fileType\": \"DOCUMENT\"\n }\n ],\n \"images\": [\n {\n \"imageUrl\": \"https://files.devic.ai/uploads/roof.jpg\"\n }\n ],\n \"metadata\": {\n \"promptTemplateParams\": {\n \"companyName\": \"Acme Corp\"\n },\n \"source\": \"web-widget\"\n },\n \"tenantId\": \"tenant_12345\",\n \"subtenantId\": \"user_67890\",\n \"previousConversation\": [\n {\n \"message\": \"Hello\",\n \"role\": \"user\"\n },\n {\n \"message\": \"Hi there!\",\n \"role\": \"assistant\"\n }\n ],\n \"enabledTools\": [\n \"get_weather\",\n \"calculator\"\n ],\n \"disabledIntegrations\": [\n \"gmail\"\n ],\n \"provider\": \"open-ai\",\n \"model\": \"gpt-4.1\",\n \"tools\": [\n {\n \"type\": \"function\",\n \"function\": {\n \"name\": \"get_user_location\",\n \"description\": \"Get the current user location\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {},\n \"required\": [\n \"<string>\"\n ]\n }\n }\n }\n ],\n \"transcriptId\": \"550e8400-e29b-41d4-a716-446655440000\"\n}"
response = http.request(request)
puts response.read_body[
{
"uid": "75ecbcfc-a3be-43ba-8da6-b3e16e8d7280",
"chatUid": "550e8400-e29b-41d4-a716-446655440000",
"role": "user",
"content": {
"message": "I would recommend a 450 W monocrystalline panel.",
"data": {},
"files": [
{
"name": "invoice.pdf",
"donwloadUrl": "https://files.devic.ai/uploads/invoice.pdf",
"fileType": "DOCUMENT"
}
]
},
"timestamp": 1706000000000,
"userUID": "api-key:42",
"summary": "The user asks which panels to install on a 60 m2 roof.",
"contentSource": "finish_tool",
"tool_calls": [
{
"id": "call_abc123",
"type": "function",
"function": {
"name": "get_user_location",
"arguments": "{}"
}
}
],
"tool_call_id": "call_abc123",
"latencyMs": 1045,
"messageTokenUsage": {
"inputTokens": 123,
"outputTokens": 123,
"inputCachedTokens": 123,
"inputCacheWriteTokens": 123,
"outputCachedTokens": 123,
"reasoningOutputTokens": 123,
"totalTokens": 123,
"provider": "<string>",
"model": "<string>"
},
"messageCost": {
"inputCost": 123,
"outputCost": 123,
"inputCachedCost": 123,
"inputCacheWriteCost": 123,
"outputCachedCost": 123,
"reasoningOutputCost": 123,
"totalCost": 123,
"currency": "USD",
"calculatedAt": 123
}
}
]{
"error": "<string>",
"message": "<string>",
"details": {}
}{
"error": "<string>",
"message": "<string>",
"details": {}
}Process a message with an assistant
Sends one user message to an assistant and returns the turn it produced. Pass chatUid to continue a conversation; leave it out to start one and keep the id that comes back.
Synchronous (default). The request is held until the assistant finishes and the response is the array of messages the turn produced — the user message, any tool messages, and the assistant reply — in chronological order. The reply is the last element, and its text is in content.message.
Asynchronous (?async=true). The response is an acknowledgement with the chatUid and nothing else. Follow the run with the realtime endpoint (polling) or the stream endpoint (server-sent events).
Queueing. An async send that cannot start a run right away is queued on the conversation instead: the acknowledgement carries queued: true and willProcess. Reading queuedMessages from the realtime endpoint tells you whether anything is still waiting. Sending while the conversation is busy requires messageQueueEnabled on the assistant; without it the send is rejected with 409 CHAT_BUSY, and past maxQueuedMessages (50 by default) further sends are rejected with 409 too.
Payload-template mode (messageTemplate). Lets a third-party webhook, whose body shape you do not control, point straight at this endpoint: the body is then treated as an opaque payload and the message text is rendered from the template.
curl --request POST \
--url https://api.devic.ai/v1/assistants/{identifier}/messages \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"message": "What solar panels do you recommend?",
"chatUid": "550e8400-e29b-41d4-a716-446655440000",
"userName": "John Doe",
"tags": [
"support",
"onboarding"
],
"files": [
{
"name": "invoice.pdf",
"donwloadUrl": "https://files.devic.ai/uploads/invoice.pdf",
"fileType": "DOCUMENT"
}
],
"images": [
{
"imageUrl": "https://files.devic.ai/uploads/roof.jpg"
}
],
"metadata": {
"promptTemplateParams": {
"companyName": "Acme Corp"
},
"source": "web-widget"
},
"tenantId": "tenant_12345",
"subtenantId": "user_67890",
"previousConversation": [
{
"message": "Hello",
"role": "user"
},
{
"message": "Hi there!",
"role": "assistant"
}
],
"enabledTools": [
"get_weather",
"calculator"
],
"disabledIntegrations": [
"gmail"
],
"provider": "open-ai",
"model": "gpt-4.1",
"tools": [
{
"type": "function",
"function": {
"name": "get_user_location",
"description": "Get the current user location",
"parameters": {
"type": "object",
"properties": {},
"required": [
"<string>"
]
}
}
}
],
"transcriptId": "550e8400-e29b-41d4-a716-446655440000"
}
'import requests
url = "https://api.devic.ai/v1/assistants/{identifier}/messages"
payload = {
"message": "What solar panels do you recommend?",
"chatUid": "550e8400-e29b-41d4-a716-446655440000",
"userName": "John Doe",
"tags": ["support", "onboarding"],
"files": [
{
"name": "invoice.pdf",
"donwloadUrl": "https://files.devic.ai/uploads/invoice.pdf",
"fileType": "DOCUMENT"
}
],
"images": [{ "imageUrl": "https://files.devic.ai/uploads/roof.jpg" }],
"metadata": {
"promptTemplateParams": { "companyName": "Acme Corp" },
"source": "web-widget"
},
"tenantId": "tenant_12345",
"subtenantId": "user_67890",
"previousConversation": [
{
"message": "Hello",
"role": "user"
},
{
"message": "Hi there!",
"role": "assistant"
}
],
"enabledTools": ["get_weather", "calculator"],
"disabledIntegrations": ["gmail"],
"provider": "open-ai",
"model": "gpt-4.1",
"tools": [
{
"type": "function",
"function": {
"name": "get_user_location",
"description": "Get the current user location",
"parameters": {
"type": "object",
"properties": {},
"required": ["<string>"]
}
}
}
],
"transcriptId": "550e8400-e29b-41d4-a716-446655440000"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
message: 'What solar panels do you recommend?',
chatUid: '550e8400-e29b-41d4-a716-446655440000',
userName: 'John Doe',
tags: ['support', 'onboarding'],
files: [
{
name: 'invoice.pdf',
donwloadUrl: 'https://files.devic.ai/uploads/invoice.pdf',
fileType: 'DOCUMENT'
}
],
images: [{imageUrl: 'https://files.devic.ai/uploads/roof.jpg'}],
metadata: {promptTemplateParams: {companyName: 'Acme Corp'}, source: 'web-widget'},
tenantId: 'tenant_12345',
subtenantId: 'user_67890',
previousConversation: [{message: 'Hello', role: 'user'}, {message: 'Hi there!', role: 'assistant'}],
enabledTools: ['get_weather', 'calculator'],
disabledIntegrations: ['gmail'],
provider: 'open-ai',
model: 'gpt-4.1',
tools: [
{
type: 'function',
function: {
name: 'get_user_location',
description: 'Get the current user location',
parameters: {type: 'object', properties: {}, required: ['<string>']}
}
}
],
transcriptId: '550e8400-e29b-41d4-a716-446655440000'
})
};
fetch('https://api.devic.ai/v1/assistants/{identifier}/messages', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.devic.ai/v1/assistants/{identifier}/messages",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'message' => 'What solar panels do you recommend?',
'chatUid' => '550e8400-e29b-41d4-a716-446655440000',
'userName' => 'John Doe',
'tags' => [
'support',
'onboarding'
],
'files' => [
[
'name' => 'invoice.pdf',
'donwloadUrl' => 'https://files.devic.ai/uploads/invoice.pdf',
'fileType' => 'DOCUMENT'
]
],
'images' => [
[
'imageUrl' => 'https://files.devic.ai/uploads/roof.jpg'
]
],
'metadata' => [
'promptTemplateParams' => [
'companyName' => 'Acme Corp'
],
'source' => 'web-widget'
],
'tenantId' => 'tenant_12345',
'subtenantId' => 'user_67890',
'previousConversation' => [
[
'message' => 'Hello',
'role' => 'user'
],
[
'message' => 'Hi there!',
'role' => 'assistant'
]
],
'enabledTools' => [
'get_weather',
'calculator'
],
'disabledIntegrations' => [
'gmail'
],
'provider' => 'open-ai',
'model' => 'gpt-4.1',
'tools' => [
[
'type' => 'function',
'function' => [
'name' => 'get_user_location',
'description' => 'Get the current user location',
'parameters' => [
'type' => 'object',
'properties' => [
],
'required' => [
'<string>'
]
]
]
]
],
'transcriptId' => '550e8400-e29b-41d4-a716-446655440000'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.devic.ai/v1/assistants/{identifier}/messages"
payload := strings.NewReader("{\n \"message\": \"What solar panels do you recommend?\",\n \"chatUid\": \"550e8400-e29b-41d4-a716-446655440000\",\n \"userName\": \"John Doe\",\n \"tags\": [\n \"support\",\n \"onboarding\"\n ],\n \"files\": [\n {\n \"name\": \"invoice.pdf\",\n \"donwloadUrl\": \"https://files.devic.ai/uploads/invoice.pdf\",\n \"fileType\": \"DOCUMENT\"\n }\n ],\n \"images\": [\n {\n \"imageUrl\": \"https://files.devic.ai/uploads/roof.jpg\"\n }\n ],\n \"metadata\": {\n \"promptTemplateParams\": {\n \"companyName\": \"Acme Corp\"\n },\n \"source\": \"web-widget\"\n },\n \"tenantId\": \"tenant_12345\",\n \"subtenantId\": \"user_67890\",\n \"previousConversation\": [\n {\n \"message\": \"Hello\",\n \"role\": \"user\"\n },\n {\n \"message\": \"Hi there!\",\n \"role\": \"assistant\"\n }\n ],\n \"enabledTools\": [\n \"get_weather\",\n \"calculator\"\n ],\n \"disabledIntegrations\": [\n \"gmail\"\n ],\n \"provider\": \"open-ai\",\n \"model\": \"gpt-4.1\",\n \"tools\": [\n {\n \"type\": \"function\",\n \"function\": {\n \"name\": \"get_user_location\",\n \"description\": \"Get the current user location\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {},\n \"required\": [\n \"<string>\"\n ]\n }\n }\n }\n ],\n \"transcriptId\": \"550e8400-e29b-41d4-a716-446655440000\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.devic.ai/v1/assistants/{identifier}/messages")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"message\": \"What solar panels do you recommend?\",\n \"chatUid\": \"550e8400-e29b-41d4-a716-446655440000\",\n \"userName\": \"John Doe\",\n \"tags\": [\n \"support\",\n \"onboarding\"\n ],\n \"files\": [\n {\n \"name\": \"invoice.pdf\",\n \"donwloadUrl\": \"https://files.devic.ai/uploads/invoice.pdf\",\n \"fileType\": \"DOCUMENT\"\n }\n ],\n \"images\": [\n {\n \"imageUrl\": \"https://files.devic.ai/uploads/roof.jpg\"\n }\n ],\n \"metadata\": {\n \"promptTemplateParams\": {\n \"companyName\": \"Acme Corp\"\n },\n \"source\": \"web-widget\"\n },\n \"tenantId\": \"tenant_12345\",\n \"subtenantId\": \"user_67890\",\n \"previousConversation\": [\n {\n \"message\": \"Hello\",\n \"role\": \"user\"\n },\n {\n \"message\": \"Hi there!\",\n \"role\": \"assistant\"\n }\n ],\n \"enabledTools\": [\n \"get_weather\",\n \"calculator\"\n ],\n \"disabledIntegrations\": [\n \"gmail\"\n ],\n \"provider\": \"open-ai\",\n \"model\": \"gpt-4.1\",\n \"tools\": [\n {\n \"type\": \"function\",\n \"function\": {\n \"name\": \"get_user_location\",\n \"description\": \"Get the current user location\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {},\n \"required\": [\n \"<string>\"\n ]\n }\n }\n }\n ],\n \"transcriptId\": \"550e8400-e29b-41d4-a716-446655440000\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.devic.ai/v1/assistants/{identifier}/messages")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"message\": \"What solar panels do you recommend?\",\n \"chatUid\": \"550e8400-e29b-41d4-a716-446655440000\",\n \"userName\": \"John Doe\",\n \"tags\": [\n \"support\",\n \"onboarding\"\n ],\n \"files\": [\n {\n \"name\": \"invoice.pdf\",\n \"donwloadUrl\": \"https://files.devic.ai/uploads/invoice.pdf\",\n \"fileType\": \"DOCUMENT\"\n }\n ],\n \"images\": [\n {\n \"imageUrl\": \"https://files.devic.ai/uploads/roof.jpg\"\n }\n ],\n \"metadata\": {\n \"promptTemplateParams\": {\n \"companyName\": \"Acme Corp\"\n },\n \"source\": \"web-widget\"\n },\n \"tenantId\": \"tenant_12345\",\n \"subtenantId\": \"user_67890\",\n \"previousConversation\": [\n {\n \"message\": \"Hello\",\n \"role\": \"user\"\n },\n {\n \"message\": \"Hi there!\",\n \"role\": \"assistant\"\n }\n ],\n \"enabledTools\": [\n \"get_weather\",\n \"calculator\"\n ],\n \"disabledIntegrations\": [\n \"gmail\"\n ],\n \"provider\": \"open-ai\",\n \"model\": \"gpt-4.1\",\n \"tools\": [\n {\n \"type\": \"function\",\n \"function\": {\n \"name\": \"get_user_location\",\n \"description\": \"Get the current user location\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {},\n \"required\": [\n \"<string>\"\n ]\n }\n }\n }\n ],\n \"transcriptId\": \"550e8400-e29b-41d4-a716-446655440000\"\n}"
response = http.request(request)
puts response.read_body[
{
"uid": "75ecbcfc-a3be-43ba-8da6-b3e16e8d7280",
"chatUid": "550e8400-e29b-41d4-a716-446655440000",
"role": "user",
"content": {
"message": "I would recommend a 450 W monocrystalline panel.",
"data": {},
"files": [
{
"name": "invoice.pdf",
"donwloadUrl": "https://files.devic.ai/uploads/invoice.pdf",
"fileType": "DOCUMENT"
}
]
},
"timestamp": 1706000000000,
"userUID": "api-key:42",
"summary": "The user asks which panels to install on a 60 m2 roof.",
"contentSource": "finish_tool",
"tool_calls": [
{
"id": "call_abc123",
"type": "function",
"function": {
"name": "get_user_location",
"arguments": "{}"
}
}
],
"tool_call_id": "call_abc123",
"latencyMs": 1045,
"messageTokenUsage": {
"inputTokens": 123,
"outputTokens": 123,
"inputCachedTokens": 123,
"inputCacheWriteTokens": 123,
"outputCachedTokens": 123,
"reasoningOutputTokens": 123,
"totalTokens": 123,
"provider": "<string>",
"model": "<string>"
},
"messageCost": {
"inputCost": 123,
"outputCost": 123,
"inputCachedCost": 123,
"inputCacheWriteCost": 123,
"outputCachedCost": 123,
"reasoningOutputCost": 123,
"totalCost": 123,
"currency": "USD",
"calculatedAt": 123
}
}
]{
"error": "<string>",
"message": "<string>",
"details": {}
}{
"error": "<string>",
"message": "<string>",
"details": {}
}Authorizations
An API key from your Devic console, sent as Authorization: Bearer <key>. An embedded front end sends a tenant-session token instead, so no API key reaches the browser, and an OAuth integration sends its access token. Missing, invalid or expired credentials get a 401. See Authentication.
Path Parameters
Identifier of the assistant, as returned by the assistants endpoints.
Query Parameters
Send true to return as soon as the message is accepted, with the chatUid to poll, instead of waiting for the assistant to finish.
Language the assistant has to answer in, as a language code (en, es, fr, ...). Overrides whatever the prompt says for this message only.
Send true to skip the per-message summaries. Saves a secondary model call, so it cuts latency and cost when nothing reads summary.
Turns on payload-template mode. The request body stops being a ProcessMessageRequest and is taken as an opaque payload, and the message text is rendered from this template: {{path.to.field}} resolves a dot-path into the body, {{$date}} resolves to the current server date (YYYY-MM-DD, see tz).
In this mode every other body field — metadata, tenantId, provider, model, ... — is ignored, so an external payload cannot set them. A template that renders an empty string (a sticker, a reaction, an unrelated event) is acknowledged with 200 and no run, so the sender does not retry.
Template for the chatUid in payload-template mode, same syntax as messageTemplate and only valid together with it. Use it to derive the conversation grouping from the payload, for example one conversation per source chat per day. When omitted, or when it renders empty, a new chatUid is generated.
Template for the userName in payload-template mode, same syntax as messageTemplate and only valid together with it.
IANA timezone used to resolve {{$date}} in the templates. Defaults to UTC; an invalid value falls back to UTC.
Body
The message to send and the context it is sent with. In payload-template mode the body is instead the third-party payload the templates read from.
One user message and the context it is sent with. The assistant answers that single message; the rest of the conversation is recovered from chatUid.
The user message the assistant has to answer. Required, except in payload-template mode (messageTemplate query parameter), where the body is an opaque third-party payload and the text is rendered from the template instead.
"What solar panels do you recommend?"
Conversation to continue. Omit it to start a new one: the generated id comes back on the messages of the response (and, in async mode, in the acknowledgement), and is what you send on the next call.
"550e8400-e29b-41d4-a716-446655440000"
Name of the end user writing, used for personalisation and shown in the conversation logs.
"John Doe"
Tags stored on the conversation, to filter it later from the chat listing endpoints.
["support", "onboarding"]
Files attached to the message. Upload them first with the file upload endpoint, then pass the returned download URL here.
Show child attributes
Show child attributes
Images attached to the message, always as URLs (never base64). Requires a vision-capable model.
Show child attributes
Show child attributes
Free-form context stored on the conversation. Two keys are read by the platform; anything else is kept as-is and can be read back from the chat history.
Show child attributes
Show child attributes
{
"promptTemplateParams": { "companyName": "Acme Corp" },
"source": "web-widget"
}
Tenant (customer/organization) this conversation belongs to in multi-tenant setups. Auto-registers the tenant on first use and attributes its cost/usage. See the Tenants endpoints.
"tenant_12345"
End user/entity inside the tenant. When omitted it is derived from metadata.subtenantMetadata.id or the legacy metadata.userId. Used for per-subtenant cost attribution and usage limits.
"user_67890"
Earlier exchanges to seed the conversation with, for example when migrating a chat from another system. Only accepted when starting a new conversation, that is, without chatUid.
Show child attributes
Show child attributes
[
{ "message": "Hello", "role": "user" },
{
"message": "Hi there!",
"role": "assistant"
}
]
Restricts this message to these tools, by name, out of the ones the assistant's tool servers offer. Omit the field to leave the assistant's own configuration alone; send an empty array to run the message with no tools at all.
["get_weather", "calculator"]
Apps the end user connected that should sit out this message, by slug. A deny list over the tenant's own connected apps only — the assistant's tool servers are governed by enabledTools. The account stays connected and the next message has it back unless it is named again.
["gmail"]
Overrides the assistant's LLM provider for this message. The account must have that provider configured.
open-ai, anthropic, google-gemini, deepseek, kimi, xai "open-ai"
Overrides the assistant's model for this message. Must be a supported model and, when provider is also sent, must belong to it.
"gpt-4.1"
Model Interface Protocol: tools that run on your side. When the assistant calls one, the turn stops with the call pending and you answer it with the tool-response endpoint.
Show child attributes
Show child attributes
Id of a speech-to-text transcript (from the transcription endpoint) that seeded this message, so the conversation keeps a link to the original audio.
"550e8400-e29b-41d4-a716-446655440000"
Response
Synchronously, the messages the turn produced, oldest first, with the assistant reply last. In async mode, the acknowledgement with the chatUid to poll.
- object[]
- object
A single message of a conversation, as the platform stored it.
Unique message id
"75ecbcfc-a3be-43ba-8da6-b3e16e8d7280"
Conversation this message belongs to
"550e8400-e29b-41d4-a716-446655440000"
Who the message is from. developer messages are the ones the platform injects (current date, injected context) and can be ignored by most clients.
user, assistant, developer, tool Body of the message.
Show child attributes
Show child attributes
Unix timestamp in milliseconds
1706000000000
Identity the message was written under
"api-key:42"
Short AI-generated summary of the message, unless summarisation was skipped
"The user asks which panels to install on a 60 m2 roof."
Where content.message came from when the model did not write it. finish_tool means the reply was taken from the finish tool's message argument, so it can be read without parsing tool calls. Absent on messages the model wrote itself.
"finish_tool"
Tool calls the assistant made on this message
Show child attributes
Show child attributes
On tool messages, the call this message answers
"call_abc123"
How long the model or the tool took, in milliseconds
1045
Tokens this message accounted for
Show child attributes
Show child attributes
What this message cost, at the pricing in force when it ran
Show child attributes
Show child attributes