Skip to content

Messages API

Manage individual messages within dialogues.

Create Message

Add a new message to a dialogue.

Endpoint

http
POST /dialogue/{id}/messages

Authentication

Bearer token (via Authorization header)

Path Parameters

ParameterTypeRequiredDescription
idstringYesDialogue ID (identifier)

Request Body

FieldTypeRequiredDescription
rolestringYesMessage role: "user", "assistant", or "system"
contentstring | object | object[]YesMessage content — plain text, structured object, or array of content blocks
namestringNoOptional name for the speaker
idstringNoCustom message ID (auto-generated if not provided)
createdstringNoCustom creation timestamp (ISO 8601, auto-generated if not provided)
metadataobjectNoCustom metadata (can't be changed after creation)
tagsstring[]NoCustom tags

Response

typescript
{
  id: string;
  dialogueId: string;
  role: string;
  content: string | object | object[];
  contentLength: number;
  created: string;
  modified: string;
}

Behavior

  • Authenticated via bearer token
  • Full content included in response
  • Updates dialogue message count and timestamp

Which Fields Can Be Changed?

User-settable on creation:

  • content - Message content (required)
  • role - Message role (required)
  • name - Optional speaker name
  • id - Custom identifier (auto-generated if omitted)
  • created - Custom timestamp (auto-generated if omitted)
  • tags - Categorization tags
  • metadata - Custom metadata (can't be changed after creation)

System-managed (read-only):

  • dialogueId - Parent dialogue reference
  • contentLength - Content size in bytes
  • modified - Last modification timestamp

Messages Can't Be Changed

Messages cannot be updated after creation — only created and deleted. If you need to "edit" a message:

  • Delete the original message
  • Create a new message with the corrected content
  • Or keep the original and add a follow-up correction message

Metadata Can't Be Changed

Message metadata is set at creation and cannot be changed. Use tags for categorization that may need to change later.

Errors

StatusError CodeDescription
400MISSING_PARAMETERMissing required field (role, content, or dialogue ID)
400MESSAGE_CONTENT_EMPTYMessage content cannot be empty
400MESSAGE_TOO_LARGEMessage exceeds 1MB uncompressed size limit
401N/AUnauthorized - invalid or missing API key
404DIALOGUE_NOT_FOUNDDialogue does not exist
409DIALOGUE_ENDEDCannot add messages to an ended dialogue
409DIALOGUE_IMMUTABLECannot add messages to immutable dialogue
429RATE_LIMIT_EXCEEDEDToo many requests - retry with backoff
500INTERNAL_ERRORServer error - contact support with requestId

See Error Handling for complete error reference.

Examples

bash
curl -X POST https://api.dialoguedb.com/dialogue/dlg_abc123xyz/messages \
  -H "Authorization: Bearer DIALOGUE_DB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "role": "user",
    "content": "Hello, how are you?"
  }'
typescript
const message = await fetch(
  `https://api.dialoguedb.com/dialogue/${dialogueId}/messages`,
  {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer DIALOGUE_DB_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      role: 'user',
      content: 'Hello, how are you?',
      metadata: {
        timestamp: new Date().toISOString(),
        userId: 'user_123'
      }
    })
  }
).then(r => r.json());
python
import requests

response = requests.post(
    f"https://api.dialoguedb.com/dialogue/{dialogue_id}/messages",
    headers={
        "Authorization": "Bearer DIALOGUE_DB_API_KEY",
        "Content-Type": "application/json"
    },
    json={
        "role": "user",
        "content": "Hello, how are you?",
        "metadata": {
            "timestamp": "2026-02-19T12:00:00Z"
        }
    }
)
message = response.json()
typescript
const dialogue = await db.getDialogue(dialogueId);

const message = await dialogue.saveMessage({
  role: 'user',
  content: 'Hello, how are you?',
  metadata: {
    timestamp: new Date().toISOString()
  }
});

List Messages

Retrieve messages for a specific dialogue with pagination.

Endpoint

http
GET /dialogue/{id}/messages

Authentication

Bearer token (via Authorization header)

Path Parameters

ParameterTypeRequiredDescription
idstringYesDialogue ID (identifier)

Query Parameters

ParameterTypeRequiredDescription
limitnumberNoMax messages to return (default: 50)
nextstringNoPagination token for next page

Response

typescript
{
  items: Message[];
  next?: string; // Pagination token if more messages exist
}

Message Format

typescript
{
  id: string;
  dialogueId: string;
  role: "user" | "assistant" | "system";
  content: string | object | object[];
  contentLength: number;
  created: string;
  metadata?: Record<string, any>;
}

Behavior

  • Messages ordered chronologically (oldest first)
  • Paginate for large conversation histories
  • Full content included for all messages
  • Authenticated via bearer token

Errors

StatusError CodeDescription
400MISSING_PARAMETERMissing required dialogue ID
401N/AUnauthorized - invalid or missing API key
404DIALOGUE_NOT_FOUNDDialogue does not exist
429RATE_LIMIT_EXCEEDEDToo many requests - retry with backoff
500INTERNAL_ERRORServer error - contact support with requestId

