PrimeThink Documentation Help

Data Management API Reference

Overview

Live Pages use a powerful JavaScript library (pt) that provides database-like operations for managing data. The library is automatically initialized and provides simple CRUD operations with server-side filtering.

Complete API Reference

The PrimeThink API provides a complete set of operations for managing entities and chat context:

Operation

Method

Description

Performance

Create

pt.add(entityName, data)

Add new entity

Fast

Read (one)

pt.get(entityId)

Get single entity by ID

Very Fast (Primary Key)

Read (many)

pt.list(options)

Query multiple entities with filters

Fast (Indexed)

Update

pt.edit(entityId, data)

Update existing entity

Fast

Delete

pt.delete(entityId)

Remove entity

Fast

Members

pt.getChatMembers()

Get chat members (users & agents)

Fast

Chat Messages

pt.addMessage(message)

Add text message to chat

Fast

File Upload

pt.uploadFiles(form, message)

Upload files with optional message

Fast

Notifications

pt.sendNotification(userId, title, text)

Send push notification to user

Fast

Document Search

pt.searchDocuments(query, scope)

Search documents and collections using RAG

Fast

Document Read

pt.getDocumentText(docId, options)

Get document text content

Fast

Document Create

pt.saveDocument(filename, format, mimetype, content)

Create and save document

Fast

Available Methods

pt.list(options)

List entities with optional server-side filtering, pagination, and multiple entity types.

Parameters:

  • entityNames: Array of entity types to include (e.g., ['user', 'product'])

  • filters: Object with field-value pairs for server-side filtering

  • limit: Maximum number of results to return (default: 100, max: 1000)

  • offset: Number of results to skip for pagination (default: 0)

  • page: Page number for page-based pagination (1-indexed, mutually exclusive with offset)

  • pageSize: Items per page for page-based pagination (mutually exclusive with limit)

  • returnMetadata: Set to true to return pagination metadata along with entities

Basic Usage:

// List entities with filters const users = await pt.list({ entityNames: ['user', 'product'], filters: { status: 'active', age: { $gte: 18 } }, limit: 10, offset: 0 }); // List multiple entity types const entities = await pt.list({ entityNames: ['task', 'event', 'user'], filters: { status: 'active' } }); // Process results const tasks = entities.filter(e => e.entity_name === 'task'); const events = entities.filter(e => e.entity_name === 'event'); const users = entities.filter(e => e.entity_name === 'user');

Response Structure:

// Without metadata (default) [ { id: 123, entity_name: 'task', data: { text: 'Buy groceries', completed: false }, creator_user_id: 456, created_at: '2024-03-15T10:30:00+00:00', updated_at: '2024-03-15T10:35:00+00:00' }, // ... more entities ] // With metadata (returnMetadata: true) { entities: [...], // Array of entity objects count: 20, // Number of items in this response pagination: { limit: 20, // Items requested offset: 40, // Starting position has_more: true, // true if full page returned (more likely exists) page: 3, // Current page (if page-based) page_size: 20 // Items per page (if page-based) } }

pt.get(entityId)

Retrieve a single entity by its ID. This method performs a direct primary key lookup, which is much faster and more semantic than using pt.list() with filters.

Parameters:

  • entityId: Numeric ID of the entity to retrieve

Usage:

// Get entity by ID const task = await pt.get(123); console.log(task.data.text); console.log(task.created_at); // Get and edit pattern const task = await pt.get(123); await pt.edit(123, { ...task.data, completed: !task.data.completed });

Error Handling:

try { const task = await pt.get(123); console.log('Found:', task.data); } catch (error) { console.error('Entity not found or unauthorized:', error); }

When to use pt.get():

  • When you know the entity ID

  • For direct lookups (much faster than filtering)

  • Before editing an entity to get current state

pt.add(entityName, data)

Create a new entity.

Parameters:

  • entityName: String identifying the entity type

  • data: Object containing the entity data

Usage:

