Skip to main content

Conversations API

Retrieve and browse your chatbot's messages programmatically through the Developer API.


Base URL

https://api.peki.ai/api

Authentication

All endpoints require HMAC-SHA256 authentication. See the Messages API guide for full details on signature generation.

Required Headers

HeaderRequiredDescription
Content-TypeMust be application/json
X-API-KeyYour API key (starts with pk_)
X-SignatureHMAC-SHA256 signature
X-TimestampUnix timestamp in seconds

List Messages

Get all messages for your chatbot with pagination. Optionally filter by session or user.

GET /Dev/{chatbotId}/messages

Path Parameters

ParameterTypeRequiredDescription
chatbotIdstringThe unique identifier for your chatbot

Query Parameters

ParameterTypeRequiredDefaultDescription
sessionIdstring-Filter messages by session ID
userIdstring-Filter messages by user ID
pageint1Page number (1-based)
pageSizeint20Number of items per page

Response

{
"data": [
{
"id": "6612a1b2c3d4e5f6a7b8c9d2",
"chatbotId": "your_chatbot_id",
"chatSessionId": "6612a1b2c3d4e5f6a7b8c9d1",
"chatUserId": "6612a1b2c3d4e5f6a7b8c9d0",
"senderType": "User",
"text": "What are the latest crypto trends?",
"tokenCount": 12,
"responseTime": null,
"createdAt": "2025-04-08T12:00:00Z"
},
{
"id": "6612a1b2c3d4e5f6a7b8c9d3",
"chatbotId": "your_chatbot_id",
"chatSessionId": "6612a1b2c3d4e5f6a7b8c9d1",
"chatUserId": "6612a1b2c3d4e5f6a7b8c9d0",
"senderType": "Bot",
"text": "Based on current market trends, here are the key developments...",
"tokenCount": 350,
"responseTime": 1.25,
"createdAt": "2025-04-08T12:00:02Z"
}
],
"error": null,
"totalItems": 500,
"pageSize": 20,
"currentPage": 1,
"totalPages": 25
}

Response Fields

FieldTypeDescription
idstringUnique identifier for the message
chatbotIdstringThe chatbot this message belongs to
chatSessionIdstringThe session this message belongs to
chatUserIdstringThe user who sent or received the message
senderTypestringWho sent the message: User or Bot
textstringThe message content (for text messages)
urlstringMedia URL (for media messages)
tokenCountintNumber of tokens consumed by this message
responseTimenumberAI response time in seconds (only for Bot messages)
createdAtdatetimeWhen the message was sent

Get Message

Get a single message by its ID.

GET /Dev/{chatbotId}/messages/{messageId}

Path Parameters

ParameterTypeRequiredDescription
chatbotIdstringThe unique identifier for your chatbot
messageIdstringThe unique identifier for the message

Response

{
"data": {
"id": "6612a1b2c3d4e5f6a7b8c9d2",
"chatbotId": "your_chatbot_id",
"chatSessionId": "6612a1b2c3d4e5f6a7b8c9d1",
"chatUserId": "6612a1b2c3d4e5f6a7b8c9d0",
"senderType": "User",
"text": "What are the latest crypto trends?",
"tokenCount": 12,
"createdAt": "2025-04-08T12:00:00Z"
},
"error": null
}

Error Response

{
"data": null,
"error": "Message not found."
}

Get Message Count

Get the number of messages within a date range — optionally filtered by sender.

Analytics performance

The count and count-by-month endpoints aggregate server-side in a single database query. For analytics and dashboards, use these instead of paging through GET /messages and counting client-side — they are dramatically faster and transfer almost no data, no matter how many messages exist.

GET /Dev/{chatbotId}/messages/count?from={from}&to={to}

Path Parameters

ParameterTypeRequiredDescription
chatbotIdstringThe unique identifier for your chatbot

Query Parameters

ParameterTypeRequiredDescription
fromdatetime (ISO 8601)Start of the range (inclusive), e.g. 2025-01-01
todatetime (ISO 8601)End of the range (exclusive). Must be after from
sentbooleanFilter by sender. true = user-sent only, false = non-user (bot/system/agent), omitted = all senders

Response

{
"data": 1234,
"error": null
}

