The Sensay API provides access to conversation data and messages through specialized endpoints that use cursor-based pagination for efficient navigation through large message histories.
Conversation mentions
The mentions endpoint allows you to retrieve conversation messages grouped into "mention groups" (containing assistant replies and context) and "placeholder groups" (representing collapsed user-only messages).
Conversation messages
The messages endpoint allows you to retrieve conversation messages. This is useful for expanding placeholders received from the mentions endpoint.
Cursor-based pagination
Conversation endpoints use cursor-based pagination with unique identifiers (UUIDs) to navigate through datasets. This approach is efficient for large datasets and handles concurrent changes gracefully.
Parameters
limit
: Number of items to fetch (1-100)beforeUUID
: Return items before this UUID (excluding the UUID itself)afterUUID
: Return items after this UUID (excluding the UUID itself)
Basic usage
Get the first page (latest mentions):
curl -X GET "https://api.sensay.io/v1/replicas/{replicaUUID}/conversations/{conversationUUID}/mentions?limit=20" \
-H "X-ORGANIZATION-SECRET: $ORGANIZATION_SECRET" \
-H "X-API-Version: $API_VERSION" \
-H "Content-Type: application/json"
Response:
{
"success": true,
"items": [
{
"type": "message",
"uuid": "03db5651-cb61-4bdf-9ef0-89561f7c9c53",
"content": "Hello, how are you?",
"role": "user",
"createdAt": "2024-09-24T09:09:55.66709+00:00",
"source": "web",
"replicaUUID": "f0e4c2f7-ae27-4b35-89bf-7cf729a73687"
},
{
"type": "message",
"uuid": "04ea3f1b-df72-4c98-a8f1-2ef820b5c94d",
"content": "I'm doing well, thank you for asking!",
"role": "assistant",
"createdAt": "2024-09-24T09:10:15.33421+00:00",
"source": "web",
"replicaUUID": "f0e4c2f7-ae27-4b35-89bf-7cf729a73687"
},
{
"type": "placeholder",
"count": 15
}
]
}
Navigation
Get the next page (older mentions):
# Use the UUID of the last message from the previous response
curl -X GET "https://api.sensay.io/v1/replicas/{replicaUUID}/conversations/{conversationUUID}/mentions?limit=20&beforeUUID=03db5651-cb61-4bdf-9ef0-89561f7c9c53" \
-H "X-ORGANIZATION-SECRET: $ORGANIZATION_SECRET" \
-H "X-API-Version: $API_VERSION" \
-H "Content-Type: application/json"
Get newer mentions:
# Use the UUID of the first message from the current page
curl -X GET "https://api.sensay.io/v1/replicas/{replicaUUID}/conversations/{conversationUUID}/mentions?limit=20&afterUUID=ec46b4db-3f0d-4392-b0f5-9fe327922e8a" \
-H "X-ORGANIZATION-SECRET: $ORGANIZATION_SECRET" \
-H "X-API-Version: $API_VERSION" \
-H "Content-Type: application/json"
Implementation pattern
async function loadNextPage(lastMessageUUID) {
const response = await fetch(
`/mentions?limit=20&beforeUUID=${lastMessageUUID}`
);
return response.json();
}
async function loadPreviousPage(firstMessageUUID) {
const response = await fetch(
`/mentions?limit=20&afterUUID=${firstMessageUUID}`
);
return response.json();
}
// Usage
const firstPage = await fetch('/mentions?limit=20');
const data = await firstPage.json();
// Get the last message UUID for next page
const lastMessage = data.items
.filter(item => item.type === 'message')
.pop();
if (lastMessage) {
const nextPage = await loadNextPage(lastMessage.uuid);
}
Placeholder expansion
Expand a placeholder chronologically before a known message UUID:
# Use the UUID of the first message after the placeholder
curl -X GET "https://api.sensay.io/v1/replicas/{replicaUUID}/conversations/{conversationUUID}/messages?limit=20&beforeUUID=03db5651-cb61-4bdf-9ef0-89561f7c9c53" \
-H "X-ORGANIZATION-SECRET: $ORGANIZATION_SECRET" \
-H "X-API-Version: $API_VERSION" \
-H "Content-Type: application/json"
Expand a placeholder chronologically after a known message UUID:
# Use the UUID of the last message before the placeholder
curl -X GET "https://api.sensay.io/v1/replicas/{replicaUUID}/conversations/{conversationUUID}/mentions?limit=20&afterUUID=ec46b4db-3f0d-4392-b0f5-9fe327922e8a" \
-H "X-ORGANIZATION-SECRET: $ORGANIZATION_SECRET" \
-H "X-API-Version: $API_VERSION" \
-H "Content-Type: application/json"
Implementation pattern
async function expandPlaceholderBefore(firstMessageUUID) {
const response = await fetch(
`/messages?limit=20&afterUUID=${firstMessageUUID}`
);
return response.json();
}
async function expandPlaceholderAfter(lastMessageUUID) {
const response = await fetch(
`/messages?limit=20&afterUUID=${lastMessageUUID}`
);
return response.json();
}
// Usage
const mentions = await fetch('/mentions?limit=20');
const { items } = await mentions.json();
const placeholders = items.reduce((acc, item, ix, array) => {
if (item.type === 'placeholder') {
acc.push({
...item,
nextOlderMessageUUID: array[ix - 1]?.uuid,
nextNewerMessageUUID: array[ix + 1]?.uuid
})
}
return acc;
}, [])
// Expand the most recent placeholder
const messages = await fetch(`/messages?afterUUID=${placeholders[placeholders.length-1].nextOlderMessageUUID}`)
Understanding message types
Message items
Messages represent actual conversation content with full details:
uuid
: Unique identifier for cursor navigationcontent
: The message textrole
: Either "user" or "assistant"createdAt
: Timestamp when the message was createdsource
: Where the message originated (web, telegram, discord, etc.)replicaUUID
: The replica involved in this conversation
Placeholder items
Placeholders represent collapsed groups of messages to improve navigation:
type
: Always "placeholder"count
: Number of messages represented by this placeholder
Placeholders typically represent stretches of user-only messages between assistant interactions, allowing you to focus on the most relevant parts of long conversations.
Best practices
Performance
Choose appropriate limits:
- 10-50 items for UI lists
- Up to 100 for data processing
Cache responses when possible:
- Cursor positions are stable and cache-friendly
- Message content rarely changes once created
Error handling
// Handle invalid cursors
try {
const response = await fetch(`/mentions?beforeUUID=${uuid}`);
if (response.status === 400) {
// UUID doesn't exist in this conversation
// Fall back to loading from the beginning
return fetch('/mentions?limit=20');
}
} catch (error) {
console.error('Conversation pagination error:', error);
}
UI considerations
- Loading states: Always show loading indicators during pagination requests
- Empty states: Handle conversations with no assistant interactions
- Error states: Provide retry mechanisms for failed requests
- Real-time updates: Consider how new messages affect cursor positions