Tutorial

Generate Context for Users

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.

Important Note

⚠️ Query Usage Guide

  • Queries will only provide context based on uploaded files
  • If no files have been uploaded, queries will return empty responses
  • Make sure to upload relevant files before making queries for meaningful results

For example:

  1. Upload your documents using the /file/upload endpoint
  2. Wait for processing to complete (check status with /file/status)
  3. Then submit queries to get relevant context from your uploaded files

This ensures your queries have the necessary document context to provide accurate responses.

Authentication

All endpoints require authentication via:

  • API Key: X-API-Key: <api_key>

Base URL

https://api.synvo.ai

Submit Query

Processes queries with reference to all the uploaded files and output relevant context that supports the query.

Endpoint: POST /ai/query

Content-Type: multipart/form-data

Parameters

ParameterTypeRequiredDefaultDescription
payloadstringYes-JSON string containing messages array for query processing
sub_user_namestringNodefaultUser isolation identifier for scoping queries to specific users
final_answerstringNofalseWhether to return a final summarized answer

Payload Format

The payload parameter should be a JSON string containing a messages array:

{
  "messages": [
    {
      "role": "user",
      "content": [
        {
          "type": "text",
          "text": "Your question here"
        }
      ]
    }
  ]
}

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

api_key = "<API_KEY>"
url = "https://api.synvo.ai/ai/query"
headers = {"X-API-Key": api_key}

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 api_key = "<API_KEY>";

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": apiKey,
  },
  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"
}

[Upcoming Feature] 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 successfully
  • 400 - 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

ParameterTypeRequiredDescription
messagestringYesSearch 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

api_key = "<API_KEY>"
url = "https://api.synvo.ai/ai/search"
data = {"message": "financial reports for Q4"}
headers = {"X-API-Key": api_key}

response = requests.post(url, data=data, headers=headers, timeout=30)
response.raise_for_status()
print(response.json())
const api_key = "<API_KEY>";
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": apiKey,
  },
  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 successfully
  • 401 - Unauthorized

Advanced Features

File Context

File-specific querying is coming soon! This feature will allow you to include specific files in your queries by adding file content to messages. Here's how it will work:

{
  "messages": [
    {
      "role": "user",
      "content": [
        {
          "type": "text",
          "text": "Analyze this document"
        },
        {
          "type": "file",
          "file_id": "abc123xyz",
          "path": "/documents/report.pdf"
        }
      ]
    }
  ]
}

Best Practices

Query Optimization

  1. Be Specific: Use clear, specific queries for better results
  2. Context Length: Keep conversations focused to avoid context limits
  3. File References: Include relevant files when asking document-specific questions

Performance Tips

  1. Streaming: Use streaming for long responses to improve user experience
  2. Model Selection: Choose appropriate models based on task complexity
  3. Search First: Use /ai/search to 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 parameter
  • MODEL_UNAVAILABLE - Requested model is not available
  • RATE_LIMITED - Too many requests
  • CONTEXT_TOO_LONG - Message context exceeds limits
  • SEARCH_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");
}