Skip to main content

Overview

The Query API is Sorcia’s core endpoint for searching your knowledge base. It uses hybrid search (vector + text) and AI to provide accurate, cited answers to natural language questions.
Base URL: https://api.sorcia.ai/api/ai/query
Method: POST
Authentication: Required (Bearer token or API key)

Quick Example

curl -X POST https://api.sorcia.ai/api/ai/query \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "question": "What is our vacation policy?"
  }'

Request Parameters

Required Parameters

question
string
required
The question or search query in natural languageExample: “How do I submit expense reports?”

Optional Parameters

filters
object
Filters to narrow search results
options
object
Query behavior options

Response Format

Success Response (200)

{
  "answer": "Based on your Employee Handbook, all full-time employees receive 20 days of paid time off (PTO) per year...",
  "confidence": 0.95,
  "citations": [
    {
      "id": "doc_123",
      "title": "Employee Handbook 2024",
      "source": "google-drive",
      "url": "https://drive.google.com/file/d/abc123",
      "snippet": "All full-time employees receive 20 days of paid time off...",
      "relevance": 0.92,
      "metadata": {
        "author": "HR Team",
        "updated_at": "2024-01-15T10:00:00Z",
        "file_type": "pdf"
      }
    }
  ],
  "related_questions": [
    "How do I request time off?",
    "Can I roll over unused vacation days?",
    "What's the policy for sick leave?"
  ],
  "query_metadata": {
    "query_id": "qry_abc123",
    "response_time_ms": 1247,
    "sources_searched": 847,
    "sources_used": 3
  }
}

Response Fields

answer
string
AI-generated answer based on retrieved documents
confidence
number
Confidence score (0-1) indicating answer quality
citations
array
Source documents used to generate the answer
Suggested follow-up questions
query_metadata
object
Query performance and statistics

Advanced Usage

Filtering by Source

Search only specific integrations:
const response = await fetch('https://api.sorcia.ai/api/ai/query', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${accessToken}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    question: 'Latest product roadmap updates',
    filters: {
      sources: ['notion', 'github'],
      dateRange: {
        start: '2024-01-01',
        end: '2024-12-31'
      }
    }
  })
});

Streaming Responses

For real-time answer generation, use streaming:
const response = await fetch('https://api.sorcia.ai/api/ai/query', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${accessToken}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    question: 'Explain our security architecture',
    options: { stream: true }
  })
});

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: ')) {
      const data = JSON.parse(line.slice(6));
      console.log(data.delta); // Incremental text
    }
  }
}

Server-Sent Events Format

data: {"delta": "Based on ", "done": false}

data: {"delta": "your Security ", "done": false}

data: {"delta": "Policy...", "done": false}

data: {"done": true, "citations": [...]}

Error Responses

Bad Request (400)

{
  "error": "Bad Request",
  "message": "Question is required",
  "code": "MISSING_QUESTION"
}
Common Causes:
  • Missing question parameter
  • Invalid filter format
  • Malformed JSON

Unauthorized (401)

{
  "error": "Unauthorized",
  "message": "Invalid or expired token"
}
Solution: Refresh your access token

Rate Limited (429)

{
  "error": "Rate Limit Exceeded",
  "message": "Too many requests",
  "retry_after": 60
}
Solution: Implement exponential backoff

No Results (200)

{
  "answer": "I couldn't find any relevant information about that in your knowledge base.",
  "confidence": 0.0,
  "citations": [],
  "related_questions": []
}
A 200 status with empty citations means no relevant documents were found, not an error.

Rate Limits

Query API limits by plan:
PlanQueries/MonthQueries/Minute
Free1005
Pro1,00020
EnterpriseUnlimited100
Monitor usage via the X-RateLimit-* response headers

Best Practices

  • Use natural language
  • Be specific (e.g., “Q4 2024 sales metrics” vs “sales”)
  • Include context when needed
  • Avoid overly broad questions
  • Filter by source when you know where info lives
  • Use date ranges for time-sensitive queries
  • Combine filters for precision
  • Confidence < 0.5: Show warning to users
  • Confidence < 0.3: Suggest refining question
  • Always show citations so users can verify
  • Cache identical queries for 5-10 minutes
  • Use query_id for deduplication
  • Invalidate cache on document updates
  • Retry on 5xx errors with exponential backoff
  • Don’t retry on 4xx errors (client errors)
  • Set maximum retry limit (e.g., 3 attempts)

Code Examples

React Hook

import { useState } from 'react';

export function useQuery() {
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const query = async (question: string) => {
    setLoading(true);
    setError(null);
    
    try {
      const response = await fetch('https://api.sorcia.ai/api/ai/query', {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${getAccessToken()}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({ question })
      });
      
      if (!response.ok) {
        throw new Error('Query failed');
      }
      
      return await response.json();
    } catch (err) {
      setError(err.message);
      throw err;
    } finally {
      setLoading(false);
    }
  };
  
  return { query, loading, error };
}

Python Client

class SorciaClient:
    def __init__(self, access_token):
        self.access_token = access_token
        self.base_url = 'https://api.sorcia.ai'
    
    def query(self, question, **kwargs):
        """Query the knowledge base"""
        response = requests.post(
            f'{self.base_url}/api/ai/query',
            headers={'Authorization': f'Bearer {self.access_token}'},
            json={'question': question, **kwargs}
        )
        response.raise_for_status()
        return response.json()
    
    def query_with_retry(self, question, max_retries=3):
        """Query with automatic retry on failure"""
        for attempt in range(max_retries):
            try:
                return self.query(question)
            except requests.exceptions.RequestException as e:
                if attempt == max_retries - 1:
                    raise
                time.sleep(2 ** attempt)  # Exponential backoff

Next Steps