REST API
The Server AI Toolkit provides REST API endpoints for both tools and workflows.
Postman collection
Authentication
All requests must include:
Authorization: Bearer <JWT>X-App-Id: <APP_ID>
Generate the JWT server-side with your AI secret. Get your App ID and secret key on the Server AI Toolkit settings page.
import jwt from 'jsonwebtoken'
const JWT_TOKEN = jwt.sign(
{
experimental_document_server_id: 'your-document-server-id',
experimental_document_server_management_api_secret:
'your-document-server-management-api-secret',
},
'your-ai-secret-key',
{ expiresIn: '1h' },
)See the authorization guide for more information.
Document Server credentials
Include these JWT claims when you want the Server AI Toolkit to fetch and save Tiptap Cloud documents automatically:
experimental_document_server_idexperimental_document_server_management_api_secret
Base URL
The hosted base URL is:
https://api.tiptap.devIn the examples below, requests are written as BASE_URL/v3/ai/....
How to provide the document
Most tool and workflow endpoints accept exactly one document source:
document: Inline Tiptap JSONexperimental_documentOptions: A Tiptap Cloud document reference
experimental_documentOptions has the following shape:
documentId(string, required): The Tiptap Cloud document identifier.userId?(string | null, optional): Identifier attributed to edits the AI performs.field?(string | null, optional, default:"default"): Targets a specific collaborative field (Y.js XML fragment) inside the document when omitted ornull. Use this when your document stores multiple editable fields — for example a separate title and body — under the samedocumentId.
Example with a Tiptap Cloud document:
{
"experimental_documentOptions": {
"documentId": "your-document-id",
"userId": "ai-assistant"
}
}Example targeting a non-default collaborative field:
{
"experimental_documentOptions": {
"documentId": "your-document-id",
"userId": "ai-assistant",
"field": "title"
}
}Example with an inline document:
{
"document": {
"type": "doc",
"content": []
}
}Threads require a cloud document
Thread and comment endpoints always require experimental_documentOptions.documentId.
Session mechanism
Read endpoints return a sessionId that records the node hashes and content hashes the AI saw.
Reuse that same sessionId on follow-up edit requests so the server can reject stale edits instead
of overwriting newer user changes.
Formats
Most endpoints accept a format field:
"json": Standard JSON representation"shorthand": Tiptap Shorthand, a token-efficient format for prompts and model output
proofreader currently supports shorthand only.
Tool endpoints
Get tool definitions
POST /v3/ai/toolkit/toolsReturns the available tool definitions for AI agents.
Request body:
schemaAwarenessData(SchemaAwarenessData, required)tools?(object, optional): Enable or disable individual toolsoperationMeta?(string | null, optional, default:"")format?('json' | 'shorthand', optional, default:'json')
Response:
tools(array)name(string)description(string)inputSchema(object)
Execute a tool
POST /v3/ai/toolkit/execute-toolExecutes one Server AI Toolkit tool such as tiptapRead, tiptapEdit, getThreads, or
editThreads.
Request body:
toolName(string, required)input(unknown, required)schemaAwarenessData(SchemaAwarenessData, required)sessionId?(string | null, optional): Reuse the session from a previous read or tool execution to enable stale-read protection.format?('json' | 'shorthand', optional, default:'json')chunkSize?(number, optional, default:32000)reviewOptions?(ReviewOptions, optional, default:{ mode: 'disabled' })experimental_commentsOptions?({ threadData?: Record<string, unknown>, commentData?: Record<string, unknown> }, optional): Metadata attached to new threads and comments created during thread-related tool execution.- exactly one of:
documentexperimental_documentOptions
Response:
sessionId(string)output(unknown)docChanged(boolean)document(object | null)
Workflow endpoints
Get a workflow definition
Use one of these endpoints:
POST /v3/ai/toolkit/workflows/editPOST /v3/ai/toolkit/workflows/insert-contentPOST /v3/ai/toolkit/workflows/proofreaderPOST /v3/ai/toolkit/workflows/threads
Request body:
format?('json' | 'shorthand', optional, default:'json'). Theproofreaderworkflow only accepts'shorthand'.
Response:
systemPrompt(string)outputSchema(object)
Example:
curl --location 'BASE_URL/v3/ai/toolkit/workflows/edit' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_JWT_TOKEN' \
--header 'X-App-Id: YOUR_APP_ID' \
--data '{
"format": "shorthand"
}'
Keep the returned sessionId and send it with the matching workflow execute request.
Read document content for a workflow
POST /v3/ai/toolkit/read/read-documentReads document content and returns workflow-ready content.
Request body:
range?({ from: number, to: number }, optional, default: entire document)schemaAwarenessData(SchemaAwarenessData, required)format?('json' | 'shorthand', optional, default:'json')sessionId?(string | null, optional)chunkSize?(number, optional, default:32000)reviewOptions?(ReviewOptions, optional, default:{ mode: 'disabled' })- exactly one of:
documentexperimental_documentOptions
Response:
sessionId(string)outputsuccess(boolean)content?(unknown)error?(string)
docChanged(boolean)document(object | null)
Example:
curl --location 'BASE_URL/v3/ai/toolkit/read/read-document' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_JWT_TOKEN' \
--header 'X-App-Id: YOUR_APP_ID' \
--data '{
"schemaAwarenessData": { /* schema awareness data */ },
"format": "shorthand",
"reviewOptions": {
"mode": "disabled"
},
"experimental_documentOptions": {
"documentId": "your-document-id",
"userId": "ai-assistant"
}
}'
Keep the returned sessionId and send it with the matching insert-content execute request.
Read the current selection
POST /v3/ai/toolkit/read/read-selectionReads the selection and returns either a selection payload or an explicit empty state.
Request body:
range({ from: number, to: number }, required)schemaAwarenessData(SchemaAwarenessData, required)format?('json' | 'shorthand', optional, default:'json')sessionId?(string | null, optional)chunkSize?(number, optional, default:32000)reviewOptions?(ReviewOptions, optional, default:{ mode: 'disabled' })- exactly one of:
documentexperimental_documentOptions
Response:
sessionId(string)output- when the selection is empty:
isEmpty(true)
- when the selection contains content:
isEmpty(false)content(unknown)nodeHashes(string[])nodeRange({ from: number, to: number })prompt(string)
- when the selection is empty:
docChanged(boolean)document(object | null)
Example:
curl --location 'BASE_URL/v3/ai/toolkit/read/read-selection' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_JWT_TOKEN' \
--header 'X-App-Id: YOUR_APP_ID' \
--data '{
"schemaAwarenessData": { /* schema awareness data */ },
"range": { "from": 10, "to": 42 },
"format": "shorthand",
"experimental_documentOptions": {
"documentId": "your-document-id"
}
}'
Read threads
POST /v3/ai/toolkit/read/threadsReads all threads and comments for a Tiptap Cloud document.
Request body:
schemaAwarenessData(SchemaAwarenessData, required)format('json' | 'shorthand', required)experimental_documentOptions({ documentId: string, userId?: string, field?: string | null }, required)
Response:
outputthreads?(unknown[])error?(string)
docChanged(boolean)document(object | null)
Example:
curl --location 'BASE_URL/v3/ai/toolkit/read/threads' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_JWT_TOKEN' \
--header 'X-App-Id: YOUR_APP_ID' \
--data '{
"schemaAwarenessData": { /* schema awareness data */ },
"format": "shorthand",
"experimental_documentOptions": {
"documentId": "your-document-id",
"userId": "ai-assistant"
}
}'
Execute the insert-content workflow
POST /v3/ai/toolkit/execute-workflow/insert-contentRequest body:
input(unknown, required): Generated insert-content payloadrange?({ from: number, to: number }, optional)schemaAwarenessData(SchemaAwarenessData, required)format?('json' | 'shorthand', optional, default:'json')sessionId?(string | null, optional)chunkSize?(number, optional, default:32000)reviewOptions?(ReviewOptions, optional, default:{ mode: 'disabled' })- exactly one of:
documentexperimental_documentOptions
Response:
sessionId(string)outputerror?(string)range?({ from: number, to: number })
docChanged(boolean)document(object | null)
Example:
curl --location 'BASE_URL/v3/ai/toolkit/execute-workflow/insert-content' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_JWT_TOKEN' \
--header 'X-App-Id: YOUR_APP_ID' \
--data '{
"schemaAwarenessData": { /* schema awareness data */ },
"input": "This is the replacement content.",
"range": { "from": 10, "to": 42 },
"format": "shorthand",
"reviewOptions": {
"mode": "disabled"
},
"experimental_documentOptions": {
"documentId": "your-document-id",
"userId": "ai-assistant"
}
}'
Execute the Tiptap Edit workflow
POST /v3/ai/toolkit/execute-workflow/tiptap-editRequest body:
input(object, required): Edit workflow operationsschemaAwarenessData(SchemaAwarenessData, required)format?('json' | 'shorthand', optional, default:'json')sessionId?(string | null, optional)chunkSize?(number, optional, default:32000)reviewOptions?(ReviewOptions, optional, default:{ mode: 'disabled' })- exactly one of:
documentexperimental_documentOptions
Response:
sessionId(string)outputoperationResults?(array)reason?('validationError' | 'unexpectedError')error?(string)
docChanged(boolean)document(object | null)
Example:
curl --location 'BASE_URL/v3/ai/toolkit/execute-workflow/tiptap-edit' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_JWT_TOKEN' \
--header 'X-App-Id: YOUR_APP_ID' \
--data '{
"schemaAwarenessData": { /* schema awareness data */ },
"input": {
"operations": [
{
"type": "replace",
"target": "abc123",
"content": "# Updated heading\n\nUpdated paragraph content."
}
]
},
"format": "shorthand",
"reviewOptions": {
"mode": "disabled"
},
"experimental_documentOptions": {
"documentId": "your-document-id",
"userId": "ai-assistant"
}
}'
Execute the proofreader workflow
POST /v3/ai/toolkit/execute-workflow/proofreaderRequest body:
input(object, required): Proofreader operationsschemaAwarenessData(SchemaAwarenessData, required)format('shorthand', required)sessionId?(string | null, optional)chunkSize?(number, optional, default:32000)reviewOptions?(ReviewOptions, optional, default:{ mode: 'disabled' })- exactly one of:
documentexperimental_documentOptions
Response:
sessionId(string)outputoperationResults(array)
docChanged(boolean)document(object | null)
Example:
curl --location 'BASE_URL/v3/ai/toolkit/execute-workflow/proofreader' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_JWT_TOKEN' \
--header 'X-App-Id: YOUR_APP_ID' \
--data '{
"schemaAwarenessData": { /* schema awareness data */ },
"input": {
"operations": []
},
"format": "shorthand",
"reviewOptions": {
"mode": "trackedChanges",
"trackedChangesOptions": {
"userId": "ai-assistant"
}
},
"experimental_documentOptions": {
"documentId": "your-document-id"
}
}'
Execute the comments workflow
POST /v3/ai/toolkit/execute-workflow/threadsRequest body:
input(object, required): Thread operationsschemaAwarenessData(SchemaAwarenessData, required)format?('json' | 'shorthand', optional, default:'json')experimental_documentOptions({ documentId: string, userId?: string, field?: string | null }, required)experimental_commentsOptions?({ threadData?: Record<string, unknown>, commentData?: Record<string, unknown> }, optional): Metadata attached to new threads and comments created by the workflow.
Response:
outputoperations?(array)error?(string)
docChanged(boolean)document(object | null)
Example:
curl --location 'BASE_URL/v3/ai/toolkit/execute-workflow/threads' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_JWT_TOKEN' \
--header 'X-App-Id: YOUR_APP_ID' \
--data '{
"schemaAwarenessData": { /* schema awareness data */ },
"input": {
"operations": [
{
"type": "createComment",
"threadId": "thread-123",
"content": "Please clarify this point."
}
]
},
"format": "shorthand",
"experimental_documentOptions": {
"documentId": "your-document-id",
"userId": "ai-assistant"
},
"experimental_commentsOptions": {
"threadData": {
"source": "ai"
},
"commentData": {
"source": "ai"
}
}
}'
Schema awareness prompt
POST /v3/ai/toolkit/schema-awareness-promptReturns a prompt that describes the editor schema for the requested format.
Request body:
schemaAwarenessData(SchemaAwarenessData, required)format?('json' | 'shorthand', optional)
Response:
prompt(string)
Error handling
The API uses standard HTTP error codes:
400 Bad Request: Invalid body, invalid format, missing document source, or missing Document Server credentials401 Unauthorized: Missing or invalid JWT or App ID404 Not Found: Unknown endpoint or tool422 Unprocessable Entity: Validation failed429 Too Many Requests: Duplicate request or rate-limit protection500 Internal Server Error: Unexpected server error502 Bad Gateway: Failed to load or save the Tiptap Cloud document