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.

Example Request
curl -X GET "https://lerty.ai/api/v1/agents" \
  -H "Authorization: Bearer ak_your_api_key_here"

Getting an API Key

  1. Log in to Lerty at lerty.ai
  2. Go to the Settings of your organization → API Key
  3. 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.

Personal organizations are private to the account owner and cannot be shared. To collaborate with others, create a new organization from the organization switcher.

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

Owner
Full access, billing, can delete organization
Admin
Manage agents, settings, and members
Member
Chat with agents, respond to approvals
To invite members, go to Settings → Users in your organization dashboard and send an invite by email.

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

Anthropic
Claude
Complex reasoning, long context, best models 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

  1. User sends a message in Lerty
  2. Lerty POSTs the message to your webhook URL
  3. Your automation or backend processes the message
  4. Your workflow calls Lerty's API to send a response
  5. 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

Incoming Webhook
{
  "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.

GET /api/v1/agents

List all agents

Query Parameters

detailed Optional
boolean
Include detailed agent information
Request

          curl -X GET "https://lerty.ai/api/v1/agents?detailed=true" \
  -H "Authorization: Bearer YOUR_API_KEY"

        
200 Success

          {
  "agents": [
    {
      "id": "agent-uuid-here",
      "name": "Support Bot",
      "status": "active",
      "protocol": "webhook",
      "webhook_url": "https://your-server.com/webhook"
    }
  ]
}

        
GET /api/v1/agents/:id

Get a specific agent

Query Parameters

detailed Optional
boolean
Include detailed agent information
Request

          curl -X GET "https://lerty.ai/api/v1/agents/AGENT_ID?detailed=true" \
  -H "Authorization: Bearer YOUR_API_KEY"

        
PATCH /api/v1/agents/:id

Update agent configuration

Body Parameters

name Optional
string
Agent name
webhook_url Optional
string
Webhook URL for messages
enabled Optional
boolean
Enable or disable the agent
test_mode Optional
boolean
Use test webhook URL
Request

          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}'

        
200 Success

          {
  "success": true,
  "agent": {
    "id": "agent-uuid-here",
    "name": "Support Bot",
    "webhook_url": "https://your-new-webhook.com/handle",
    "enabled": true
  }
}

        
GET /api/v1/agents/:id/connection-info

Get agent connection information

Get webhook URLs, API endpoints, and conversation list for an agent

Request

          curl -X GET "https://lerty.ai/api/v1/agents/AGENT_ID/connection-info" \
  -H "Authorization: Bearer YOUR_API_KEY"

        
200 Success

          {
  "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.

POST /api/v1/agents/:agent_id/conversations/create

Create a new conversation

Body Parameters

title Optional
string
Conversation title
user_id Optional
string
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.
Request

          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"}'

        
201 Created

          {
  "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"
  }
}

        
GET /api/v1/agents/:agent_id/conversations

List conversations for an agent

Request

          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.

POST /api/v1/conversations/:conversation_id/messages

Send a user message

Body Parameters

content Required
string
Message content
Request

          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"}'

        
POST /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
string
Message text (supports markdown)
role Required
string
Must be "assistant"
external_message_id Optional
string
Unique ID for deduplication
Request

          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"}'

        