See Error Handling for complete error reference.

Examples

bash
curl -X GET "https://api.dialoguedb.com/dialogue/dlg_abc123xyz/messages?limit=100" \
  -H "Authorization: Bearer DIALOGUE_DB_API_KEY"
typescript
const { items, next } = await fetch(
  `https://api.dialoguedb.com/dialogue/${dialogueId}/messages?limit=100`,
  {
    headers: {
      'Authorization': 'Bearer DIALOGUE_DB_API_KEY'
    }
  }
).then(r => r.json());

// Load next page
if (next) {
  const { items: more, next: nextToken } = await fetch(
    `https://api.dialoguedb.com/dialogue/${dialogueId}/messages?limit=100&next=${next}`,
    {
      headers: {
        'Authorization': 'Bearer DIALOGUE_DB_API_KEY'
      }
    }
  ).then(r => r.json());
}
python
import requests

response = requests.get(
    f"https://api.dialoguedb.com/dialogue/{dialogue_id}/messages",
    headers={"Authorization": "Bearer DIALOGUE_DB_API_KEY"},
    params={"limit": 100}
)
data = response.json()
items = data["items"]
next_token = data.get("next")

# Load next page
if next_token:
    response = requests.get(
        f"https://api.dialoguedb.com/dialogue/{dialogue_id}/messages",
        headers={"Authorization": "Bearer DIALOGUE_DB_API_KEY"},
        params={"limit": 100, "next": next_token}
    )
    more_data = response.json()
typescript
const dialogue = await db.getDialogue(dialogueId);

const messages = await dialogue.loadMessages({
  limit: 100
});

// Load next page
const moreMessages = await dialogue.loadMessages({
  limit: 100,
  next: messages.next
});

Get Single Message

Retrieve a single message by ID.

Endpoint

http
GET /dialogue/{id}/message/{messageId}

Authentication

Bearer token (via Authorization header)

Path Parameters

ParameterTypeRequiredDescription
idstringYesDialogue ID (identifier)
messageIdstringYesMessage ID (identifier)

Response

typescript
{
  id: string;
  dialogueId: string;
  role: "user" | "assistant" | "system";
  content: string | object | object[];
  contentLength: number;
  created: string;
  metadata?: Record<string, any>;
}

Behavior

  • Returns complete message with full content
  • Authenticated via bearer token

Errors

StatusError CodeDescription
400MISSING_PARAMETERMissing required dialogue ID or message ID
401N/AUnauthorized - invalid or missing API key
404MESSAGE_NOT_FOUNDMessage does not exist
429RATE_LIMIT_EXCEEDEDToo many requests - retry with backoff
500INTERNAL_ERRORServer error - contact support with requestId

See Error Handling for complete error reference.

Examples

bash
curl -X GET https://api.dialoguedb.com/dialogue/dlg_abc123xyz/message/msg_xyz789abc \
  -H "Authorization: Bearer DIALOGUE_DB_API_KEY"
typescript
const message = await fetch(
  `https://api.dialoguedb.com/dialogue/${dialogueId}/message/${messageId}`,
  {
    headers: {
      'Authorization': 'Bearer DIALOGUE_DB_API_KEY'
    }
  }
).then(r => r.json());
python
import requests

response = requests.get(
    f"https://api.dialoguedb.com/dialogue/{dialogue_id}/message/{message_id}",
    headers={"Authorization": "Bearer DIALOGUE_DB_API_KEY"}
)
message = response.json()
typescript
// Get a single message by ID (use raw API)
import { api } from 'dialogue-db';

const message = await api.message.get({
  dialogueId,
  id: messageId
});

Delete Message

Delete a specific message from a dialogue.

Endpoint

http
DELETE /dialogue/{id}/message/{messageId}

Authentication

Bearer token (via Authorization header)

Path Parameters

ParameterTypeRequiredDescription
idstringYesDialogue ID (identifier)
messageIdstringYesMessage ID (identifier)

Response

typescript
{
  success: boolean;
  id: string;
  dialogueId: string;
}

Behavior

  • Permanently removes the message
  • Dialogue totalMessages count is decremented
  • This operation cannot be undone

Warnings

  • Irreversible: Deleted messages cannot be recovered
  • Use sparingly: Consider soft-deletion via metadata instead
  • GET /dialogue/{id}/messages - List remaining messages
  • DELETE /dialogue/{id} - Delete entire dialogue

Errors

StatusError CodeDescription
400MISSING_PARAMETERMissing required dialogue ID or message ID
401N/AUnauthorized - invalid or missing API key
404MESSAGE_NOT_FOUNDMessage does not exist
409DIALOGUE_IMMUTABLECannot delete messages from immutable dialogue
429RATE_LIMIT_EXCEEDEDToo many requests - retry with backoff
500INTERNAL_ERRORServer error - contact support with requestId

See Error Handling for complete error reference.

Examples