The data field is the number of messages in the range, respecting the sent filter when provided.

Examples

GET /Dev/{chatbotId}/messages/count?from=2025-01-01&to=2025-02-01           # all messages
GET /Dev/{chatbotId}/messages/count?from=2025-01-01&to=2025-02-01&sent=true # user-sent only

Error Response

{
"data": 0,
"error": "`to` must be greater than `from`."
}

Get Message Counts by Month

Get message metrics aggregated per calendar month across a date range — useful for usage dashboards, growth tracking, and billing.

GET /Dev/{chatbotId}/messages/count-by-month?from={from}&to={to}

Path Parameters

ParameterTypeRequiredDescription
chatbotIdstringThe unique identifier for your chatbot

Query Parameters

ParameterTypeRequiredDescription
fromdatetime (ISO 8601)Start of the range (inclusive)
todatetime (ISO 8601)End of the range (exclusive). Must be after from

Response

{
"data": [
{
"month": "2025-01",
"messageCount": 5200,
"userMessageCount": 2600,
"distinctUsers": 480,
"distinctSessions": 910,
"tokenTotal": 1450000
},
{
"month": "2025-02",
"messageCount": 6100,
"userMessageCount": 3050,
"distinctUsers": 530,
"distinctSessions": 1020,
"tokenTotal": 1710000
}
],
"error": null
}

Response Fields

FieldTypeDescription
monthstringMonth bucket in YYYY-MM format (UTC)
messageCountnumberTotal messages (any sender) in the month
userMessageCountnumberMessages sent by users only (senderType = User)
distinctUsersnumberDistinct users who sent at least one message in the month
distinctSessionsnumberDistinct sessions active in the month
tokenTotalnumberSum of tokenCount across all messages in the month

Error Response

{
"data": null,
"error": "`to` must be greater than `from`."
}

Filtering Messages

By Session

Get all messages in a specific conversation session:

GET /Dev/{chatbotId}/messages?sessionId=6612a1b2c3d4e5f6a7b8c9d1

By User

Get all messages from a specific user across all sessions:

GET /Dev/{chatbotId}/messages?userId=6612a1b2c3d4e5f6a7b8c9d0

Combined Filters

Filter by both session and user:

GET /Dev/{chatbotId}/messages?sessionId=SESSION_ID&userId=USER_ID&page=1&pageSize=50

Pagination

All list endpoints return paginated results with the following metadata:

FieldTypeDescription
totalItemsintTotal number of records
pageSizeintNumber of items per page
currentPageintCurrent page number
totalPagesintTotal number of pages

Use the page and pageSize query parameters to navigate through results. Results are ordered by creation date (newest first).


Code Examples

JavaScript

const crypto = require("crypto");

const apiKey = "pk_your_api_key";
const apiSecret = "sk_your_api_secret";
const chatbotId = "your_chatbot_id";
const sessionId = "your_session_id";

// Get messages for a specific session
const timestamp = Math.floor(Date.now() / 1000);
const path = `/api/Dev/${chatbotId}/messages?sessionId=${sessionId}&page=1&pageSize=50`;
const payload = `GET\n${path}\n\n${timestamp}`;
const signature = crypto
.createHmac("sha256", apiSecret)
.update(payload)
.digest("base64");

const response = await fetch(`https://api.peki.ai${path}`, {
method: "GET",
headers: {
"Content-Type": "application/json",
"X-API-Key": apiKey,
"X-Signature": signature,
"X-Timestamp": timestamp.toString(),
},
});

const result = await response.json();
console.log("Messages:", result.data);
console.log("Total:", result.totalItems);

// --- Monthly analytics (aggregated server-side, no pagination needed) ---
const from = "2025-01-01T00:00:00Z";
const to = "2025-04-01T00:00:00Z";
const statsPath = `/api/Dev/${chatbotId}/messages/count-by-month?from=${from}&to=${to}`;
const statsTs = Math.floor(Date.now() / 1000);
const statsSig = crypto
.createHmac("sha256", apiSecret)
.update(`GET\n${statsPath}\n\n${statsTs}`)
.digest("base64");

const stats = await fetch(`https://api.peki.ai${statsPath}`, {
method: "GET",
headers: {
"Content-Type": "application/json",
"X-API-Key": apiKey,
"X-Signature": statsSig,
"X-Timestamp": statsTs.toString(),
},
}).then((r) => r.json());