200 Success

          {
  "success": true,
  "message": {
    "id": "msg-uuid-here",
    "content": "Hi! How can I help you today?",
    "role": "assistant"
  }
}

        
409 Duplicate Message

          {
  "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

  1. Your workflow sends an interactive message to a conversation via the API
  2. The user sees the interactive UI (buttons, form, or approval prompt) in Lerty
  3. When the user responds, Lerty POSTs the response to your callback URL
  4. Your workflow receives the callback and continues processing

Action Types

Each interactive message requires exactly one action element:

Boolean
Approve/Reject with optional message
Callback receives: approved (true/false), message
Buttons
Multiple choice selection
Callback receives: selection (button value)
Fields
Form with multiple inputs
Callback receives: data object with field values
The callback_url is where Lerty sends the user's response. The callback_id is your reference ID to correlate the response with your original request.
POST /api/v1/conversations/:conversation_id/interactive

Send an interactive message

Body Parameters

callback_url Required
string
URL to receive user's response
callback_id Required
string
Your unique ID for this interaction
elements Required
array
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
Boolean Example

          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"}]}'

        
Fields Form Example

          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:

200 Boolean Response

          {
  "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"
  }
}

        
200 Fields Response

          {
  "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.

POST /api/agents/:agent_id/callback

Show or hide typing indicator

Path Parameters

agent_id Required
string
The agent ID

Body Parameters

callback_type Required
string
Must be "typing"
conversation_id Required
string
The conversation ID to show typing indicator in
data.typing Required
boolean
true to show, false to hide
data.label Optional
string
Optional text to display with animated shimmer effect (e.g., "Thinking...", "Searching...")
data.show_dots Optional
boolean
Whether to show animated dots (default: true). Set to false to show only the label.
data.timeout Optional
integer
Timeout in milliseconds before auto-clear (default: 30000). Use for long-running operations.
Request
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
    }
  }'
Typing indicators auto-clear after the specified timeout (default: 30 seconds). Send typing: false when done processing. The optional label field displays animated text next to the typing dots.

Organization API

Manage your organization and team members programmatically. The organization is determined automatically from your API key.

Required permissions: organizations:read for viewing, members:read and members:write for member management.
GET /api/v1/organization

Get organization details

Request
curl -X GET "https://lerty.ai/api/v1/organization" \
  -H "Authorization: Bearer YOUR_API_KEY"
200 Success

          {
  "organization": {
    "id": "org-uuid-here",
    "name": "My Company"
  }
}

        
GET /api/v1/organization/members

List organization members

Request

          curl -X GET "https://lerty.ai/api/v1/organization/members" \
  -H "Authorization: Bearer YOUR_API_KEY"

        
200 Success

          {
  "members": [
    {"id": "user-uuid", "email": "owner@example.com", "role": "owner"},
    {"id": "user-uuid-2", "email": "member@example.com", "role": "member"}
  ]
}

        
POST /api/v1/organization/members

Invite a member by email

Body Parameters

email Required
string
Email address to invite
Request

          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"}'

        
201 Member invited

          {
  "member": {
    "id": "user-uuid-new",
    "email": "newuser@example.com",
    "role": "member"
  }
}

        
New members are always assigned the member role. Use the dashboard to promote to admin.
DELETE /api/v1/organization/members/:user_id

Remove a member

Path Parameters

user_id Required
string
User ID to remove
Request

          curl -X DELETE "https://lerty.ai/api/v1/organization/members/USER_ID" \
  -H "Authorization: Bearer YOUR_API_KEY"

        
Cannot remove owners or admins via API. Only members with the member role can be removed.

Push Notifications

Send push notifications to users on the Lerty mobile app. Notify users of important events, approvals needed, or updates from your workflows.

POST /api/push/send

Send push notification to a user

Body Parameters

email Required
string
User's email address
title Required
string
Notification title
body Required
string
Notification body
priority Optional
string
critical, high, medium, normal, low
sound Optional
string
Notification sound
data Optional
object
Custom data payload
Request

          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"}'

        
200 Success
{
  "success": true,
  "email": "user@example.com",
  "devices_succeeded": 2,
  "devices_failed": 0,
  "total_devices": 2
}
POST /api/push/send/bulk

Send push to multiple users

Body Parameters

recipients Required
array
Array of email addresses
title Required
string
Notification title
body Required
string
Notification body
priority Optional
string
Notification priority
Request

          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"}'

        
GET /api/push/devices

List user's registered devices

Query Parameters

email Required
string
User's email address
Request

          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.

Live Activities are started via POST /api/push/send with workflow_state in the data payload. See the Quick Start guide for complete examples.
POST /api/push/live-activity/update

Update a Live Activity

Body Parameters