// Add a task const result = await pt.add('task', { text: 'Buy groceries', completed: false }); // Add an event const event = await pt.add('event', { title: 'Team Meeting', date: '2024-03-20', time: '14:00', description: 'Weekly sync' }); // The creator_user_id is automatically set to the current user console.log(result.creator_user_id); // Automatically populated

Important Notes:

  • created_at and updated_at are automatically managed

  • creator_user_id is automatically set to the current user

  • Don't include these fields in your data object

pt.edit(entityId, data)

Update an existing entity. This method replaces all data in the entity.

Parameters:

  • entityId: Numeric ID of the entity to update

  • data: Object containing the new entity data

Usage:

// Get current data first const task = await pt.get(taskId); // Update with merged data const updated = await pt.edit(taskId, { ...task.data, completed: true }); // Toggle a field async function toggleTaskCompletion(taskId) { const task = await pt.get(taskId); await pt.edit(taskId, { ...task.data, completed: !task.data.completed }); }

Warning: Always merge with existing data unless you want to replace all fields:

// ❌ BAD: This removes all other fields await pt.edit(123, { completed: true }); // ✅ GOOD: This preserves other fields const task = await pt.get(123); await pt.edit(123, { ...task.data, completed: true });

pt.delete(entityId)

Remove an entity from the database.

Parameters:

  • entityId: Numeric ID of the entity to delete

Usage:

// Simple delete async function deleteTask(taskId) { try { await pt.delete(taskId); console.log('Task deleted successfully'); } catch (error) { console.error('Error deleting task:', error); } } // Delete with confirmation async function deleteTaskSafely(taskId) { try { const task = await pt.get(taskId); if (confirm(`Delete task: "${task.data.text}"?`)) { await pt.delete(taskId); console.log('Task deleted successfully'); } } catch (error) { alert('Task not found or already deleted'); } } // Bulk delete async function bulkDeleteTasks(taskIds) { const results = []; for (const id of taskIds) { try { await pt.delete(id); results.push({ id, success: true }); } catch (error) { results.push({ id, success: false, error: error.message }); } } return results; }

pt.getChatMembers()

Get all members of the current chat (users and AI agents).

Returns: Array of member objects with a simplified, clear structure. Each member is either a user or an AI agent.

Response Structure:

[ { "id": 123, // Member ID (either user_id or agent_id) "type": "user", // "user" or "agent" "name": "John Doe", // Display name (full name for users, agent name for agents) // User-only fields (null for agents): "first_name": "John", "last_name": "Doe", "email": "john@example.com", "is_owner": true // Created the chat }, { "id": 456, "type": "agent", "name": "AI Assistant", // User fields are null for agents "first_name": null, "last_name": null, "email": null, "is_owner": false } ]

Field Reference:

Field

Type

User

Agent

Description

id

number

Member ID

type

string

"user" or "agent"

name

string

Display name (full name or agent name)

first_name

string?

null

First name

last_name

string?

null

Last name

email

string?

null

Email address

is_owner

boolean

Created the chat

Usage Examples:

// Get and display all members const members = await pt.getChatMembers(); members.forEach(member => { const icon = member.type === 'user' ? '👤' : '🤖'; console.log(`${icon} ${member.name}`); }); // Filter by type const users = members.filter(m => m.type === 'user'); const agents = members.filter(m => m.type === 'agent'); console.log(`Users: ${users.length}, Agents: ${agents.length}`); // Create task assignment dropdown (users only) async function createAssigneeDropdown() { const members = await pt.getChatMembers(); const users = members.filter(m => m.type === 'user'); const options = users .map(m => `<option value="${m.id}">${m.name}</option>`) .join(''); return ` <select id="assignee"> <option value="">Unassigned</option> ${options} </select> `; } // Get current user const members = await pt.getChatMembers(); const currentUser = members.find(m => m.type === 'user' && m.is_owner);

pt.initDb()

Initialize the database for the current group. This is usually called automatically, but can be called manually if needed.

Usage:

await pt.initDb();

pt.reload()

Reload the current Live Page.

Usage:

// Reload the page pt.reload(); // Example: Reload after a major update async function refreshApplication() { await pt.initDb(); pt.reload(); }

pt.navigate(chatId)

Navigate to a different Live Page.

Parameters:

  • chatId: ID of the chat/Live Page to navigate to

Usage:

// Navigate to another Live Page pt.navigate(456); // Example: Navigation menu function createNavigation(livePages) { return livePages.map(page => ` <button onclick="pt.navigate(${page.id})"> ${page.title} </button> `).join(''); }

pt.addMessage(message)

Add a text message to the current chat from your Live Page. This allows your Live Page to communicate back to the chat interface.

Parameters:

  • message: String containing the message text to send

Returns: Promise that resolves to an object containing:

  • message_id: ID of the created message

  • chat_id: ID of the chat

  • created_at: Timestamp when the message was created

Usage:

// Send a simple text message async function sendNotification() { try { const result = await pt.addMessage('Task completed successfully!'); console.log('Message sent with ID:', result.message_id); } catch (error) { console.error('Error sending message:', error); } } // Send message from user input async function sendUserMessage() { const input = document.getElementById('messageInput'); const message = input.value.trim(); if (!message) { alert('Please enter a message'); return; } try { await pt.addMessage(message); input.value = ''; // Clear input alert('Message sent!'); } catch (error) { alert('Failed to send message: ' + error.message); } } // Send notification after an action async function completeTask(taskId) { const task = await pt.get(taskId); await pt.edit(taskId, { ...task.data, completed: true }); // Notify the chat await pt.addMessage(`Task "${task.data.text}" has been completed!`); }

Common Use Cases:

  • Notify users when an action is completed

  • Send alerts or warnings

  • Provide feedback from form submissions

  • Log important events to the chat

  • Create interactive chat-based workflows

AI-Powered Database Operations:

When you send a message to the chat, the AI assistant can process your instructions and automatically manage database entities. This enables powerful automation workflows where you describe what you want, and the AI handles the database operations.

Best Practice: Be Explicit About Tool Usage

To ensure the AI executes your desired operation, explicitly mention which database tool to use:

  • Use chatdb_add to create new entities

  • Use chatdb_list to search/query entities

  • Use chatdb_get to retrieve a specific entity by ID

  • Use chatdb_edit to update existing entities

  • Use chatdb_delete to remove entities

// Example 1: Extract data and store it (explicit tool usage) await pt.addMessage(` Please analyze the sales data from last quarter and use the tool 'chatdb_add' to create database entries: - entity_name: "sales_record" - data format: { month: string, revenue: number, region: string, growth_percentage: number } Extract all quarterly sales information and add each month as a separate record. `); // Example 2: Process and categorize information (explicit tool usage) await pt.addMessage(` Search for the top 5 competitors in the AI assistant market and use the tool 'chatdb_add' to store each one: - entity_name: "competitor" - data: { name: string, website: string, key_features: array, pricing_model: string } `); // Example 3: Query and transform existing data await pt.addMessage(` Use 'chatdb_list' to find all tasks with status "pending" and high priority. For each one, use 'chatdb_add' to create a new entity: - entity_name: "urgent_action" - data: { task_id: number, title: string, due_date: string, estimated_hours: number } `); // Example 4: Update existing entities await pt.addMessage(` Use 'chatdb_list' to find all expenses from last month with category "uncategorized". For each expense, use 'chatdb_edit' to update it with the appropriate category based on the merchant name. `); // Example 5: Clean up old data await pt.addMessage(` Use 'chatdb_list' to find all tasks with status "completed" that were finished more than 90 days ago. Use 'chatdb_delete' to remove them from the database. `);

Available Database Tools:

Tool

Purpose

When to Use

chatdb_add

Create new entities

Storing new data, adding records

chatdb_list

Query/search entities

Finding records with filters, getting multiple items

chatdb_get

Get single entity by ID

Retrieving a specific record when you know its ID

chatdb_edit

Update existing entities

Modifying data, changing status, updating fields

chatdb_delete

Remove entities

Cleaning up, removing old data

chatdb_init

Initialize database schema

First-time setup (rarely needed)

This feature is particularly powerful because:

  • The AI understands natural language instructions

  • It can process complex requirements and extract structured data

  • Explicit tool mentions ensure the correct operations are executed

  • It handles the database operations automatically

  • You can combine data processing with storage in one request

pt.uploadFiles(formOrFormData, message)

Upload files from your Live Page to the chat with an optional text message. The files are processed and attached to the chat.

Parameters:

  • formOrFormData: Either an HTML <form> element or a FormData object containing files

  • message: Optional string message to include with the upload

Returns: Promise that resolves to an object containing:

  • message: Success message

  • files_count: Number of files uploaded

  • chat_id: ID of the chat

Usage:

Example 1: Upload from HTML Form

<form id="uploadForm" onsubmit="handleUpload(event)"> <input type="file" name="files" multiple required> <input type="text" name="message" placeholder="Optional message..."> <button type="submit">Upload Files</button> </form> <script> async function handleUpload(event) { event.preventDefault(); const form = event.target; try { const result = await pt.uploadFiles(form); alert(`Uploaded ${result.files_count} file(s) successfully!`); form.reset(); } catch (error) { alert('Upload failed: ' + error.message); } } </script>

Example 2: Programmatic Upload with FormData

// Upload files with custom message async function uploadFilesWithMessage() { const fileInput = document.getElementById('fileInput'); if (fileInput.files.length === 0) { alert('Please select files'); return; } const formData = new FormData(); // Add all selected files for (const file of fileInput.files) { formData.append('files', file); } try { const result = await pt.uploadFiles( formData, 'Uploaded files from Live Page' ); alert(`Success! Uploaded ${result.files_count} files`); } catch (error) { alert('Error: ' + error.message); } }

Example 3: Drag and Drop Upload

<div id="dropZone" ondrop="handleDrop(event)" ondragover="event.preventDefault()" class="border-2 border-dashed p-8 text-center" > Drop files here to upload </div> <script> async function handleDrop(event) { event.preventDefault(); const files = event.dataTransfer.files; if (files.length === 0) return; const formData = new FormData(); for (const file of files) { formData.append('files', file); } try { const result = await pt.uploadFiles(formData, 'Files uploaded via drag & drop'); alert(`Uploaded ${result.files_count} file(s)`); } catch (error) { console.error('Upload error:', error); } } </script>

Important Notes:

  • Files are processed through the existing message processing system

  • Uploaded files are automatically attached to the chat

  • Supports multiple file uploads in a single request

  • File size limits and restrictions apply based on system configuration

  • Authentication and rate limiting are automatically handled

Common Use Cases:

  • Document upload forms

  • Image galleries with upload

  • File attachment for support tickets

  • Batch file processing interfaces

  • Report generation and upload

AI-Powered File Processing with Database Storage:

When you upload files with instructions, the AI can process the files and automatically store extracted information in the database. This is incredibly powerful for automating data entry, document processing, and information extraction.

// Example 1: Extract structured data from invoices const formData = new FormData(); formData.append('files', invoiceFile); await pt.uploadFiles(formData, ` Please extract invoice information from the uploaded file and use the tool 'chatdb_add' to create database records: - entity_name: "invoice" - data format: { invoice_number: string, date: string, vendor: string, amount: number, due_date: string, line_items: array of {item: string, quantity: number, price: number} } `); // Example 2: Process multiple resumes and extract candidate info const formData = new FormData(); for (const file of resumeFiles) { formData.append('files', file); } await pt.uploadFiles(formData, ` Extract candidate information from each resume and use the tool 'chatdb_add' to create entries: - entity_name: "candidate" - data: { name: string, email: string, phone: string, years_experience: number, skills: array, education: string, previous_companies: array } `); // Example 3: Analyze meeting recordings and create action items await pt.uploadFiles(formData, ` Transcribe the meeting recording and extract all action items. For each action item, use the tool 'chatdb_add' to create: - entity_name: "action_item" - data: { description: string, assigned_to: string, due_date: string, priority: "high" | "medium" | "low", mentioned_at_timestamp: string } `); // Example 4: Process expense receipts await pt.uploadFiles(formData, ` Extract expense information from the receipt images and use the tool 'chatdb_add' to store each as: - entity_name: "expense" - data: { date: string, merchant: string, category: string, amount: number, currency: string, description: string } `); // Example 5: Import customer data from spreadsheets await pt.uploadFiles(formData, ` Parse the customer data spreadsheet and use the tool 'chatdb_add' to create database entries: - entity_name: "customer" - data: { customer_id: string, company_name: string, contact_person: string, email: string, phone: string, industry: string, contract_value: number, renewal_date: string } Skip any rows with missing required fields and create a summary of imported vs skipped records. `); // Example 6: Update existing records based on uploaded data await pt.uploadFiles(formData, ` Parse the uploaded spreadsheet containing updated customer information. Use 'chatdb_list' to find matching customers by customer_id. Use 'chatdb_edit' to update each customer record with the new information. Provide a summary of how many records were updated. `);

How It Works:

  1. You upload files using pt.uploadFiles()

  2. Include clear instructions in the message parameter

  3. Specify the entity name and data structure you want

  4. The AI processes the files, extracts information, and stores it automatically

  5. The AI can validate data, handle errors, and provide feedback

Benefits:

  • Automate tedious data entry tasks

  • Extract structured data from unstructured files

  • Process multiple files in batch

  • Combine file analysis with database storage

  • Get intelligent parsing with error handling

pt.sendNotification(userId, title, text)

Send push notifications to specific users in the chat.

Parameters:

  • userId (number, required): The ID of the user to notify

  • title (string, required): Notification title

  • text (string, required): Notification message text

Returns: Promise that resolves to an object with message field indicating success

Usage:

// Send notification to a specific user const members = await pt.getChatMembers(); const targetUser = members.find(m => m.email === 'john@example.com'); await pt.sendNotification( targetUser.id, 'Task Assigned', 'You have been assigned a new task' ); // Send notification after task assignment async function assignTask(taskId, userId) { const task = await pt.get(taskId); await pt.edit(taskId, { ...task.data, assigned_to: userId }); // Notify the user await pt.sendNotification( userId, 'New Task', `You've been assigned: ${task.data.title}` ); } // Notify user when task is completed async function completeTask(taskId) { const task = await pt.get(taskId); await pt.edit(taskId, { ...task.data, completed: true }); if (task.data.assigned_to) { await pt.sendNotification( task.data.assigned_to, 'Task Completed', `Task "${task.data.title}" has been marked as complete` ); } }

Common Use Cases:

  • Task assignment notifications

  • Alert users about important updates

  • Remind users of pending actions

  • Notify collaborators of changes

pt.searchDocuments(query, scope)

Perform semantic search across documents and collections using RAG (Retrieval-Augmented Generation).

Parameters:

  • query (string, required): Natural language search query

  • scope (string, optional): Search scope - "ALL", "DOCUMENTS_ONLY", or "COLLECTIONS_ONLY" (default: "ALL")

Returns: Promise that resolves to an object with results field containing XML-formatted search results

Usage:

// Search all documents and collections const result = await pt.searchDocuments('quarterly financial results Q3 2024'); console.log(result.results); // Search only documents const docsOnly = await pt.searchDocuments('project requirements', 'DOCUMENTS_ONLY'); // Search only collections const collectionsOnly = await pt.searchDocuments('company policies', 'COLLECTIONS_ONLY'); // Build a search interface async function searchKnowledgeBase(query) { try { const result = await pt.searchDocuments(query); displaySearchResults(result.results); } catch (error) { console.error('Search failed:', error); } } // Search with user input async function handleSearch() { const query = document.getElementById('searchInput').value; const scope = document.getElementById('scopeSelect').value; if (!query) { alert('Please enter a search query'); return; } const results = await pt.searchDocuments(query, scope); document.getElementById('resultsArea').textContent = results.results; }

Common Use Cases:

  • Knowledge base search

  • Find relevant documents

  • Research and discovery

  • Content recommendation

pt.getDocumentText(docId, options)

Retrieve the text content from a document.

Parameters:

  • docId (number, required): Document ID

  • options (object, optional): Options object with:

    • from (number): Start character position (default: 0)

    • to (number): End character position (default: null for full text)

Returns: Promise that resolves to an object with text field containing the document content

Usage:

// Get full document text const doc = await pt.getDocumentText(123); console.log(doc.text); // Get first 1000 characters (preview) const preview = await pt.getDocumentText(123, { from: 0, to: 1000 }); console.log(preview.text); // Get text starting from character 500 const partial = await pt.getDocumentText(123, { from: 500 }); console.log(partial.text); // Build a document viewer async function viewDocument(docId) { try { const result = await pt.getDocumentText(docId); if (result.text) { document.getElementById('documentContent').textContent = result.text; } else { alert(result.message || 'No text available'); } } catch (error) { console.error('Error loading document:', error); } } // Load document preview async function loadPreview(docId) { const preview = await pt.getDocumentText(docId, { to: 500 }); document.getElementById('preview').textContent = preview.text + '...'; }

Common Use Cases:

  • Document preview

  • Content analysis

  • Text extraction

  • Partial content loading for large documents

pt.saveDocument(filename, format, mimetype, content)

Create and save content as a document in the chat.

Parameters:

  • filename (string, required): Filename with extension

  • format (string, required): Format type - "TXT", "MD", "HTML", "DOCX", "PDF", "CSV", "XLSX", or "CUSTOM"

  • mimetype (string, required): MIME type (e.g., "text/plain", "application/pdf")

  • content (string, required): Document content

Format Guidelines:

  • TXT: Plain text (no Markdown)

  • MD/MARKDOWN: Markdown text

  • HTML: HTML content (not Markdown)

  • DOCX: Use Markdown text (will be converted to Word format)

  • PDF: Use Markdown text (will be converted to PDF)

  • CSV: Plain CSV format text

  • XLSX: Plain CSV format text (will be converted to Excel)

  • CUSTOM: Any non-binary plain text format

Returns: Promise that resolves to an object with filename field and success status

Usage:

// Save a plain text document await pt.saveDocument( 'notes.txt', 'TXT', 'text/plain', 'These are my meeting notes from today.' ); // Save a Markdown document await pt.saveDocument( 'report.md', 'MD', 'text/markdown', '# Project Report\n\n## Summary\n\nThe project is progressing well.' ); // Save as Word document (using Markdown) await pt.saveDocument( 'proposal.docx', 'DOCX', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', '# Business Proposal\n\n## Executive Summary\n\nThis proposal outlines...' ); // Save as PDF (using Markdown) await pt.saveDocument( 'invoice.pdf', 'PDF', 'application/pdf', '# Invoice #12345\n\n**Date:** 2025-01-15\n**Amount:** $1,250.00' ); // Save CSV data await pt.saveDocument( 'data.csv', 'CSV', 'text/csv', 'Name,Email,Age\nJohn Doe,john@example.com,30\nJane Smith,jane@example.com,28' ); // Generate and save a report async function generateReport(data) { const content = `# Monthly Report ## Summary Total items: ${data.length} ## Details ${data.map(item => `- ${item.name}: ${item.value}`).join('\n')} `; await pt.saveDocument( 'monthly-report.pdf', 'PDF', 'application/pdf', content ); alert('Report generated successfully!'); } // Helper function for common MIME types function getMimeType(format) { const types = { 'TXT': 'text/plain', 'MD': 'text/markdown', 'HTML': 'text/html', 'DOCX': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'PDF': 'application/pdf', 'CSV': 'text/csv', 'XLSX': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }; return types[format] || 'text/plain'; } // Save with helper await pt.saveDocument('report.pdf', 'PDF', getMimeType('PDF'), content);

MIME Type Reference:

  • Plain text: text/plain

  • Markdown: text/markdown

  • HTML: text/html

  • Word: application/vnd.openxmlformats-officedocument.wordprocessingml.document

  • PDF: application/pdf

  • CSV: text/csv

  • Excel: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet

Common Use Cases:

  • Report generation

  • Export data to various formats

  • Create documentation

  • Save user-generated content

  • Generate invoices and forms

Entity Structure

All entities follow this consistent structure:

{ // System fields (managed automatically) id: 123, // Unique entity ID entity_name: 'task', // Type of entity creator_user_id: 456, // User ID who created this entity created_at: '2024-03-15T10:30:00+00:00', // Auto-managed updated_at: '2024-03-15T10:35:00+00:00', // Auto-managed // Your data (in the 'data' property) data: { text: 'Buy groceries', completed: false, priority: 'high', // ... any custom fields } }

System-Managed Fields:

  • id: Unique identifier for the entity

  • entity_name: Type/category of the entity

  • creator_user_id: ID of the user who created the entity (automatic)

  • created_at: Timestamp when entity was created (automatic)

  • updated_at: Timestamp when entity was last updated (automatic)

Important:

  • Never add created_at, updated_at, or creator_user_id to your data object

  • These fields are managed at the entity level, not in your data

  • Your custom fields go inside the data object

Best Practices

1. Use pt.get() for Single Entities

When you know the entity ID, always use pt.get() instead of pt.list() with filters:

// ✅ GOOD: Fast primary key lookup const task = await pt.get(123); // ❌ AVOID: Slower filtering when ID is known const tasks = await pt.list({ entityNames: ['task'], filters: { id: 123 } }); const task = tasks[0];

2. Always Merge Data When Editing

// ✅ GOOD: Preserve existing fields const task = await pt.get(taskId); await pt.edit(taskId, { ...task.data, completed: true }); // ❌ BAD: Lose all other fields await pt.edit(taskId, { completed: true });

3. Handle Errors Gracefully

async function robustOperation() { try { const entity = await pt.get(123); return entity; } catch (error) { console.error('Operation failed:', error); return null; } }

4. Cache getChatMembers() Results

// ✅ GOOD: Cache members at app initialization let allMembers = []; async function initApp() { allMembers = await pt.getChatMembers(); await loadTasks(); } function getMemberName(userId) { const member = allMembers.find(m => m.id === userId); return member ? member.name : 'Unknown'; } // ❌ AVOID: Calling getChatMembers() repeatedly async function displayTask(task) { const members = await pt.getChatMembers(); // Called for every task! const creator = members.find(m => m.id === task.creator_user_id); return creator.name; }

5. Use Appropriate Limits

// ✅ GOOD: Reasonable limits const recentTasks = await pt.list({ entityNames: ['task'], limit: 50 }); // ❌ AVOID: Requesting too much data const allTasks = await pt.list({ entityNames: ['task'], limit: 10000 // Too large });

Performance Tips

  1. Primary key lookups: Use pt.get() when you know the ID (fastest)

  2. Server-side filtering: Use filters in pt.list() instead of client-side filtering

  3. Pagination: Use limit and offset for large datasets

  4. Caching: Cache getChatMembers() and other static data

  5. Batch operations: Use Promise.all() for multiple independent operations

// Batch operations example async function batchUpdate(taskIds, updates) { const promises = taskIds.map(async id => { const task = await pt.get(id); return pt.edit(id, { ...task.data, ...updates }); }); await Promise.all(promises); }

Next Steps

09 November 2025