stats.data.forEach((m) =>
console.log(`${m.month}: ${m.messageCount} messages, ${m.distinctUsers} users`)
);

Python

import hmac, hashlib, base64, time, requests

api_key = 'pk_your_api_key'
api_secret = 'sk_your_api_secret'
chatbot_id = 'your_chatbot_id'
session_id = 'your_session_id'

# Get messages for a specific session
timestamp = str(int(time.time()))
path = f'/api/Dev/{chatbot_id}/messages?sessionId={session_id}&page=1&pageSize=50'
payload = f'GET\n{path}\n\n{timestamp}'

signature = base64.b64encode(
hmac.new(api_secret.encode(), payload.encode(), hashlib.sha256).digest()
).decode()

headers = {
'Content-Type': 'application/json',
'X-API-Key': api_key,
'X-Signature': signature,
'X-Timestamp': timestamp
}

response = requests.get(f'https://api.peki.ai{path}', headers=headers)
result = response.json()

for msg in result['data']:
sender = 'You' if msg['senderType'] == 'User' else 'Bot'
print(f'{sender}: {msg.get("text", "")}')

# --- Monthly analytics (aggregated server-side, no pagination needed) ---
stats_ts = str(int(time.time()))
stats_path = f'/api/Dev/{chatbot_id}/messages/count-by-month?from=2025-01-01T00:00:00Z&to=2025-04-01T00:00:00Z'
stats_sig = base64.b64encode(
hmac.new(api_secret.encode(), f'GET\n{stats_path}\n\n{stats_ts}'.encode(), hashlib.sha256).digest()
).decode()

stats = requests.get(f'https://api.peki.ai{stats_path}', headers={
'Content-Type': 'application/json',
'X-API-Key': api_key,
'X-Signature': stats_sig,
'X-Timestamp': stats_ts,
}).json()

for m in stats['data']:
print(f"{m['month']}: {m['messageCount']} messages, {m['distinctUsers']} users")

cURL

API_KEY="pk_your_api_key"
API_SECRET="sk_your_api_secret"
CHATBOT_ID="your_chatbot_id"
SESSION_ID="your_session_id"

TIMESTAMP=$(date +%s)
REQ_PATH="/api/Dev/$CHATBOT_ID/messages?sessionId=$SESSION_ID&page=1&pageSize=50"
PAYLOAD="GET\n$REQ_PATH\n\n$TIMESTAMP"
SIGNATURE=$(echo -ne "$PAYLOAD" | openssl dgst -sha256 -hmac "$API_SECRET" -binary | base64)

curl -s "https://api.peki.ai$REQ_PATH" \
-H "Content-Type: application/json" \
-H "X-API-Key: $API_KEY" \
-H "X-Signature: $SIGNATURE" \
-H "X-Timestamp: $TIMESTAMP"

# --- Monthly analytics (aggregated server-side, no pagination needed) ---
STATS_TS=$(date +%s)
STATS_PATH="/api/Dev/$CHATBOT_ID/messages/count-by-month?from=2025-01-01T00:00:00Z&to=2025-04-01T00:00:00Z"
STATS_SIG=$(echo -ne "GET\n$STATS_PATH\n\n$STATS_TS" | openssl dgst -sha256 -hmac "$API_SECRET" -binary | base64)

curl -s "https://api.peki.ai$STATS_PATH" \
-H "Content-Type: application/json" \
-H "X-API-Key: $API_KEY" \
-H "X-Signature: $STATS_SIG" \
-H "X-Timestamp: $STATS_TS"

Common Workflow

A typical flow to retrieve a full conversation:

  1. List users to find the user you're interested in
  2. List sessions filtered by userId to find their conversations
  3. List messages filtered by sessionId to read the full conversation
GET /Dev/{chatbotId}/users
→ pick a userId

GET /Dev/{chatbotId}/sessions?userId={userId}
→ pick a sessionId

GET /Dev/{chatbotId}/messages?sessionId={sessionId}
→ full conversation

Error Codes

Status CodeDescription
401Invalid API key or signature
403API key doesn't have access to the specified chatbot
404Message not found
500Internal server error