notification_id Required
string
ID of the Live Activity notification
content_state Required
object
Live Activity content (itemTitle, status, progressPercent, etc.)
event Optional
string
"update" (default) or "end" to dismiss
priority Optional
string
critical, high, normal, low (low = silent update)
dismissal_date Optional
integer
Unix timestamp for dismissal (only for end event)

Content State Fields

itemTitle Required
string
Main title displayed
itemSubtitle Optional
string
Subtitle text
status Required
string
Current status text
progressPercent Required
integer
Progress percentage (0-100)
currentStep Optional
integer
Current step number
totalSteps Optional
integer
Total steps
lastUpdate Optional
integer
Unix timestamp (auto-dismiss after 2 min without updates)
Update Request

          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}}'

        
200 Success

          {
  "success": true,
  "tokens_updated": 1,
  "notification_id": "notif-123"
}

        
End Request

          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}}'

        
Use 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.

GET /api/v1/databases

List all databases

Request

          curl -X GET "https://lerty.ai/api/v1/databases" \
  -H "Authorization: Bearer YOUR_API_KEY"

        
200 Success

          {
  "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 }
}

        
POST /api/v1/databases

Create a database

Parameters

name Required
string
Database name
description Optional
string
Optional description
color Optional
string
Hex color code (e.g. #3B82F6)
Request

          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"}'

        
201 Created

          {
  "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"
  }
}

        
GET /api/v1/databases/:id

Get a database by ID

Request

          curl -X GET "https://lerty.ai/api/v1/databases/db_abc123" \
  -H "Authorization: Bearer YOUR_API_KEY"

        
PATCH /api/v1/databases/:id

Update a database

Request

          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"}'

        
DELETE /api/v1/databases/:id

Delete a database

Soft-deletes the database and all its tables. Returns 204 No Content.

Request

          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.

GET /api/v1/databases/:db_id/tables

List tables in a database

Request

          curl -X GET "https://lerty.ai/api/v1/databases/db_abc123/tables" \
  -H "Authorization: Bearer YOUR_API_KEY"

        
200 Success

          {
  "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 }
}

        
POST /api/v1/databases/:db_id/tables

Create a table

Parameters

name Required
string
Table name
Request

          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"}'

        
New tables include 4 default fields (text, select, date, checkbox) and 3 empty entries. You can delete the defaults and add your own fields.
GET /api/v1/tables/:id

Get a table by ID

Returns the table with all its active fields.

PATCH /api/v1/tables/:id

Update a table

Update the table name.

DELETE /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.

Request

          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.

GET /api/v1/tables/:table_id/fields

List fields in a table

POST /api/v1/tables/:table_id/fields

Create a field

Parameters

name Required
string
Field name
type Required
string
Field type: text, number, select, date, checkbox, file, formula, url
config Optional
object
Type-specific config. For select: {"options": [{"label": "...", "color": "..."}]}
Request

          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"}]}}'

        
201 Created

          {
  "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"
  }
}

        
Select field options get auto-generated op_ IDs. Use these IDs (not labels) when setting entry values.
PATCH /api/v1/fields/:id

Update a field

Request

          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"}'

        
DELETE /api/v1/fields/:id

Delete a field

Soft-deletes the field. Returns 204 No Content.

Request

          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.

Field names or IDs: You can use human-readable field names (e.g. "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.

GET /api/v1/tables/:table_id/entries

List entries in a table

Query Parameters

limit Optional
integer
Page size, max 200 (default 50)
offset Optional
integer
Pagination offset (default 0)
sort Optional
string
field_name:direction or field_id:direction (e.g. Status:asc)
search Optional
string
Full-text search across text fields
Request

          curl -X GET "https://lerty.ai/api/v1/tables/tb_xyz789/entries?limit=50&offset=0" \
  -H "Authorization: Bearer YOUR_API_KEY"

        
200 Success

          {
  "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 }
}

        
POST /api/v1/tables/:table_id/entries

Create an entry

Parameters

values Optional
object
Map of field name (or field ID) → value. Select fields accept option labels or option IDs. Omit for an empty entry.
Using field names

          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"}}'

        
Using field IDs (also works)

          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"}}'

        
GET /api/v1/entries/:id

Get an entry by ID

PATCH /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.

Request

          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"}}'

        
DELETE /api/v1/entries/:id

Delete an entry

Soft-deletes the entry and cleans up any attached files. Returns 204 No Content.

POST /api/v1/tables/:table_id/entries/query

Query entries with filters and sorting

Parameters

filters Optional
array
Array of {field, op, value}. Field can be a name or ID. Select values accept option labels.
sort Optional
array
Array of {field, direction}. Field can be a name or ID. Direction: asc or desc
search Optional
string
Full-text search
limit Optional
integer
Page size (default 50, max 200)
offset Optional
integer
Pagination offset
Request

          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}'

        
