Code Examples
Explore common use cases for the Synaplan API with these code snippets.
1. Chat Completion (OpenAI SDK)
Since Synaplan is OpenAI-compatible, you can use the official OpenAI library. The
compatible endpoints live under /v1 on the instance root (not under
/api/v1, which is Synaplan's own REST API):
Node.js / TypeScript
import OpenAI from 'openai';
const openai = new OpenAI({
apiKey: 'YOUR_SYNAPLAN_API_KEY',
baseURL: 'https://web.synaplan.com/v1',
});
async function main() {
const chatCompletion = await openai.chat.completions.create({
messages: [{ role: 'user', content: 'What is Synaplan?' }],
model: 'gpt-5.4',
});
console.log(chatCompletion.choices[0].message.content);
}
main();
2. Document Upload for RAG
Upload one or more files to be processed and indexed for semantic search. group_key
is the knowledge folder; process_level decides how far the pipeline runs (store,
extract, vectorize, full). Integrations should set source so the file is labelled
by origin.
cURL
curl -X POST "https://web.synaplan.com/api/v1/files/upload" \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "files[]=@/path/to/your/document.pdf" \
-F "group_key=knowledge_base" \
-F "process_level=vectorize"
Search the indexed text afterwards with POST /api/v1/rag/search (query, limit,
group_key).
3. Streaming Chat Responses (SSE)
Use the native EventSource API in the browser to receive real-time updates.
JavaScript
// 1. Get a short-lived SSE token first (via your backend or API key)
const response = await fetch('https://web.synaplan.com/api/v1/auth/token', {
headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
});
const { token } = await response.json();
// 2. Connect to the stream
const eventSource = new EventSource(`https://web.synaplan.com/api/v1/messages/stream?token=${token}`);
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.content) {
process.stdout.write(data.content);
}
};
eventSource.onerror = (err) => {
console.error("EventSource failed:", err);
eventSource.close();
};
SSE carries the AI answer tokens and, with multi-task (DAG) routing, plan progress events (plan, task_update, task_chunk, task_file, task_progress).
4. Realtime WebSocket Events (Centrifugo)
Live-support events — human takeover, typing indicators, operator notifications — are delivered over WebSockets instead of SSE. Synaplan runs a Centrifugo gateway behind the same origin (/connection/websocket); the backend issues short-lived JWTs for the connection and for each channel subscription. See Architecture & Realtime for the full design.
JavaScript (centrifuge-js)
import { Centrifuge } from 'centrifuge'
// 1. Get a connection token (authenticated user)
const { token } = await fetch('https://web.synaplan.com/api/v1/realtime/token', {
method: 'POST',
headers: { 'X-API-Key': 'YOUR_API_KEY' }
}).then(r => r.json())
// 2. Connect to the same-origin WebSocket endpoint
const centrifuge = new Centrifuge('wss://web.synaplan.com/connection/websocket', { token })
centrifuge.connect()
// 3. Subscribe to a channel with a per-channel subscription token
const channel = 'widget:operators.YOUR_WIDGET_ID'
const sub = centrifuge.newSubscription(channel, {
getToken: () =>
fetch('https://web.synaplan.com/api/v1/realtime/subscribe', {
method: 'POST',
headers: { 'X-API-Key': 'YOUR_API_KEY', 'Content-Type': 'application/json' },
body: JSON.stringify({ channel })
}).then(r => r.json()).then(d => d.token)
})
sub.on('publication', (ctx) => {
// Envelope: { type: 'notification', ts: 1700000000123, data: { ... } }
console.log(ctx.data)
})
sub.subscribe()
Subscriptions are authorized server-side: the subscribe endpoint only issues a token if the authenticated user (or widget visitor) is allowed to read that channel.
5. Multi-Channel Integration (WhatsApp)
WhatsApp is an inbound channel: Meta delivers messages to Synaplan's webhook, the AI answers on the same number, and there is no public "send a WhatsApp message" endpoint. What the API does expose is the binding between your number and an assistant — which published assistant answers incoming WhatsApp messages:
cURL
# Which assistant answers on WhatsApp right now
curl -sS "https://web.synaplan.com/api/v1/channels/whatsapp/assistant" \
-H "Authorization: Bearer YOUR_API_KEY"
# Bind a published assistant (null = the usual chat routing)
curl -sS -X PUT "https://web.synaplan.com/api/v1/channels/whatsapp/assistant" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"agentId": 42}'
Setup of the number, tokens and webhook: WhatsApp channel.
6. cURL / Node.js / PHP Quick Reference
cURL
Chat (OpenAI-compatible)
curl -sS -H "Authorization: Bearer $SYNAPLAN_API_KEY" -H "Content-Type: application/json" \
-X POST https://web.synaplan.com/v1/chat/completions \
-d '{"model":"gpt-5.4","messages":[{"role":"user","content":"Hello"}]}'
Chat streaming
curl -sS -H "Authorization: Bearer $SYNAPLAN_API_KEY" -H "Content-Type: application/json" \
-X POST https://web.synaplan.com/v1/chat/completions \
-d '{"model":"gpt-5.4","stream":true,"messages":[{"role":"user","content":"Stream please"}]}'
Images, video and audio generation
There is no /v1/images/generations endpoint. Media generation runs through Synaplan's
own chat pipeline — the multi-task planner routes a "draw me…"
step to the account's image / video / audio model: send the request with
POST /api/v1/messages/send and read the SSE stream (task_file events carry the
generated files), or call the MCP tool synaplan_chat. /v1/chat/completions is text
(and tool calls) only; image inputs are not supported on it yet.
Legacy REST chat + SSE (api.php)
last=$(curl -sS -H "Authorization: Bearer $SYNAPLAN_API_KEY" \
-F action=messageNew -F message="Who are you?" https://web.synaplan.com/api.php | jq -r '.lastIds[0]')
curl -N -sS -H "Authorization: Bearer $SYNAPLAN_API_KEY" \
-F action=chatStream -F lastIds="$last" https://web.synaplan.com/api.php
Models list
curl -sS -H "Authorization: Bearer $SYNAPLAN_API_KEY" https://web.synaplan.com/v1/models
# per-model prices (priceIn / priceOut) come from Synaplan's own API:
curl -sS -H "Authorization: Bearer $SYNAPLAN_API_KEY" https://web.synaplan.com/api/v1/config/models
Audio transcription
curl -sS -H "Authorization: Bearer $SYNAPLAN_API_KEY" -X POST \
-F file=@/path/to/audio.m4a \
https://web.synaplan.com/v1/audio/transcriptions
Node.js (axios)
const axios = require('axios');
async function chat() {
const res = await axios.post('https://web.synaplan.com/v1/chat/completions', {
model: 'gpt-5.4',
messages: [{ role: 'user', content: 'Hello' }]
}, {
headers: { Authorization: `Bearer ${process.env.SYNAPLAN_API_KEY}` }
});
console.log(res.data);
}
chat();
PHP
<?php
$ch = curl_init('https://web.synaplan.com/v1/chat/completions');
$payload = json_encode([
'model' => 'gpt-5.4',
'messages' => [ ['role'=>'user','content'=>'Hello'] ]
]);
curl_setopt_array($ch, [
CURLOPT_POST => 1,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('SYNAPLAN_API_KEY'),
'Content-Type: application/json'
],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true
]);
$res = curl_exec($ch);
curl_close($ch);
echo $res;
7. Outbound MCP OAuth connectors
Notion and Higgsfield do not accept a static token. Create the server row, then start the browser sign-in. Full walkthrough: MCP OAuth connectors.
Example server rows
{
"name": "Notion",
"url": "https://mcp.notion.com/mcp",
"auth_mode": "oauth",
"enabled": true,
"allow_write": false
}
{
"name": "Higgsfield",
"url": "https://mcp.higgsfield.ai/mcp",
"auth_mode": "oauth",
"enabled": true,
"allow_write": false
}
cURL — create the row, then start sign-in
# Requires MCP.OAUTH_CONNECTORS_ENABLED=1 on the installation.
curl -X POST "https://web.synaplan.com/api/v1/mcp-servers" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"Notion","url":"https://mcp.notion.com/mcp","auth_mode":"oauth"}'
curl -X POST "https://web.synaplan.com/api/v1/mcp-servers/42/oauth/start" \
-H "Authorization: Bearer YOUR_API_KEY"
# Open authorize_url in the browser. After consent, Synaplan redirects to
# /channels/mcp?connected=42