bash
curl -X DELETE https://api.dialoguedb.com/dialogue/dlg_abc123xyz/message/msg_xyz789abc \
  -H "Authorization: Bearer DIALOGUE_DB_API_KEY"
typescript
const result = await fetch(
  `https://api.dialoguedb.com/dialogue/${dialogueId}/message/${messageId}`,
  {
    method: 'DELETE',
    headers: {
      'Authorization': 'Bearer DIALOGUE_DB_API_KEY'
    }
  }
).then(r => r.json());
python
import requests

response = requests.delete(
    f"https://api.dialoguedb.com/dialogue/{dialogue_id}/message/{message_id}",
    headers={"Authorization": "Bearer DIALOGUE_DB_API_KEY"}
)
result = response.json()
typescript
const dialogue = await db.getDialogue(dialogueId);

await dialogue.deleteMessage(messageId);

Message Roles

User

Messages from end users or human participants.

typescript
{
  role: 'user',
  content: 'What is the weather today?'
}

Assistant

Responses from AI assistants or bots.

typescript
{
  role: 'assistant',
  content: 'The current weather is sunny with a high of 75°F.'
}

System

System prompts, instructions, or notifications.

typescript
{
  role: 'system',
  content: 'You are a helpful weather assistant. Provide accurate information.'
}

Message Content

The content field accepts string | object | object[] — store whatever shape your application needs. DialogueDB doesn't enforce any particular content schema; it stores and returns your content exactly as provided.

This is especially useful for AI applications where messages aren't just plain text.

Plain Text

json
{
  "role": "user",
  "content": "What is the weather today?"
}

Tool Calls

Store tool/function calls directly in content — no need to flatten to a string:

json
{
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "Let me check the weather for you."
    },
    {
      "type": "tool_use",
      "id": "call_abc123",
      "name": "get_weather",
      "input": { "location": "San Francisco", "unit": "fahrenheit" }
    }
  ]
}

Tool Results

json
{
  "role": "user",
  "content": [
    {
      "type": "tool_result",
      "tool_use_id": "call_abc123",
      "content": "72°F, sunny with light clouds"
    }
  ]
}

Multi-Part Content

json
{
  "role": "user",
  "content": [
    { "type": "text", "text": "What's in this image?" },
    { "type": "image_url", "image_url": { "url": "https://example.com/photo.jpg" } }
  ]
}

Structured Objects

json
{
  "role": "assistant",
  "content": {
    "type": "structured_output",
    "data": { "sentiment": "positive", "confidence": 0.95, "topics": ["weather", "travel"] }
  }
}

Store It As-Is

You don't need to JSON.stringify() structured content into a string. Pass objects and arrays directly — DialogueDB handles serialization and will return the original structure when you retrieve the message.


Message Storage

Messages are automatically stored and optimized for fast retrieval. The system handles storage transparently - you don't need to do anything special.

Retrieving Messages

All messages include full content when retrieved:

typescript
const dialogue = await db.getDialogue(dialogueId);
const messages = await dialogue.loadMessages();

// All messages include complete content
messages.forEach(msg => {
  console.log(msg.content);       // Full message content
  console.log(msg.contentLength); // Content size in bytes
});

Best Practices

Pagination

Always use pagination for dialogues with many messages:

typescript
async function getAllMessages(dialogueId: string) {
  const db = new DialogueDB({ apiKey: process.env.DIALOGUE_DB_API_KEY });
  const dialogue = await db.getDialogue(dialogueId);
  const allMessages = [];
  let nextToken = undefined;

  do {
    const result = await dialogue.loadMessages({
      limit: 100,
      next: nextToken
    });

    allMessages.push(...result);
    nextToken = result.next;
  } while (nextToken);

  return allMessages;
}

Message Batching

When adding multiple messages, use parallel creation:

typescript
// Add multiple messages efficiently using saveMessages
const dialogue = await db.getDialogue(dialogueId);

await dialogue.saveMessages([
  { role: 'user', content: 'Question 1' },
  { role: 'assistant', content: 'Answer 1' },
  { role: 'user', content: 'Question 2' }
]);

Error Handling

Handle message creation errors gracefully with proper error codes:

typescript
async function safeCreateMessage(dialogue: any, message: any) {
  try {
    return await dialogue.saveMessage(message);
  } catch (error) {
    switch (error.code) {
      case 'DIALOGUE_NOT_FOUND':
        console.error('Dialogue not found - create it first');
        break;
      case 'MESSAGE_CONTENT_EMPTY':
        console.error('Message content cannot be empty');
        break;
      case 'MESSAGE_TOO_LARGE':
        console.error('Message exceeds 1MB limit');
        break;
      case 'DIALOGUE_IMMUTABLE':
        console.error('Cannot modify immutable dialogue');
        break;
      case 'RATE_LIMIT_EXCEEDED':
        await sleep(1000);
        return safeCreateMessage(dialogue, message);
      default:
        console.error('Failed to create message:', error);
    }
    throw error;
  }
}

See Error Handling Guide for comprehensive error handling patterns.

Built with DialogueDB