POST /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).

Request

          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"}]}'

        
200 Results

          {
  "data": {
    "total": 3,
    "succeeded": 3,
    "failed": 0,
    "results": [...]
  }
}

        
POST /api/v1/tables/:table_id/aggregate

Aggregate entries

Compute aggregate functions across entries. Supported: count, sum, avg, min, max.

Parameters

function Required
string
Aggregate function: count, distinct_count, sum, avg, min, max
field Optional
string
Field name or ID to aggregate (required for sum, avg, min, max)
Request

          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"}'

        
200 Result

          {
  "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.

TipTap node types: 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.

GET /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.

Request

          curl -X GET "https://lerty.ai/api/v1/entries/en_abc123/notes" \
  -H "Authorization: Bearer YOUR_API_KEY"

        
200 Success

          {
  "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
  }
}

        
PATCH /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
object | null
TipTap JSON document (must have type: "doc" and content array), or null to clear
Replace notes

          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."}]}]}}'

        
Clear notes

          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}'

        
POST /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
array
Array of TipTap block nodes to append (e.g. paragraphs, headings, lists)
Append a 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": "paragraph", "content": [{"type": "text", "text": "Appended a new paragraph."}]}]}'

        
Append rich content

          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.

Upload flow (3 steps):
  1. Call POST /files/upload with file metadata — get back a presigned S3 URL and upload token
  2. PUT the file binary directly to the presigned URL
  3. Call POST /files/confirm with the upload token — the file is verified, recorded, and attached to the entry
GET /api/v1/files

List all files in the organization

Query Parameters

limit Optional
integer
Page size, max 200 (default 50)
offset Optional
integer
Pagination offset (default 0)
Request

          curl -X GET "https://lerty.ai/api/v1/files?limit=50" \
  -H "Authorization: Bearer YOUR_API_KEY"

        
200 Success

          {
  "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 }
}

        
POST /api/v1/files/upload

Step 1: Request a presigned upload URL

Parameters

entry_id Required
string
Entry display ID (e.g. en_abc123)
field_id Required
string
File field display ID (e.g. fd_xyz)
filename Required
string
Filename with extension
content_type Required
string
MIME type (e.g. application/pdf)
size_bytes Required
integer
File size in bytes
Request

          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}'

        
200 Presigned URL and token

          {
  "data": {
    "upload_url": "https://s3.amazonaws.com/bucket/key?X-Amz-Signature=...",
    "upload_token": "SFMyNTY...",
    "upload_headers": { "Content-Type": "application/pdf" },
    "expires_in": 3600
  }
}

        
PUT <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.

Request

          curl -X PUT "<upload_url from step 1>" \
  -H "Content-Type: application/pdf" \
  --data-binary @report.pdf

        
POST /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
string
Token from the upload response (step 1)
Request

          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..."}'

        
201 File recorded and attached

          {
  "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" }
  }
}

        
GET /api/v1/files/:id/download

Get a presigned download URL

Returns a temporary download URL that expires in 1 hour.

Request

          curl -X GET "https://lerty.ai/api/v1/files/FILE_ID/download" \
  -H "Authorization: Bearer YOUR_API_KEY"

        
