Introduction
Lerty is a chat interface that lets you deploy AI agents and automation workflows for yourself or an end user. It's also a notification and approval layer — surface alerts from your workflows and let users approve actions directly from their phone or desktop.
Base URL
https://lerty.ai/api/v1
What's an Agent?
You might call it a bot, assistant, workflow, or automation — in Lerty, we call it an Agent. Think of it as the conversation layer that sits between your users and whatever powers the responses, whether that's an AI model, an n8n workflow, a custom backend, or anything else.
Lerty supports two types of agents:
- Custom Agent - Uses built-in LLM providers (Anthropic, OpenAI, Google, Xai, OpenRouter) to handle conversations automatically
- Webhook Agent - Forwards messages to your backend via HTTP webhooks for custom processing (typically used to surface a front end for automations and agents on platforms like n8n, Flowmattic, Make.com, Zapier, Pipedream, etc.)
Authentication
All API requests require authentication using an API key in the Authorization header.
curl -X GET "https://lerty.ai/api/v1/agents" \
-H "Authorization: Bearer ak_your_api_key_here"
Getting an API Key
- Log in to Lerty at lerty.ai
- Go to the Settings of your organization → API Key
- Copy the api key.
Organizations
Organizations are how you group agents, conversations, and team members in Lerty. Every agent belongs to an organization, and you can invite team members to collaborate.
Sharing Access
Invite team members to your organization so they can:
- Chat with agents and receive notifications on their own devices
- Respond to human-in-the-loop approvals and interactive messages
- View conversation history and agent activity
- Manage agents and settings (admin role)
Member Roles
| Role | Permissions |
|---|---|
| Owner | Full access including billing, can delete organization |
| Admin | Manage agents, organization settings, and invite members |
| Member | Chat with agents, respond to approvals and interactive messages |
Custom Agent
Custom Agents use Lerty's built-in LLM integrations to automatically respond to messages. Agents can be configured with a system prompt to give your agent instructions and you can surface MCP server tools to your agents.
Supported Providers
| Provider | Models | Best For |
|---|---|---|
| Anthropic | Claude | Complex reasoning, long context, best for MCP Servers |
| OpenAI | ChatGPT | General purpose, fast responses |
| OpenRouter | 100+ models | Model variety, cost optimization, access unique models |
Webhook Agent
Webhook Agents forward user messages to your backend or automation platform via HTTP webhooks. Use this to connect Lerty to n8n, Make.com, Zapier, FlowMattic, Pipedream, or any custom backend.
How It Works
- User sends a message in Lerty
- Lerty POSTs the message to your webhook URL
- Your automation or backend processes the message
- Your workflow calls Lerty's API to send a response
- The user sees the response in real-time
Example Use Cases
- n8n workflow that queries a database and responds with results
- Make.com scenario that creates tickets in your helpdesk
- Custom backend that routes to different AI models based on intent
Webhook Payload
{
"event": "message.created",
"conversationId": "conv-uuid-here",
"messageId": "msg-uuid-here",
"agentId": "agent-uuid-here",
"content": "Hello, I need help",
"userId": "user-uuid-here",
"userEmail": "user@example.com",
"timestamp": "2024-01-15T10:30:00Z"
}
Agents
Retrieve agent configuration, update webhook URLs, and manage agent settings.
/api/v1/agents
List all agents
Query Parameters
detailed
Optional
| Name | Type | Required | Description |
|---|---|---|---|
detailed |
boolean | No | Include detailed agent information |
curl -X GET "https://lerty.ai/api/v1/agents?detailed=true" \
-H "Authorization: Bearer YOUR_API_KEY"
{
"agents": [
{
"id": "agent-uuid-here",
"name": "Support Bot",
"status": "active",
"protocol": "webhook",
"webhook_url": "https://your-server.com/webhook"
}
]
}
/api/v1/agents/:id
Get a specific agent
Query Parameters
detailed
Optional
| Name | Type | Required | Description |
|---|---|---|---|
detailed |
boolean | No | Include detailed agent information |
curl -X GET "https://lerty.ai/api/v1/agents/AGENT_ID?detailed=true" \
-H "Authorization: Bearer YOUR_API_KEY"
/api/v1/agents/:id
Update agent configuration
Body Parameters
name
Optional
webhook_url
Optional
enabled
Optional
test_mode
Optional
| Name | Type | Required | Description |
|---|---|---|---|
name |
string | No | Agent name |
webhook_url |
string | No | Webhook URL for messages |
enabled |
boolean | No | Enable or disable the agent |
test_mode |
boolean | No | Use test webhook URL |
curl -X PATCH "https://lerty.ai/api/v1/agents/AGENT_ID" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"webhook_url": "https://your-new-webhook.com/handle", "enabled": true}'
{
"success": true,
"agent": {
"id": "agent-uuid-here",
"name": "Support Bot",
"webhook_url": "https://your-new-webhook.com/handle",
"enabled": true
}
}
/api/v1/agents/:id/connection-info
Get agent connection information
Get webhook URLs, API endpoints, and conversation list for an agent
curl -X GET "https://lerty.ai/api/v1/agents/AGENT_ID/connection-info" \
-H "Authorization: Bearer YOUR_API_KEY"
{
"connection_info": {
"agent_id": "agent-uuid-here",
"agent_name": "Support Bot",
"webhook_url": "https://your-server.com/webhook",
"protocol": "webhook",
"conversations": [...],
"api_endpoints": {
"send_message": "https://lerty.ai/api/v1/agents/{id}/messages",
"create_conversation": "https://lerty.ai/api/v1/agents/{id}/conversations/create"
}
}
}
Conversations
A conversation is a thread between your agent and a user. Create conversations programmatically to start new threads from your backend.
/api/v1/agents/:agent_id/conversations/create
Create a new conversation
Body Parameters
title
Optional
user_id
Optional
| Name | Type | Required | Description |
|---|---|---|---|
title |
string | No | Conversation title |
user_id |
string | No | UUID of a user in your organization. If provided, the conversation is created on behalf of this user. The user must belong to the same organization as the API key. |
curl -X POST "https://lerty.ai/api/v1/agents/AGENT_ID/conversations/create" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"title": "Support Request", "user_id": "USER_UUID"}'
{
"success": true,
"conversation": {
"id": "conv-uuid-here",
"user_id": "user-uuid-here",
"agent_id": "agent-uuid-here",
"title": "Support Request",
"status": "active",
"created_at": "2024-01-15T10:30:00Z"
}
}
/api/v1/agents/:agent_id/conversations
List conversations for an agent
curl -X GET "https://lerty.ai/api/v1/agents/AGENT_ID/conversations" \
-H "Authorization: Bearer YOUR_API_KEY"
Messages
Send messages into conversations. For Webhook Agents, use the
originate
endpoint to send responses back to users.
/api/v1/conversations/:conversation_id/messages
Send a user message
Body Parameters
content
Required
| Name | Type | Required | Description |
|---|---|---|---|
content |
string | Yes | Message content |
curl -X POST "https://lerty.ai/api/v1/conversations/CONV_ID/messages" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"content": "Hello, I need help"}'
/api/v1/conversations/:conversation_id/originate
Send an agent message (Webhook Agents)
Use this endpoint to send agent responses back to users when using Webhook Agents.
Body Parameters
content
Required
role
Required
external_message_id
Optional
| Name | Type | Required | Description |
|---|---|---|---|
content |
string | Yes | Message text (supports markdown) |
role |
string | Yes | Must be "assistant" |
external_message_id |
string | No | Unique ID for deduplication |
curl -X POST "https://lerty.ai/api/v1/conversations/CONV_ID/originate" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"content": "Hi! How can I help you today?", "role": "assistant", "external_message_id": "msg-12345"}'
{
"success": true,
"message": {
"id": "msg-uuid-here",
"content": "Hi! How can I help you today?",
"role": "assistant"
}
}
{
"error": "duplicate_message",
"message": "Message with this external_message_id already exists"
}
Interactive Messages
Interactive messages enable human-in-the-loop workflows — collect approvals, gather structured input, or present choices before your automation proceeds. Perfect for expense approvals, confirmation dialogs, data collection forms, and any workflow that needs human oversight.
Example Use Cases
- Manager approves expense before n8n workflow processes payment
- User confirms shipping address before order is placed
- Team lead selects priority level for incoming support ticket
- Employee submits PTO request form, HR approves in Lerty
How It Works
- Your workflow sends an interactive message to a conversation via the API
- The user sees the interactive UI (buttons, form, or approval prompt) in Lerty
- When the user responds, Lerty POSTs the response to your callback URL
- Your workflow receives the callback and continues processing
Action Types
Each interactive message requires exactly one action element:
approved
(true/false), message
selection
(button value)
data
object with field values
| Type | Description | Callback Data |
|---|---|---|
| Boolean | Approve/Reject buttons with optional message field |
approved
(true/false), message
|
| Buttons | Multiple choice — user picks one option |
selection
(the button's value)
|
| Fields | Form with text, number, email, date inputs |
data
object with field name→value pairs
|
/api/v1/conversations/:conversation_id/interactive
Send an interactive message
Body Parameters
callback_url
Required
callback_id
Required
elements
Required
| Name | Type | Required | Description |
|---|---|---|---|
callback_url |
string | Yes | URL to receive user's response |
callback_id |
string | Yes | Your unique ID for this interaction |
elements |
array | Yes | UI elements to display |
Element Types
header
Large title text
text
Body text for context
divider
Horizontal line separator
boolean
Approve/Reject buttons with optional message
buttons
Multiple choice options
fields
Full form with multiple inputs
| Type | Description |
|---|---|
header |
Large title text |
text |
Body text for context |
divider
|
Horizontal line separator |
boolean
|
Approve/Reject buttons with optional message |
buttons
|
Multiple choice options |
fields |
Full form with multiple inputs |
curl -X POST "https://lerty.ai/api/v1/conversations/CONV_ID/interactive" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"callback_url": "https://your-server.com/callback", "callback_id": "approval-001", "elements": [{"type": "header", "text": "Invoice Approval"}, {"type": "text", "text": "Invoice #1234 for $5,000"}, {"type": "boolean"}]}'
curl -X POST "https://lerty.ai/api/v1/conversations/CONV_ID/interactive" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"callback_url": "https://your-server.com/callback", "callback_id": "expense-001", "elements": [{"type": "header", "text": "Submit Expense"}, {"type": "fields", "submit_label": "Submit", "inputs": [{"name": "amount", "label": "Amount ($)", "input_type": "number", "required": true}]}]}'
Callback Response
When the user submits, Lerty POSTs to your callback_url:
{
"callback_id": "approval-001",
"conversation_id": "conv-uuid",
"message_id": "msg-uuid",
"response_type": "boolean",
"approved": true,
"message": "Looks good",
"responded_at": "2024-01-15T10:30:00Z",
"responded_by": {
"user_id": "user-uuid",
"email": "user@example.com"
}
}
{
"callback_id": "expense-001",
"conversation_id": "conv-uuid",
"response_type": "fields",
"data": {
"amount": 500,
"category": "travel",
"date": "2024-01-15"
},
"responded_at": "2024-01-15T10:30:00Z"
}
Typing Indicators
Show users that your agent is processing their message. Useful for longer-running workflows to keep users informed.
/api/agents/:agent_id/callback
Show or hide typing indicator
Path Parameters
agent_id
Required
| Name | Type | Required | Description |
|---|---|---|---|
agent_id |
string | Yes | The agent ID |
Body Parameters
callback_type
Required
conversation_id
Required
data.typing
Required
data.label
Optional
data.show_dots
Optional
data.timeout
Optional
| Name | Type | Required | Description |
|---|---|---|---|
callback_type |
string | Yes | Must be "typing" |
conversation_id |
string | Yes | The conversation ID to show typing indicator in |
data.typing |
boolean | Yes | true to show, false to hide |
data.label |
string | No | Optional text to display with animated shimmer effect (e.g., "Thinking...", "Searching...") |
data.show_dots |
boolean | No | Whether to show animated dots (default: true). Set to false to show only the label. |
data.timeout |
integer | No | Timeout in milliseconds before auto-clear (default: 30000). Use for long-running operations. |
curl -X POST "https://lerty.ai/api/agents/AGENT_ID/callback" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"callback_type": "typing",
"conversation_id": "CONV_ID",
"data": {
"typing": true,
"label": "Thinking...",
"show_dots": true,
"timeout": 60000
}
}'
Organization API
Manage your organization and team members programmatically. The organization is determined automatically from your API key.
organizations:read
for viewing, members:read
and members:write
for member management.
/api/v1/organization
Get organization details
curl -X GET "https://lerty.ai/api/v1/organization" \
-H "Authorization: Bearer YOUR_API_KEY"
{
"organization": {
"id": "org-uuid-here",
"name": "My Company"
}
}
/api/v1/organization/members
List organization members
curl -X GET "https://lerty.ai/api/v1/organization/members" \
-H "Authorization: Bearer YOUR_API_KEY"
{
"members": [
{"id": "user-uuid", "email": "owner@example.com", "role": "owner"},
{"id": "user-uuid-2", "email": "member@example.com", "role": "member"}
]
}
/api/v1/organization/members
Invite a member by email
Body Parameters
email
Required
| Name | Type | Required | Description |
|---|---|---|---|
email |
string | Yes | Email address to invite |
curl -X POST "https://lerty.ai/api/v1/organization/members" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"email": "newuser@example.com"}'
{
"member": {
"id": "user-uuid-new",
"email": "newuser@example.com",
"role": "member"
}
}
/api/v1/organization/members/:user_id
Remove a member
Path Parameters
user_id
Required
| Name | Type | Required | Description |
|---|---|---|---|
user_id |
string | Yes | User ID to remove |
curl -X DELETE "https://lerty.ai/api/v1/organization/members/USER_ID" \
-H "Authorization: Bearer YOUR_API_KEY"
Push Notifications
Send push notifications to users on the Lerty mobile app. Notify users of important events, approvals needed, or updates from your workflows.
/api/push/send
Send push notification to a user
Body Parameters
email
Required
title
Required
body
Required
priority
Optional
sound
Optional
data
Optional
| Name | Type | Required | Description |
|---|---|---|---|
email |
string | Yes | User's email address |
title |
string | Yes | Notification title |
body |
string | Yes | Notification body |
priority |
string | No | critical, high, medium, normal, low |
sound |
string | No | Notification sound |
data |
object | No | Custom data payload |
curl -X POST "https://lerty.ai/api/push/send" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"email": "user@example.com", "title": "New Message", "body": "You have a new message", "priority": "high"}'
{
"success": true,
"email": "user@example.com",
"devices_succeeded": 2,
"devices_failed": 0,
"total_devices": 2
}
/api/push/send/bulk
Send push to multiple users
Body Parameters
recipients
Required
title
Required
body
Required
priority
Optional
| Name | Type | Required | Description |
|---|---|---|---|
recipients |
array | Yes | Array of email addresses |
title |
string | Yes | Notification title |
body |
string | Yes | Notification body |
priority |
string | No | Notification priority |
curl -X POST "https://lerty.ai/api/push/send/bulk" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"recipients": ["user1@example.com", "user2@example.com"], "title": "Announcement", "body": "New features available"}'
/api/push/devices
List user's registered devices
Query Parameters
email
Required
| Name | Type | Required | Description |
|---|---|---|---|
email |
string | Yes | User's email address |
curl -X GET "https://lerty.ai/api/push/devices?email=user@example.com" \
-H "Authorization: Bearer YOUR_API_KEY"
Live Activities
iOS Live Activities display real-time updates on the Lock Screen and Dynamic Island. Perfect for order tracking, workflow progress, and time-sensitive notifications.
POST /api/push/send
with workflow_state
in the data payload. See the Quick Start guide for complete examples.
/api/push/live-activity/update
Update a Live Activity
Body Parameters
notification_id
Required
content_state
Required
event
Optional
priority
Optional
dismissal_date
Optional
| Name | Type | Required | Description |
|---|---|---|---|
notification_id |
string | Yes | ID of the Live Activity notification |
content_state |
object | Yes | Live Activity content (itemTitle, status, progressPercent, etc.) |
event |
string | No | "update" (default) or "end" to dismiss |
priority |
string | No | critical, high, normal, low (low = silent update) |
dismissal_date |
integer | No | Unix timestamp for dismissal (only for end event) |
Content State Fields
itemTitle
Required
itemSubtitle
Optional
status
Required
progressPercent
Required
currentStep
Optional
totalSteps
Optional
lastUpdate
Optional
| Name | Type | Required | Description |
|---|---|---|---|
itemTitle |
string | Yes | Main title displayed |
itemSubtitle |
string | No | Subtitle text |
status |
string | Yes | Current status text |
progressPercent |
integer | Yes | Progress percentage (0-100) |
currentStep |
integer | No | Current step number |
totalSteps |
integer | No | Total steps |
lastUpdate |
integer | No | Unix timestamp (auto-dismiss after 2 min without updates) |
curl -X POST "https://lerty.ai/api/push/live-activity/update" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"notification_id": "notif-123", "content_state": {"itemTitle": "Order Status", "status": "In Transit", "progressPercent": 75}}'
{
"success": true,
"tokens_updated": 1,
"notification_id": "notif-123"
}
curl -X POST "https://lerty.ai/api/push/live-activity/update" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"notification_id": "notif-123", "event": "end", "content_state": {"itemTitle": "Complete", "status": "Delivered", "progressPercent": 100}}'
priority: "low"
for frequent updates to avoid sound/banner spam. Live Activities auto-dismiss after 2 minutes without updates.
Databases
Databases are top-level containers for your data. Each database contains tables, which hold fields and entries.
Required permissions: data.databases:read
for read operations, data.databases:write
for create/update/delete.
/api/v1/databases
List all databases
curl -X GET "https://lerty.ai/api/v1/databases" \
-H "Authorization: Bearer YOUR_API_KEY"
{
"data": [
{
"id": "db_abc123",
"name": "My Database",
"description": "Project tracker",
"color": "#3B82F6",
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:30:00Z"
}
],
"meta": { "total": 1, "limit": 50, "offset": 0 }
}
/api/v1/databases
Create a database
Parameters
name
Required
description
Optional
color
Optional
| Name | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Database name |
description |
string | No | Optional description |
color |
string | No | Hex color code (e.g. #3B82F6) |
curl -X POST "https://lerty.ai/api/v1/databases" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "My Database", "description": "Project tracker", "color": "#3B82F6"}'
{
"data": {
"id": "db_abc123",
"name": "My Database",
"description": "Project tracker",
"color": "#3B82F6",
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:30:00Z"
}
}
/api/v1/databases/:id
Get a database by ID
curl -X GET "https://lerty.ai/api/v1/databases/db_abc123" \
-H "Authorization: Bearer YOUR_API_KEY"
/api/v1/databases/:id
Update a database
curl -X PATCH "https://lerty.ai/api/v1/databases/db_abc123" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Renamed Database"}'
/api/v1/databases/:id
Delete a database
Soft-deletes the database and all its tables. Returns 204 No Content.
curl -X DELETE "https://lerty.ai/api/v1/databases/db_abc123" \
-H "Authorization: Bearer YOUR_API_KEY"
Tables
Tables live inside databases and define a schema through fields. Each table comes with default fields (text, select, date, checkbox) and 3 empty entries.
Required permissions: data.tables:read
for read operations, data.tables:write
for create/update/delete.
/api/v1/databases/:db_id/tables
List tables in a database
curl -X GET "https://lerty.ai/api/v1/databases/db_abc123/tables" \
-H "Authorization: Bearer YOUR_API_KEY"
{
"data": [
{
"id": "tb_xyz789",
"name": "Tasks",
"fields": [
{ "id": "fd_aaa", "name": "Title", "type": "text", "config": {} },
{ "id": "fd_bbb", "name": "Status", "type": "select", "config": {
"options": [
{ "id": "op_111", "label": "To do", "color": "gray" },
{ "id": "op_222", "label": "Done", "color": "green" }
]
}}
],
"created_at": "2025-01-15T10:30:00Z"
}
],
"meta": { "total": 1, "limit": 50, "offset": 0 }
}
/api/v1/databases/:db_id/tables
Create a table
Parameters
name
Required
| Name | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Table name |
curl -X POST "https://lerty.ai/api/v1/databases/db_abc123/tables" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Tasks"}'
/api/v1/tables/:id
Get a table by ID
Returns the table with all its active fields.
/api/v1/tables/:id
Update a table
Update the table name.
/api/v1/tables/:id
Delete a table
Soft-deletes the table and all its entries. Files attached to entries are cleaned up. Returns 204 No Content.
curl -X DELETE "https://lerty.ai/api/v1/tables/tb_xyz789" \
-H "Authorization: Bearer YOUR_API_KEY"
Fields
Fields define the columns/schema of a table. Supported types: text, number, select, date, checkbox, file, formula, url.
Required permissions: data.tables:read
for listing, data.tables:write
for create/update/delete.
/api/v1/tables/:table_id/fields
List fields in a table
/api/v1/tables/:table_id/fields
Create a field
Parameters
name
Required
type
Required
config
Optional
| Name | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Field name |
type |
string | Yes | Field type: text, number, select, date, checkbox, file, formula, url |
config |
object | No | Type-specific config. For select: {"options": [{"label": "...", "color": "..."}]} |
curl -X POST "https://lerty.ai/api/v1/tables/tb_xyz789/fields" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Priority", "type": "select", "config": {"options": [{"label": "High", "color": "red"}, {"label": "Low", "color": "gray"}]}}'
{
"data": {
"id": "fd_ccc",
"name": "Priority",
"type": "select",
"position": 2,
"config": {
"options": [
{ "id": "op_333", "label": "High", "color": "red" },
{ "id": "op_444", "label": "Low", "color": "gray" }
]
},
"created_at": "2025-01-15T10:30:00Z"
}
}
op_
IDs. Use these IDs (not labels) when setting entry values.
/api/v1/fields/:id
Update a field
curl -X PATCH "https://lerty.ai/api/v1/fields/fd_ccc" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Urgency"}'
/api/v1/fields/:id
Delete a field
Soft-deletes the field. Returns 204 No Content.
curl -X DELETE "https://lerty.ai/api/v1/fields/fd_ccc" \
-H "Authorization: Bearer YOUR_API_KEY"
Entries
Entries are rows in a table. Each entry has a values
map where keys are field names or field IDs, and values are the cell data.
"Status") instead
of field IDs (e.g. fd_bbb) everywhere — in values, filters, sorts, and aggregations.
Names are matched case-insensitively. Field IDs still work too. Select option labels: For select and multi-select fields, you can use option labels (e.g.
"To do") instead of option IDs (e.g. op_111).
Required permissions: data.tables:read
for read operations, data.tables:write
for create/update/delete.
/api/v1/tables/:table_id/entries
List entries in a table
Query Parameters
limit
Optional
offset
Optional
sort
Optional
search
Optional
| Name | Type | Required | Description |
|---|---|---|---|
limit |
integer | No | Page size, max 200 (default 50) |
offset |
integer | No | Pagination offset (default 0) |
sort |
string | No | field_name:direction or field_id:direction (e.g. Status:asc) |
search |
string | No | Full-text search across text fields |
curl -X GET "https://lerty.ai/api/v1/tables/tb_xyz789/entries?limit=50&offset=0" \
-H "Authorization: Bearer YOUR_API_KEY"
{
"data": [
{
"id": "en_abc123",
"values": {
"fd_aaa": "Build login page",
"fd_bbb": "op_111"
},
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:30:00Z"
}
],
"meta": { "total": 1, "limit": 50, "offset": 0 }
}
/api/v1/tables/:table_id/entries
Create an entry
Parameters
values
Optional
| Name | Type | Required | Description |
|---|---|---|---|
values |
object | No | Map of field name (or field ID) → value. Select fields accept option labels or option IDs. Omit for an empty entry. |
curl -X POST "https://lerty.ai/api/v1/tables/tb_xyz789/entries" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"values": {"Title": "Build login page", "Status": "To do"}}'
curl -X POST "https://lerty.ai/api/v1/tables/tb_xyz789/entries" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"values": {"fd_aaa": "Build login page", "fd_bbb": "op_111"}}'
/api/v1/entries/:id
Get an entry by ID
/api/v1/entries/:id
Update an entry
Values are merged with existing values — only the fields you include are changed. Use field names or IDs as keys.
curl -X PATCH "https://lerty.ai/api/v1/entries/en_abc123" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"values": {"Status": "Done"}}'
/api/v1/entries/:id
Delete an entry
Soft-deletes the entry and cleans up any attached files. Returns 204 No Content.
/api/v1/tables/:table_id/entries/query
Query entries with filters and sorting
Parameters
filters
Optional
sort
Optional
search
Optional
limit
Optional
offset
Optional
| Name | Type | Required | Description |
|---|---|---|---|
filters |
array | No | Array of {field, op, value}. Field can be a name or ID. Select values accept option labels. |
sort |
array | No | Array of {field, direction}. Field can be a name or ID. Direction: asc or desc |
search |
string | No | Full-text search |
limit |
integer | No | Page size (default 50, max 200) |
offset |
integer | No | Pagination offset |
curl -X POST "https://lerty.ai/api/v1/tables/tb_xyz789/entries/query" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"filters": [{"field": "Status", "op": "is", "value": "To do"}], "sort": [{"field": "Title", "direction": "asc"}], "limit": 50}'
/api/v1/tables/:table_id/entries/bulk
Bulk create, update, and delete entries
Process multiple operations in a single request. Each operation specifies an action (create, update, delete).
curl -X POST "https://lerty.ai/api/v1/tables/tb_xyz789/entries/bulk" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"operations": [{"action": "create", "values": {"Title": "New task"}}, {"action": "update", "id": "en_abc123", "values": {"Status": "Done"}}, {"action": "delete", "id": "en_def456"}]}'
{
"data": {
"total": 3,
"succeeded": 3,
"failed": 0,
"results": [...]
}
}
/api/v1/tables/:table_id/aggregate
Aggregate entries
Compute aggregate functions across entries. Supported: count, sum, avg, min, max.
Parameters
function
Required
field
Optional
| Name | Type | Required | Description |
|---|---|---|---|
function |
string | Yes | Aggregate function: count, distinct_count, sum, avg, min, max |
field |
string | No | Field name or ID to aggregate (required for sum, avg, min, max) |
curl -X POST "https://lerty.ai/api/v1/tables/tb_xyz789/aggregate" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"function": "sum", "field": "Amount"}'
{
"data": {
"function": "count",
"result": 42
}
}
Entry Notes
Entry notes are rich-text documents stored as TipTap JSON. Each entry can have one notes document containing headings, paragraphs, lists, blockquotes, code blocks, and inline formatting.
heading
(with level
1–3), paragraph, bulletList, orderedList, blockquote,
codeBlock
(with language), horizontalRule. Inline marks:
bold, italic, strike, code,
link
(with href
attr).
Marks can be stacked on the same text node. Limits: 50,000 characters (text + link hrefs) and 1 MB total JSON size.
Required permissions: data.tables:read
for read, data.tables:write
for update/append.
/api/v1/entries/:id/notes
Get entry notes
Returns the TipTap JSON notes for an entry. If the entry has no notes, returns null with has_notes: false.
curl -X GET "https://lerty.ai/api/v1/entries/en_abc123/notes" \
-H "Authorization: Bearer YOUR_API_KEY"
{
"data": {
"entry_id": "en_abc123",
"notes": {
"type": "doc",
"content": [
{
"type": "heading",
"attrs": { "level": 1 },
"content": [{ "type": "text", "text": "Meeting Notes" }]
},
{
"type": "paragraph",
"content": [
{ "type": "text", "text": "Discussed the " },
{ "type": "text", "marks": [{ "type": "bold" }], "text": "Q1 roadmap" },
{ "type": "text", "text": " with the team." }
]
}
]
},
"has_notes": true
}
}
/api/v1/entries/:id/notes
Update entry notes
Replaces the entry's notes with a new TipTap JSON document. Pass null to clear notes. Omitting the notes key returns the current notes without changes.
Parameters
notes
Required
| Name | Type | Required | Description |
|---|---|---|---|
notes |
object | null | Yes | TipTap JSON document (must have type: "doc" and content array), or null to clear |
curl -X PATCH "https://lerty.ai/api/v1/entries/en_abc123/notes" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"notes": {"type": "doc", "content": [{"type": "paragraph", "content": [{"type": "text", "text": "Replaced notes content."}]}]}}'
curl -X PATCH "https://lerty.ai/api/v1/entries/en_abc123/notes" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"notes": null}'
/api/v1/entries/:id/notes/append
Append to entry notes
Appends TipTap block nodes to the end of the entry's existing notes. If the entry has no notes, creates a new document. Uses row-level locking for concurrent safety.
Parameters
content
Required
| Name | Type | Required | Description |
|---|---|---|---|
content |
array | Yes | Array of TipTap block nodes to append (e.g. paragraphs, headings, lists) |
curl -X POST "https://lerty.ai/api/v1/entries/en_abc123/notes/append" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"content": [{"type": "paragraph", "content": [{"type": "text", "text": "Appended a new paragraph."}]}]}'
curl -X POST "https://lerty.ai/api/v1/entries/en_abc123/notes/append" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"content": [{"type": "heading", "attrs": {"level": 2}, "content": [{"type": "text", "text": "Update Log"}]}, {"type": "bulletList", "content": [{"type": "listItem", "content": [{"type": "paragraph", "content": [{"type": "text", "marks": [{"type": "bold"}], "text": "Feb 17:"}, {"type": "text", "text": " API integration complete"}]}]}, {"type": "listItem", "content": [{"type": "paragraph", "content": [{"type": "text", "marks": [{"type": "bold"}], "text": "Feb 18:"}, {"type": "text", "text": " Deployed to production"}]}]}]}]}'
Files
Files are uploaded directly to S3 via presigned URLs — file data never passes through the Lerty server.
Every file must be attached to an entry field of type file.
Required permissions: files:read
for list/download, files:write
+ data.tables:write
for upload/confirm/delete.
-
Call
POST /files/uploadwith file metadata — get back a presigned S3 URL and upload token - PUT the file binary directly to the presigned URL
-
Call
POST /files/confirmwith the upload token — the file is verified, recorded, and attached to the entry
/api/v1/files
List all files in the organization
Query Parameters
limit
Optional
offset
Optional
| Name | Type | Required | Description |
|---|---|---|---|
limit |
integer | No | Page size, max 200 (default 50) |
offset |
integer | No | Pagination offset (default 0) |
curl -X GET "https://lerty.ai/api/v1/files?limit=50" \
-H "Authorization: Bearer YOUR_API_KEY"
{
"data": [
{
"id": "file-uuid",
"filename": "report.pdf",
"content_type": "application/pdf",
"size_bytes": 204800,
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:30:00Z"
}
],
"meta": { "total": 1, "limit": 50, "offset": 0 }
}
/api/v1/files/upload
Step 1: Request a presigned upload URL
Parameters
entry_id
Required
field_id
Required
filename
Required
content_type
Required
size_bytes
Required
| Name | Type | Required | Description |
|---|---|---|---|
entry_id |
string | Yes | Entry display ID (e.g. en_abc123) |
field_id |
string | Yes | File field display ID (e.g. fd_xyz) |
filename |
string | Yes | Filename with extension |
content_type |
string | Yes | MIME type (e.g. application/pdf) |
size_bytes |
integer | Yes | File size in bytes |
curl -X POST "https://lerty.ai/api/v1/files/upload" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"entry_id": "en_abc123", "field_id": "fd_file", "filename": "report.pdf", "content_type": "application/pdf", "size_bytes": 204800}'
{
"data": {
"upload_url": "https://s3.amazonaws.com/bucket/key?X-Amz-Signature=...",
"upload_token": "SFMyNTY...",
"upload_headers": { "Content-Type": "application/pdf" },
"expires_in": 3600
}
}
<upload_url>
Step 2: Upload the file to S3
PUT the file binary directly to the presigned URL returned in step 1. Include the Content-Type header.
curl -X PUT "<upload_url from step 1>" \
-H "Content-Type: application/pdf" \
--data-binary @report.pdf
/api/v1/files/confirm
Step 3: Confirm the upload
Verifies the file exists in S3, checks the size matches (within 10% tolerance), records the file, and attaches it to the entry field.
Parameters
upload_token
Required
| Name | Type | Required | Description |
|---|---|---|---|
upload_token |
string | Yes | Token from the upload response (step 1) |
curl -X POST "https://lerty.ai/api/v1/files/confirm" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"upload_token": "SFMyNTY..."}'
{
"data": {
"id": "file-uuid",
"filename": "report.pdf",
"content_type": "application/pdf",
"size_bytes": 204800,
"file_value": {
"key": "org_.../files/abc.pdf",
"bucket": "lerty-user-files",
"filename": "report.pdf",
"content_type": "application/pdf",
"size": 204800,
"file_id": "file-uuid",
"uploaded_at": "2025-01-15T10:30:00Z"
},
"download_url": "https://s3.amazonaws.com/...",
"download_url_expires_in": 3600,
"entry": { "id": "en_abc123", "field_id": "fd_file" }
}
}
/api/v1/files/:id/download
Get a presigned download URL
Returns a temporary download URL that expires in 1 hour.
curl -X GET "https://lerty.ai/api/v1/files/FILE_ID/download" \
-H "Authorization: Bearer YOUR_API_KEY"
{
"data": {
"download_url": "https://s3.amazonaws.com/...",
"filename": "report.pdf",
"content_type": "application/pdf",
"size_bytes": 204800,
"expires_in": 3600
}
}
/api/v1/files/:id
Delete a file
Soft-deletes the file. The S3 object is permanently removed after 30 days. Returns 204 No Content.
curl -X DELETE "https://lerty.ai/api/v1/files/FILE_ID" \
-H "Authorization: Bearer YOUR_API_KEY"
Errors
Lerty uses standard HTTP status codes and returns JSON error responses.
| Code | Meaning |
|---|---|
| 200 | Success |
| 201 | Created |
| 400 | Bad Request - Invalid parameters |
| 401 | Unauthorized - Invalid or missing API key |
| 403 | Forbidden - Not authorized for this resource |
| 404 | Not Found |
| 409 | Conflict - Duplicate resource |
| 402 | Payment Required - Plan limit reached |
| 422 | Unprocessable Entity - Validation error |
| 429 | Too Many Requests - Rate limited |
| 500 | Internal Server Error |
Error Response Format
All errors return a structured JSON object with a code, human-readable message, and optional details.
{
"error": {
"code": "authentication_required",
"message": "Missing or invalid API key. Include your key as: Authorization: Bearer YOUR_API_KEY",
"details": null
}
}
Data API Error Codes
These error codes are specific to the Data API (entries, fields, tables).
| Status | Code | When |
|---|---|---|
| 422 | field_not_found | A field name in your values, filters, or sort doesn't match any field in the table |
| 422 | validation_failed | Values don't match field types, or a duplicate field name was used |
| 422 | invalid_filter | Filter references a non-existent field or uses an invalid operator for that field type |
| 422 | invalid_sort | Sort references a non-existent or non-sortable field |
| 402 | plan_limit_reached | You've hit your plan's entry, field, or table limit |
| 404 | not_found | The table, entry, or field ID doesn't exist or doesn't belong to your organization |
| 403 | insufficient_permissions | Your API key doesn't have the required permission (e.g. data.tables:write) |
| 502 | storage_error | File upload to S3 failed |
Examples
{
"error": {
"code": "field_not_found",
"message": "Field 'Nonexistent' not found in this table.",
"details": null
}
}
{
"error": {
"code": "validation_failed",
"message": "Request body contains invalid fields.",
"details": { "name": ["a field with this name already exists in this table"] }
}
}
{
"error": {
"code": "plan_limit_reached",
"message": "You have reached the maximum of 1000 entries on the Free plan. Upgrade to create more.",
"details": null
}
}
Plan Limits
API calls that exceed these limits return 402
with the plan_limit_reached
code.
| Resource | Free | Starter | Agency |
|---|---|---|---|
| Databases | 2 | 10 | 50 |
| Tables / database | 5 | 25 | 30 |
| Fields / table | 10 | 30 | 50 |
| Entries (total) | 1,000 | 25,000 | 100,000 |
| Agents | 1 | 5 | Unlimited |
| Messages / day | 100 | 1,000 | Unlimited |
| Storage | 100 MB | 5 GB | 500 GB |
| Dashboards | 2 | 15 | 50 |
| Organizations | 1 | 1 | 50 |
Getting Clients
If you've made it this far, you already know enough to sell AI agents. The rest is understanding your client's problems and matching them to solutions. This section shows you how to find the right clients, craft your offer, and close the deal.
Ideal Clients
Not all clients are equal. Use this framework to evaluate prospects before you invest time.
|
Sweet Spot
Ongoing, highly personalized, yet simple solutions.
|
|
|---|---|
| What to Sell | How to Pitch It |
| Daily Expense Approvals | 30 min/day → 30 seconds. Manager taps approve or reject. |
| Content Draft Review | LLM drafts 3 versions. Marketing picks one. Publishes daily. |
| Quote Response | Lead fills form. Scored by custom algorithm. LLM drafts reply. Client sends or ignores. |
|
High Maintenance
Ongoing, highly personalized, complex solutions.
|
|
|---|---|
| What to Sell | Why It's Worth More |
| Full Sales Pipeline | Leads scored, enriched, sequenced. Hot leads surfaced. Client approves who to call. |
| Client Onboarding System | Contracts, accounts, welcome sequence triggered. Client approves each kickoff. |
| Hiring Pipeline | Applications screened, ranked, summarized. Top candidates surfaced. Client picks who to interview. |
|
Commodity
Not customized for the client. Readily available elsewhere for much cheaper.
|
|
|---|---|
| Don't Sell This | Why You'll Lose |
| Meeting Transcription | Otter is $10/mo. "Why pay you $500?" |
| Generic Content Generation | ChatGPT is $20/mo. No review = no need for you. |
| Calendar Booking | Calendly is free. They already have it. |
|
Time Sink
Poorly defined requests or processes that don't exist yet and aren't easily understood.
|
|
|---|---|
| Red Flag Request | What They'll Say vs. Reality |
| "Build Me a Jarvis" | "Just make it smart." No specs. Won't pay ongoing. |
| "Automate My Whole Business" | "One system for everything." Scope creeps forever. |
| Web Scraping System | "Just pull the data." Sites change weekly. You maintain forever. |
Cross Selling
Your existing clients are the easiest to sell to. They trust you and you already know their business.
Offer a free workflow audit or strategy session. Frame it as helping them find time or cost savings in their business. Most will say yes.
Questions to ask:
"What do you spend the first hour of your day doing?" "What tasks feel like busywork?" "Where do things get stuck waiting on you?" "What falls through the cracks?"
What to listen for:
Recurring tasks. Approval bottlenecks. Manual data entry. Anything they do daily or weekly that follows a pattern. That's your opportunity.
Outreach
If you're starting fresh, target industries with obvious pain points.
Step 1.) Find industries with built-in demand:
- Real estate: Leads, follow-ups, listing descriptions
- Home services: Quotes, scheduling, follow-ups
- Gyms and fitness: Membership follow-ups, class reminders
- Salons and spas: Booking confirmations, review requests
- Contractors: Project updates, quotes, invoicing
Get creative. Christmas light installers, float tank spas, pondscaping companies. The weirder the niche, the less competition. Long tail is untapped.
Step 2.) Research and identify tells:
Before you reach out, find proof they need help. Fill out their quote form and see if they follow up. Check their Google reviews for complaints about slow responses. See if they're hiring for admin or receptionist roles. These become your anchor points when you pitch.
Step 3.) Cold Looms:
Record a 2-minute Loom showing exactly what you found and a Lerty workflow that fixes it. "I filled out your quote form three days ago and never heard back. Here's what it would look like if you could respond in 30 seconds." Walk them through the agent, show the approval flow. Send the video in an email and offer a free workflow audit call.
Bonus - Upwork: Skip the research. People posting automation or AI jobs already have budget and intent to buy. Make sure their problem is a good fit, if it is, respond to their job listing.
Selling Agents
Use a two-call close. First call is a free strategy session where you assess their workflows and gather info. No pitching, just listening. Second call is where you present the proposal.
This works because you need real numbers to build a compelling proposal. Hourly rates, time spent, pain points. You can't guess that. The first call gives you everything you need to make the second call a no-brainer.
Before the second call, fill out the Proposal Generator below with what you learned. Their hourly costs, hours spent, the workflows you'll build. Have it ready so you can walk them through the numbers live and send the proposal before you get off the call.
Calculator
Formulas
Formula fields let you compute values from other fields in your table. They support arithmetic, comparisons, and built-in functions for strings, dates, and conditionals.
Syntax
Reference other fields by wrapping the field name in curly braces. Field names are case-sensitive.
| Element | Syntax | Example |
|---|---|---|
| Field reference |
{Field Name}
|
{Price}, {Status} |
| String literal | "text" |
"Done", "Hello world" |
| Number literal | 42, 3.14 |
100, 0.5 |
| Grouping | ( ) |
({Price} + {Tax}) * 1.1 |
| System fields |
{id}, {created_date}, ...
|
{created_date}, {updated_date}, {created_by}, {last_edited_by} |
\", \\, \n,
\t
Operators
Arithmetic operators for math and comparison operators for conditions.
Arithmetic
| Operator | Description | Example |
|---|---|---|
+ |
Addition | {Price} + {Tax} |
- |
Subtraction | {Total} - {Discount} |
* |
Multiplication | {Price} * {Quantity} |
/ |
Division (returns nil if divisor is 0) | {Total} / {Count} |
*
and /
are evaluated before +
and -. Use parentheses to override.
Comparison
| Operator | Description |
|---|---|
= |
Equal |
!= |
Not equal |
< |
Less than |
> |
Greater than |
<= |
Less than or equal |
>= |
Greater than or equal |
Functions
Conditional
IF(condition, then_value, else_value)
Evaluates a condition and returns one of two values. Supports nesting for multiple conditions.
IF({Status} = "Done", "Complete", "Pending")
IF({Score} >= 90, "A", IF({Score} >= 80, "B", "C"))
String
CONCAT(val1, val2, ...)
Joins multiple values into one string. Requires 2 or more arguments. Non-strings are converted automatically.
CONCAT({First Name}, " ", {Last Name})
CONCAT("$", {Price})
Logic
EMPTY(value)
Returns true if the value is nil, an empty string, an empty array, or 0. Useful in IF conditions.
IF(EMPTY({Notes}), "No notes", {Notes})
IF(EMPTY({Email}), "Missing", "Has email")
Date & Time — Current
TODAY()
Returns today's date in your timezone. Format: YYYY-MM-DD.
NOW()
Returns the current UTC datetime. Format: ISO 8601.
Date & Time — Extract Components
| Function | Returns | Range |
|---|---|---|
YEAR(date) |
Year | e.g. 2025 |
MONTH(date)
|
Month | 1–12 |
DATE(date) |
Day of month | 1–31 |
DAY(date) |
Day of week | 0 (Sun) – 6 (Sat) |
HOUR(datetime)
|
Hour | 0–23 |
MINUTE(datetime)
|
Minute | 0–59 |
Date & Time — Arithmetic
DATEADD(date, number, unit)
Adds time to a date or datetime. Supported units: "years", "months", "weeks", "days", "hours", "minutes" (singular forms also accepted).
DATEADD({Start Date}, 7, "days")
DATEADD({Due Date}, 1, "months")
DATEADD(TODAY(), 14, "days")
DATESUBTRACT(date, number, unit)
Subtracts time from a date or datetime. Same units as DATEADD.
DATESUBTRACT({Due Date}, 1, "months")
DATESUBTRACT({End Date}, 3, "weeks")
DATEDIFF(start, end, unit)
Calculates the difference between two dates. Supports units: "years", "months", "weeks", "days", "hours", "minutes", "seconds". Returns negative numbers if start is after end.
DATEDIFF({Start Date}, {End Date}, "days")
DATEDIFF({Created Date}, TODAY(), "weeks")
DATEDIFF(TODAY(), {Due Date}, "days")
Field Types
All field types can be referenced in formulas. Here's how each type resolves when used.
| Field Type | Resolves To |
|---|---|
text |
String value |
number |
Numeric value for arithmetic |
date |
Date value for comparisons and date functions |
checkbox |
true or false (defaults to false when nil) |
select |
Option label string (e.g. "High", not the internal ID) |
multi_select
|
Comma-separated labels (e.g. "Red, Blue") |
relation |
Display value of linked entry (comma-separated if many) |
user |
Account name or email |
file |
Filename string |
rollup |
Computed value (can reference other computed fields) |
formula |
Computed value (can reference other formula fields) |
Examples
Common formula patterns you can use in your tables.
{Price} * {Quantity}
IF({Status} = "Done", "Complete", IF({Status} = "In progress", "Active", "Not started"))
DATEDIFF(TODAY(), {Due Date}, "days")
CONCAT({First Name}, " ", {Last Name})
IF(EMPTY({Email}), "Missing email", {Email})
IF({Score} >= 90, "A", IF({Score} >= 80, "B", IF({Score} >= 70, "C", "F")))
DATEADD({Close Date}, 14, "days")
DATEDIFF({created_date}, TODAY(), "days")
MCP Server
Lerty exposes a Model Context Protocol (MCP) server so any MCP-compatible client (Claude Desktop, Cursor, Windsurf, custom agents) can read and write your Lerty data using structured tools. The server uses the Streamable HTTP transport and authenticates with the same API keys as the REST API.
Connection
Point your MCP client at the Streamable HTTP endpoint. Authentication is via Bearer token using your Lerty API key.
| Setting | Value |
|---|---|
| Endpoint |
https://lerty.ai/mcp/v1
|
| Transport | Streamable HTTP |
| Auth Header |
Authorization: Bearer ak_your_api_key
|
data.databases:read
or data.tables:read; write tools need data.tables:write.
Database Tools
Databases are the top-level containers in Lerty's data hierarchy. Each database contains tables, which contain fields and entries.
database_list
read
List all databases in your organization. Returns display IDs (pr_xxx), names, descriptions, and creation dates.
database_get
read
Get details for a specific database including its tables.
database_id
(required) — Database display ID
database_create
write
Create a new database.
name
(required), description
(optional)
database_update
write
Update a database's name, description, or color.
database_id
(required), name, description,
color
(all optional)
database_delete
write
Soft-delete a database and all its tables, fields, and entries.
database_id (required)
Table Tools
Tables live inside databases and hold fields (columns) and entries (rows).
table_list
read
List all tables in a database with entry counts and field summaries.
database_id (required)
table_get
read
Get a table's details including all fields with their types and configurations.
table_id (required)
table_create
write
Create a new table in a database. A default Name text field is added automatically.
database_id
(required), name
(required)
table_update
write
Rename a table or update its position.
table_id
(required), name,
position
(optional)
table_delete
write
Soft-delete a table and all its fields and entries.
table_id (required)
Field Tools
Fields define the columns in a table. Supported types: text, number, select, multi_select, date, checkbox, file, relation, user, formula, rollup.
field_list
read
List all fields in a table with types, configurations, and display IDs.
table_id (required)
field_get
read
Get a single field's details including config (select options, formula expression, etc.).
field_id (required)
field_create
write
Add a new field to a table. For select/multi_select, provide options in config.
table_id
(required), name
(required), field_type
(required), config
(optional)
field_update
write
Update a field's name, type, or config. Config is merged (not replaced).
field_id
(required), name, field_type,
config
(optional)
field_delete
write
Soft-delete a field. Entry values for this field are preserved but hidden.
field_id (required)
Entry Tools
Entries are the rows in a table. Values are keyed by field display ID (fd_xxx) or field name. Select/multi_select values accept option IDs (op_xxx) or human-readable labels.
entry_list
read
List entries in a table with pagination. Default limit 50, max 200. For filtering or sorting, use
entry_query
instead.
table_id
(required), limit,
offset
(optional)
entry_get
read
Get a single entry by its display ID.
entry_id (required)
entry_create
write
Create a new entry. Pass values as a map of field names or display IDs to values.
table_id
(required), values
(map of field values)
entry_update
write
Update an entry's values. This is a merge — only the fields you specify are changed, all others are preserved.
entry_id
(required), values
(required, map of fields to update)
entry_delete
write
Soft-delete an entry.
entry_id (required)
entry_query
read
Query entries with filters, sorting, and full-text search. Filters are AND-combined. Fields accept display IDs or names.
table_id
(required), filters
(array), sort
(array), search, limit, offset,
timezone
entry_bulk
write
Perform bulk create, update, or delete operations on entries (max 100 per request). Returns success/failure counts.
table_id
(required), operations
(required, array of action
+ entry_id
+ values)
entry_aggregate
read
Compute aggregations: count, distinct_count, sum, average, min, max. Count doesn't require a field; all others do.
table_id
(required), function
(required), field_id
(required for non-count),
field_type
(optional hint)
Notes Tools
Each entry can have a rich-text notes document stored as TipTap JSON.
entry_notes_get
read
Get the TipTap JSON notes for an entry. Returns null with
has_notes: false
if no notes exist.
entry_id (required)
entry_notes_update
write
Replace an entry's notes with a new TipTap JSON document. Pass null to clear notes.
entry_id
(required), notes
(TipTap JSON or null)
entry_notes_append
write
Append TipTap block nodes to the end of existing notes. Creates a new document if none exists. Uses row-level locking for concurrent safety.
entry_id
(required), nodes
(required, array of TipTap block nodes)