Query & Retrieval
The Synvo API provides powerful query processing and intelligent file retrieval capabilities. These endpoints enable semantic search across your documents and conversational interactions with your data.
Authentication
All endpoints require authentication via either:
- Bearer Token:
Authorization: Bearer <token> - API Key:
X-API-Key: <api_key>
Base URL
https://api.synvo.aiSubmit Query
Sends a message for processing and receives an intelligent response. Supports streaming, file search, web search, and various processing modes.
Endpoint: POST /ai/query
Content-Type: multipart/form-data
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
payload | string | Yes | - | JSON string with messages array |
model | string | No | "synvo" | Model to use (synvo, gpt, etc.) |
agent_model | string | No | "gpt" | Agent model for tool use |
parent_cuid | string | No | - | Parent conversation ID for threading |
streaming | boolean | No | false | Enable streaming responses |
force_search | boolean | No | false | Force file search |
mcp | boolean | No | false | Enable web search |
agent | boolean | No | false | Enable deep research mode |
profiling | boolean | No | false | Enable performance profiling |
model_args | string | No | - | JSON string containing model specific args |
platform | string | No | "web" | Platform identifier (web, api, mobile) |
Payload Format
The payload parameter should be a JSON string containing a messages array:
{
"messages": [
{
"role": "user",
"content": [
{
"type": "text",
"text": "Your question here"
}
]
}
]
}Message Roles
system- System instructionsuser- User messagesassistant- Assistant responsestool- Tool execution results
Content Types
text- Plain text contentfile- File attachments withfile_idandpath
Example Request
curl -X POST "https://api.synvo.ai/ai/query" \
-H "X-API-Key: ${API-KEY}" \
-F 'payload={"messages":[{"role":"user","content":[{"type":"text","text":"What is the capital of France?"}]}]}' \
-F "model=synvo" \
-F "streaming=false"import requests
import json
token = "<BEARER_TOKEN>"
url = "https://api.synvo.ai/ai/query"
headers = {"X-API-Key": f"{token}"}
payload = {
"messages": [
{
"role": "user",
"content": [
{"type": "text", "text": "What is the capital of France?"}
]
}
]
}
data = {
"payload": json.dumps(payload),
"model": "synvo",
"streaming": "false"
}
response = requests.post(url, data=data, headers=headers, timeout=60)
response.raise_for_status()
print(response.json())const token = "<BEARER_TOKEN>";
const payload = {
messages: [
{
role: "user",
content: [
{ type: "text", text: "What is the capital of France?" }
]
}
]
};
const formData = new FormData();
formData.append("payload", JSON.stringify(payload));
formData.append("model", "synvo");
formData.append("streaming", "false");
const response = await fetch("https://api.synvo.ai/ai/query", {
method: "POST",
headers: {
"X-API-Key": `${token}`,
},
body: formData,
});
if (!response.ok) {
throw new Error(`Request failed: ${response.status}`);
}
console.log(await response.json());Example Response
{
"success": true,
"response": {
"role": "assistant",
"content": [
{
"type": "text",
"text": "The capital of France is Paris."
}
],
"cuid": "msg_abc123xyz",
"created_at": "2024-01-15T10:30:00Z"
},
"suid": "sess_def456uvw",
"summary": "Question about French capital",
"timestamp": "2024-01-15T10:30:00Z"
}Streaming Response
When streaming=true, the response is sent as Server-Sent Events (SSE):
Content-Type: text/event-stream
data: {"type": "token", "content": "The"}
data: {"type": "token", "content": " capital"}
data: {"type": "token", "content": " of"}
data: {"type": "done", "response": {...}}Response Codes
200- Query processed successfully400- Bad request (invalid payload or parameters)401- Unauthorized
Search Files
Uses intelligent search to find files relevant to a query and returns file information.
Endpoint: POST /ai/search
Content-Type: application/x-www-form-urlencoded
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
message | string | Yes | Search query |
Example Request
curl -X POST "https://api.synvo.ai/ai/search" \
-H "X-API-Key: ${API-KEY}" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "message=financial reports for Q4"import requests
token = "<BEARER_TOKEN>"
url = "https://api.synvo.ai/ai/search"
data = {"message": "financial reports for Q4"}
headers = {"X-API-Key": f"{token}"}
response = requests.post(url, data=data, headers=headers, timeout=30)
response.raise_for_status()
print(response.json())const token = "<BEARER_TOKEN>";
const params = new URLSearchParams({
message: "financial reports for Q4"
});
const response = await fetch("https://api.synvo.ai/ai/search", {
method: "POST",
headers: {
"X-API-Key": `${token}`,
},
body: params,
});
if (!response.ok) {
throw new Error(`Request failed: ${response.status}`);
}
console.log(await response.json());Example Response
[
{
"file_id": "abc123xyz",
"file_path": "/reports/q4-financial.pdf",
"file_name": "q4-financial.pdf",
"file_type": "application/pdf",
"created_at": "2024-01-15T10:30:00Z"
},
{
"file_id": "def456uvw",
"file_path": "/reports/q4-summary.docx",
"file_name": "q4-summary.docx",
"file_type": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"created_at": "2024-01-14T15:45:00Z"
}
]Response Codes
200- Search completed successfully401- Unauthorized
Advanced Features
Conversation Threading
Use parent_cuid to continue existing conversations:
{
"payload": "{\"messages\": [...]}",
"parent_cuid": "msg_previous123"
}File Context
Include files in your queries by adding file content to messages:
{
"messages": [
{
"role": "user",
"content": [
{
"type": "text",
"text": "Analyze this document"
},
{
"type": "file",
"file_id": "abc123xyz",
"path": "/documents/report.pdf"
}
]
}
]
}Web Search Mode
Enable web search with mcp=true to include external information:
{
"payload": "{\"messages\": [...]}",
"mcp": true
}Deep Research Mode
Enable agent mode with agent=true for complex multi-step research:
{
"payload": "{\"messages\": [...]}",
"agent": true,
"agent_model": "gpt"
}Model Options
Available Models
synvo- Default Synvo model (recommended)gpt- OpenAI GPT models- Custom models as configured
Model Arguments
Pass model-specific parameters via model_args:
{
"model_args": "{\"temperature\": 0.7, \"max_tokens\": 1000}"
}Integration Examples
Chat Interface
class SynvoChat:
def __init__(self, api_key):
self.api_key = api_key
self.session_id = None
self.conversation = []
def send_message(self, text, streaming=False):
self.conversation.append({
"role": "user",
"content": [{"type": "text", "text": text}]
})
payload = {"messages": self.conversation}
data = {
"payload": json.dumps(payload),
"streaming": str(streaming).lower(),
"parent_cuid": self.session_id
}
response = requests.post(
"https://api.synvo.ai/ai/query",
data=data,
headers={"X-API-Key": self.api_key}
)
result = response.json()
self.session_id = result.get("suid")
self.conversation.append(result["response"])
return result["response"]["content"][0]["text"]
# Usage
chat = SynvoChat("your-api-key")
response = chat.send_message("Hello, how are you?")
print(response)class SynvoChat {
constructor(apiKey) {
this.apiKey = apiKey;
this.sessionId = null;
this.conversation = [];
}
async sendMessage(text, streaming = false) {
this.conversation.push({
role: "user",
content: [{ type: "text", text }]
});
const formData = new FormData();
formData.append("payload", JSON.stringify({
messages: this.conversation
}));
formData.append("streaming", streaming.toString());
if (this.sessionId) {
formData.append("parent_cuid", this.sessionId);
}
const response = await fetch("https://api.synvo.ai/ai/query", {
method: "POST",
headers: {
"X-API-Key": this.apiKey
},
body: formData
});
const result = await response.json();
this.sessionId = result.suid;
this.conversation.push(result.response);
return result.response.content[0].text;
}
}
// Usage
const chat = new SynvoChat("your-api-key");
const response = await chat.sendMessage("Hello, how are you?");
console.log(response);Document Analysis
def analyze_document(api_key, file_id, question):
"""Analyze a document with a specific question"""
payload = {
"messages": [
{
"role": "user",
"content": [
{"type": "text", "text": question},
{"type": "file", "file_id": file_id}
]
}
]
}
data = {
"payload": json.dumps(payload),
"force_search": "true"
}
response = requests.post(
"https://api.synvo.ai/ai/query",
data=data,
headers={"X-API-Key": api_key}
)
return response.json()["response"]["content"][0]["text"]
# Usage
result = analyze_document(
"your-api-key",
"file123",
"What are the key findings in this report?"
)
print(result)async function analyzeDocument(apiKey, fileId, question) {
const payload = {
messages: [
{
role: "user",
content: [
{ type: "text", text: question },
{ type: "file", file_id: fileId }
]
}
]
};
const formData = new FormData();
formData.append("payload", JSON.stringify(payload));
formData.append("force_search", "true");
const response = await fetch("https://api.synvo.ai/ai/query", {
method: "POST",
headers: {
"X-API-Key": apiKey
},
body: formData
});
const result = await response.json();
return result.response.content[0].text;
}
// Usage
const result = await analyzeDocument(
"your-api-key",
"file123",
"What are the key findings in this report?"
);
console.log(result);Best Practices
Query Optimization
- Be Specific: Use clear, specific queries for better results
- Context Length: Keep conversations focused to avoid context limits
- File References: Include relevant files when asking document-specific questions
Performance Tips
- Streaming: Use streaming for long responses to improve user experience
- Model Selection: Choose appropriate models based on task complexity
- Search First: Use
/ai/searchto find relevant files before querying
Rate Limiting
- Standard rate limits apply per API key
- Streaming requests may have different limits
- Monitor response headers for rate limit information
Error Handling
Common Error Responses
{
"error": "Invalid payload format",
"code": "INVALID_PAYLOAD"
}{
"error": "Model not available",
"code": "MODEL_UNAVAILABLE"
}Error Codes
INVALID_PAYLOAD- Malformed JSON in payload parameterMODEL_UNAVAILABLE- Requested model is not availableRATE_LIMITED- Too many requestsCONTEXT_TOO_LONG- Message context exceeds limitsSEARCH_FAILED- File search operation failed
Handling Query Errors
def safe_query(api_key, payload, max_retries=3):
"""Safely perform query with error handling"""
for attempt in range(max_retries):
try:
data = {
"payload": json.dumps(payload),
"model": "synvo"
}
response = requests.post(
"https://api.synvo.ai/ai/query",
data=data,
headers={"X-API-Key": api_key},
timeout=60
)
response.raise_for_status()
return response.json()
except requests.exceptions.HTTPError as e:
if e.response.status_code == 400:
error_data = e.response.json()
if error_data.get("code") == "INVALID_PAYLOAD":
print("Invalid payload format")
return None
elif e.response.status_code == 429:
print(f"Rate limited, retrying in {2**attempt} seconds...")
time.sleep(2**attempt)
continue
else:
print(f"Query failed: {e}")
return None
except Exception as e:
print(f"Unexpected error: {e}")
if attempt < max_retries - 1:
time.sleep(2**attempt)
continue
return None
# Usage
payload = {
"messages": [
{
"role": "user",
"content": [{"type": "text", "text": "Hello"}]
}
]
}
result = safe_query("your-api-key", payload)
if result:
print("Query successful")async function safeQuery(apiKey, payload, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const formData = new FormData();
formData.append("payload", JSON.stringify(payload));
formData.append("model", "synvo");
const response = await fetch("https://api.synvo.ai/ai/query", {
method: "POST",
headers: { "X-API-Key": apiKey },
body: formData
});
if (!response.ok) {
if (response.status === 400) {
const errorData = await response.json();
if (errorData.code === "INVALID_PAYLOAD") {
console.log("Invalid payload format");
return null;
}
} else if (response.status === 429) {
console.log(`Rate limited, retrying in ${2**attempt} seconds...`);
await new Promise(resolve => setTimeout(resolve, (2**attempt) * 1000));
continue;
} else {
throw new Error(`Request failed: ${response.status}`);
}
}
return await response.json();
} catch (error) {
console.log(`Query error (attempt ${attempt + 1}): ${error.message}`);
if (attempt < maxRetries - 1) {
await new Promise(resolve => setTimeout(resolve, (2**attempt) * 1000));
continue;
}
return null;
}
}
}
// Usage
const payload = {
messages: [
{
role: "user",
content: [{ type: "text", text: "Hello" }]
}
]
};
const result = await safeQuery("your-api-key", payload);
if (result) {
console.log("Query successful");
}Streaming Implementation
Python Streaming
import requests
import json
def stream_query(api_key, payload):
"""Stream a query response"""
data = {
"payload": json.dumps(payload),
"streaming": "true",
"model": "synvo"
}
response = requests.post(
"https://api.synvo.ai/ai/query",
data=data,
headers={"X-API-Key": api_key},
stream=True
)
for line in response.iter_lines():
if line:
line = line.decode('utf-8')
if line.startswith('data: '):
try:
data = json.loads(line[6:])
if data.get("type") == "token":
print(data["content"], end="", flush=True)
elif data.get("type") == "done":
print("\n\nStream complete!")
return data["response"]
except json.JSONDecodeError:
continue
# Usage
payload = {
"messages": [
{
"role": "user",
"content": [{"type": "text", "text": "Tell me a story"}]
}
]
}
stream_query("your-api-key", payload)JavaScript Streaming
async function streamQuery(apiKey, payload) {
const formData = new FormData();
formData.append("payload", JSON.stringify(payload));
formData.append("streaming", "true");
formData.append("model", "synvo");
const response = await fetch("https://api.synvo.ai/ai/query", {
method: "POST",
headers: { "X-API-Key": apiKey },
body: formData
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
const lines = chunk.split('\n');
for (const line of lines) {
if (line.startsWith('data: ')) {
try {
const data = JSON.parse(line.slice(6));
if (data.type === "token") {
process.stdout.write(data.content);
} else if (data.type === "done") {
console.log("\n\nStream complete!");
return data.response;
}
} catch (e) {
// Skip invalid JSON
}
}
}
}
}
// Usage
const payload = {
messages: [
{
role: "user",
content: [{ type: "text", text: "Tell me a story" }]
}
]
};
await streamQuery("your-api-key", payload);