200 Download URL

          {
  "data": {
    "download_url": "https://s3.amazonaws.com/...",
    "filename": "report.pdf",
    "content_type": "application/pdf",
    "size_bytes": 204800,
    "expires_in": 3600
  }
}

        
DELETE /api/v1/files/:id

Delete a file

Soft-deletes the file. The S3 object is permanently removed after 30 days. Returns 204 No Content.

Request

          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.

200 Success
201 Created
400 Bad Request
401 Unauthorized
403 Forbidden
404 Not Found
409 Conflict
402 Plan Limit
422 Validation
429 Rate Limited
500 Server Error

Error Response Format

All errors return a structured JSON object with a code, human-readable message, and optional details.

Authentication Error (401)

        {
  "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).

Examples

Field Not Found (422)

        {
  "error": {
    "code": "field_not_found",
    "message": "Field 'Nonexistent' not found in this table.",
    "details": null
  }
}

      
Validation Failed (422)

        {
  "error": {
    "code": "validation_failed",
    "message": "Request body contains invalid fields.",
    "details": { "name": ["a field with this name already exists in this table"] }
  }
}

      
Plan Limit (402)
{
  "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.

+
Business Impact
-
Sweet Spot
High Maintenance
Commodity
Time Sink
- Support Required +
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}
Strings support escape sequences: \", \\, \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}
Standard math precedence applies: * 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.

Line item total
{Price} * {Quantity}
Status label
IF({Status} = "Done", "Complete", IF({Status} = "In progress", "Active", "Not started"))
Days until deadline
DATEDIFF(TODAY(), {Due Date}, "days")
Full name
CONCAT({First Name}, " ", {Last Name})
Missing data check
IF(EMPTY({Email}), "Missing email", {Email})
Letter grade
IF({Score} >= 90, "A", IF({Score} >= 80, "B", IF({Score} >= 70, "C", "F")))
Follow-up date
DATEADD({Close Date}, 14, "days")
Entry age
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
The MCP server exposes the same data as the REST API. Your API key permissions control which tools are available. Tools requiring read access need 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.

Params: database_id (required) — Database display ID
database_create write

Create a new database.

Params: name (required), description (optional)
database_update write

Update a database's name, description, or color.

Params: database_id (required), name, description, color (all optional)
database_delete write

Soft-delete a database and all its tables, fields, and entries.

Params: 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.

Params: database_id (required)
table_get read

Get a table's details including all fields with their types and configurations.

Params: table_id (required)
table_create write

Create a new table in a database. A default Name text field is added automatically.

Params: database_id (required), name (required)
table_update write

Rename a table or update its position.

Params: table_id (required), name, position (optional)
table_delete write

Soft-delete a table and all its fields and entries.

Params: 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.

Params: table_id (required)
field_get read

Get a single field's details including config (select options, formula expression, etc.).

Params: field_id (required)
field_create write

Add a new field to a table. For select/multi_select, provide options in config.

Params: 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).

Params: field_id (required), name, field_type, config (optional)
field_delete write

Soft-delete a field. Entry values for this field are preserved but hidden.

Params: 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.

Params: table_id (required), limit, offset (optional)
entry_get read

Get a single entry by its display ID.

Params: entry_id (required)
entry_create write

Create a new entry. Pass values as a map of field names or display IDs to values.

Params: 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.

Params: entry_id (required), values (required, map of fields to update)
entry_delete write

Soft-delete an entry.

Params: 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.

Params: table_id (required), filters (array), sort (array), search, limit, offset, timezone
Filter ops: Text: contains, is, is_not, starts_with, ends_with, is_empty, is_not_empty. Number: equals, greater_than, less_than. Date: is, is_before, is_after. Select: is, is_not. Checkbox: is_checked, is_unchecked.
entry_bulk write

Perform bulk create, update, or delete operations on entries (max 100 per request). Returns success/failure counts.

Params: 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.

Params: 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.

Params: entry_id (required)
entry_notes_update write

Replace an entry's notes with a new TipTap JSON document. Pass null to clear notes.

Params: 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.

Params: entry_id (required), nodes (required, array of TipTap block nodes)