-
Notifications
You must be signed in to change notification settings - Fork 0
API_REFERENCE_FULL
Version: 2.0.0
Base URL: http://localhost:8000/api/v1 (or your production URL)
PATAS API does not require authentication by default. For production, it is recommended to configure API key middleware or use a reverse proxy (Caddy, nginx).
GET /api/v1/health
Check API status and system readiness.
Response:
{
"status": "ok",
"version": "2.0.0",
"core_ready": true
}Example:
curl http://localhost:8000/api/v1/healthPOST /api/v1/messages/ingest
Ingest messages into PATAS storage. Messages are saved with idempotency via external_id.
Request Body:
{
"messages": [
{
"id": "msg_001",
"text": "Your message text here",
"is_spam": true,
"meta": {
"sender": "user123",
"source": "chat456",
"language": "en",
"country": "US"
},
"timestamp": "2025-01-15T10:00:00Z"
}
]
}Request Model:
-
messages(required): List[APIMsgInput]-
id(optional): External message ID (for idempotency) -
text(required): Message text content -
is_spam(optional): Spam label (True/False/None) -
meta(optional): JSON metadata (sender, source, language, country, etc.) -
timestamp(optional): ISO 8601 timestamp (default: now)
-
Response:
{
"ingested_count": 1,
"last_id": 123,
"message": "Messages ingested successfully"
}Examples:
Python:
import requests
response = requests.post(
"http://localhost:8000/api/v1/messages/ingest",
json={
"messages": [
{
"id": "msg_001",
"text": "Buy now! http://spam.com",
"is_spam": True,
"meta": {"sender": "user123"}
}
]
}
)
print(response.json())cURL:
curl -X POST http://localhost:8000/api/v1/messages/ingest \
-H "Content-Type: application/json" \
-d '{
"messages": [
{
"id": "msg_001",
"text": "Buy now! http://spam.com",
"is_spam": true
}
]
}'JavaScript:
const response = await fetch('http://localhost:8000/api/v1/messages/ingest', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
messages: [
{
id: 'msg_001',
text: 'Buy now! http://spam.com',
is_spam: true
}
]
})
});
const data = await response.json();Errors:
-
400: Empty message list -
500: Database error
POST /api/v1/patterns/mine
Run pattern mining pipeline on recent messages. Analyzes messages and creates Pattern and Rule objects.
Request Body:
{
"days": 7,
"use_llm": false,
"min_spam_count": 10
}Request Model:
-
days(optional, default: 7): Number of days to analyze (1-365) -
use_llm(optional, default: false): Use LLM for pattern discovery -
min_spam_count(optional, default: 10): Minimum spam messages required for pattern
Response:
{
"patterns_created": 5,
"rules_created": 5,
"messages_processed": 1000,
"spam_count": 750,
"ham_count": 250
}Examples:
Python:
response = requests.post(
"http://localhost:8000/api/v1/patterns/mine",
json={"days": 7, "use_llm": True, "min_spam_count": 10}
)
result = response.json()
print(f"Created {result['patterns_created']} patterns")cURL:
curl -X POST http://localhost:8000/api/v1/patterns/mine \
-H "Content-Type: application/json" \
-d '{"days": 7, "use_llm": false}'Errors:
-
400: Pattern mining failed (см. detail в ответе)
Notes:
- If
use_llm=true,OPENAI_API_KEYorPATAS_OPENAI_API_KEYis required - Semantic mining is enabled by default (if
enable_semantic_mining=truein config)
GET /api/v1/patterns
Get list of discovered patterns.
Query Parameters:
-
limit(optional, default: 100): Maximum number of patterns (1-1000) -
offset(optional, default: 0): Pagination offset -
pattern_type(optional): Filter by type (url, phone, text, meta, signature, keyword)
Response:
[
{
"id": 1,
"type": "url",
"description": "URL pattern: http://spam.com",
"examples": ["Buy now! http://spam.com", "Click here: http://spam.com"],
"created_at": "2025-01-15T10:00:00Z",
"updated_at": "2025-01-15T10:00:00Z"
}
]Examples:
Python:
response = requests.get(
"http://localhost:8000/api/v1/patterns",
params={"limit": 50, "pattern_type": "url"}
)
patterns = response.json()cURL:
curl "http://localhost:8000/api/v1/patterns?limit=50&pattern_type=url"GET /api/v1/rules
Get list of rules with optional evaluation metrics.
Query Parameters:
-
status(optional): Filter by status (candidate, shadow, active, deprecated) -
limit(optional, default: 100): Maximum number of rules (1-1000) -
offset(optional, default: 0): Pagination offset -
include_evaluation(optional, default: false): Include latest evaluation metrics
Response:
[
{
"id": 1,
"pattern_id": 1,
"status": "shadow",
"sql_expression": "SELECT id FROM messages WHERE text LIKE '%http://spam.com%'",
"origin": "llm",
"created_at": "2025-01-15T10:00:00Z",
"updated_at": "2025-01-15T10:00:00Z",
"evaluation": {
"hits_total": 100,
"spam_hits": 95,
"ham_hits": 5,
"precision": 0.95,
"coverage": 0.15,
"time_period_start": "2025-01-08T10:00:00Z",
"time_period_end": "2025-01-15T10:00:00Z"
}
}
]Examples:
Python:
response = requests.get(
"http://localhost:8000/api/v1/rules",
params={"status": "active", "include_evaluation": True}
)
rules = response.json()cURL:
curl "http://localhost:8000/api/v1/rules?status=active&include_evaluation=true"POST /api/v1/rules/eval-shadow
Evaluate shadow rules on recent messages. Computes metrics (precision, coverage, spam_hits, ham_hits).
Request Body:
{
"rule_ids": [1, 2, 3],
"days": 7
}Request Model:
-
rule_ids(optional): List of specific rule IDs to evaluate (empty = all shadow rules) -
days(optional, default: 7): Time window for evaluation (1-365)
Response:
{
"evaluated_count": 3,
"message": "Rules evaluated successfully"
}Examples:
Python:
response = requests.post(
"http://localhost:8000/api/v1/rules/eval-shadow",
json={"rule_ids": [1, 2, 3], "days": 7}
)
result = response.json()cURL:
curl -X POST http://localhost:8000/api/v1/rules/eval-shadow \
-H "Content-Type: application/json" \
-d '{"rule_ids": [1, 2, 3], "days": 7}'Notes:
- If
rule_idsis not specified, all shadow rules are evaluated - Errors when evaluating individual rules are logged but do not interrupt the process
POST /api/v1/rules/promote
Promote shadow rules to active and deprecate degrading active rules. Uses configured aggressiveness profile.
Request Body: (no parameters)
Response:
{
"promoted_count": 2,
"deprecated_count": 1,
"message": "Promotion/rollback completed"
}Examples:
Python:
response = requests.post("http://localhost:8000/api/v1/rules/promote")
result = response.json()
print(f"Promoted {result['promoted_count']} rules")cURL:
curl -X POST http://localhost:8000/api/v1/rules/promoteNotes:
- Uses
aggressiveness_profilefrom configuration (conservative/balanced/aggressive) - Shadow rules are promoted if metrics meet profile thresholds
- Active rules are deprecated if metrics degrade
GET /api/v1/rules/export
Export all active rules in the specified format.
Query Parameters:
-
backend(optional, default: "sql"): Export format ("sql" or "rol")
Response (SQL):
SELECT id FROM messages WHERE text LIKE '%http://spam.com%';
SELECT id FROM messages WHERE text LIKE '%buy now%' AND text LIKE '%price%';
Response (ROL):
{
"rules": [
{
"id": 1,
"sql_expression": "SELECT id FROM messages WHERE text LIKE '%http://spam.com%'",
"pattern_id": 1
}
]
}Examples:
Python:
# SQL export
response = requests.get(
"http://localhost:8000/api/v1/rules/export",
params={"backend": "sql"}
)
sql_rules = response.text
# ROL export
response = requests.get(
"http://localhost:8000/api/v1/rules/export",
params={"backend": "rol"}
)
rol_rules = response.json()cURL:
# SQL export
curl "http://localhost:8000/api/v1/rules/export?backend=sql"
# ROL export
curl "http://localhost:8000/api/v1/rules/export?backend=rol"POST /api/v1/analyze
Main endpoint для batch анализа. Bundles the complete workflow:
- Ingest messages
- Run pattern mining (optional)
- Evaluate rules (optional)
- Export rules (optional)
Perfect for: Small-medium batch analysis, RapidAPI integration, quick prototyping.
Request Body:
{
"messages": [
{
"id": "msg_001",
"text": "Buy now! http://spam.com",
"is_spam": true,
"meta": {"sender": "user123", "source": "chat456"}
}
],
"run_mining": true,
"run_evaluation": true,
"export_backend": "sql"
}Request Model:
-
messages(required): List[APIMsgInput] -
run_mining(optional, default: true): Run pattern mining on ingested messages -
run_evaluation(optional, default: true): Evaluate candidate/shadow rules -
export_backend(optional): Export format ("sql" or "rol")
Response:
{
"patterns": [
{
"id": 1,
"type": "url",
"description": "URL pattern: http://spam.com",
"group_size": 45,
"sources_count": 3,
"senders_count": 2,
"similarity_reason": "Messages contain the same suspicious URL: http://spam.com",
"example_report_ids": ["msg_001", "msg_002", "msg_003"],
"bot_likelihood": 0.85,
"sql_query": "SELECT id, message_content, sender, source FROM reports WHERE LOWER(message_content) LIKE '%http://spam.com%'"
}
],
"rules": [
{
"id": 1,
"pattern_id": 1,
"status": "candidate",
"sql_expression": "SELECT id FROM messages WHERE text LIKE '%http://spam.com%'",
"precision": 0.95,
"coverage": 0.15,
"hits_total": 100
}
],
"export": "SELECT id FROM messages WHERE text LIKE '%http://spam.com%';",
"meta": {
"ingested_count": 10,
"patterns_created": 3,
"rules_created": 3,
"evaluation_count": 3,
"timings": {
"ingest_seconds": 0.123,
"mining_seconds": 2.456,
"evaluation_seconds": 0.789,
"total_seconds": 3.368
}
}
}Examples:
Python:
response = requests.post(
"http://localhost:8000/api/v1/analyze",
json={
"messages": [
{"id": "1", "text": "Buy now! http://spam.com", "is_spam": True},
{"id": "2", "text": "Click here: http://spam.com", "is_spam": True}
],
"run_mining": True,
"run_evaluation": True,
"export_backend": "sql"
}
)
result = response.json()
# Access patterns
for pattern in result["patterns"]:
print(f"Pattern: {pattern['description']}")
print(f"SQL: {pattern['sql_query']}")
# Access export
if result.get("export"):
print(f"Export:\n{result['export']}")cURL:
curl -X POST http://localhost:8000/api/v1/analyze \
-H "Content-Type: application/json" \
-d '{
"messages": [
{"id": "1", "text": "Buy now! http://spam.com", "is_spam": true},
{"id": "2", "text": "Click here: http://spam.com", "is_spam": true}
],
"run_mining": true,
"run_evaluation": true,
"export_backend": "sql"
}'JavaScript:
const response = await fetch('http://localhost:8000/api/v1/analyze', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
messages: [
{ id: '1', text: 'Buy now! http://spam.com', is_spam: true },
{ id: '2', text: 'Click here: http://spam.com', is_spam: true }
],
run_mining: true,
run_evaluation: true,
export_backend: 'sql'
})
});
const result = await response.json();
// Access patterns
result.patterns.forEach(pattern => {
console.log(`Pattern: ${pattern.description}`);
console.log(`SQL: ${pattern.sql_query}`);
});Errors:
-
400: Empty messages list -
500: Internal server error
Notes:
- For large datasets, use lower-level endpoints
- Semantic mining включен по умолчанию (если доступен embedding engine)
- LLM is used automatically if
OPENAI_API_KEYis set andrun_mining=true
All endpoints return standard HTTP status codes:
-
200: Success -
400: Bad Request (invalid data) -
404: Not Found (resource not found) -
500: Internal Server Error
Error format:
{
"detail": "Error message here"
}Example error handling (Python):
try:
response = requests.post("http://localhost:8000/api/v1/analyze", json=data)
response.raise_for_status()
result = response.json()
except requests.exceptions.HTTPError as e:
error_detail = e.response.json().get("detail", "Unknown error")
print(f"Error: {error_detail}")PATAS API does not have built-in rate limiting. For production, it is recommended to configure rate limiting at the reverse proxy level (Caddy, nginx) or use middleware.
Current API version: 2.0.0
All endpoints are under /api/v1/. Future breaking changes will be in /api/v2/.
- API Quickstart — quick start in 5 minutes
- Examples — practical code examples
- Integration Guide — integration guide