Gateway ARQ API
Complete API Reference v1.5.0 - 44 Endpoints
Introduction
Gateway ARQ is a real-time data ingestion system for WebCom TLC, WebTV CDN, and Centralino (jPBX). This API provides access to call data, system metrics, blacklist management, and real-time updates via WebSocket.
🔐 Authentication
⚠️ REQUIRED - All endpoints now require API key authentication
All API requests MUST include a valid API key in the X-API-Key header.
For WebSocket connections, use the ?api_key=xxx query parameter.
Example Request
curl -H "X-API-Key: sk_live_arq_2024_production_key_change_me" \
http://localhost:8000/api/webcom/lines
Configure API Keys
Set keys in .env file:
API_KEY_1=sk_live_arq_2024_production_key_change_me
API_KEY_2=sk_live_arq_2024_dashboard_key_change_me
API_KEY_3=sk_live_arq_2024_monitoring_key_change_me
Authentication Errors
Missing or invalid API key returns 401 Unauthorized:
{
"detail": "Missing X-API-Key header. Authentication required."
}
API Endpoints
/health
Health check endpoint - returns service status
Response
{
"status": "healthy"
}
Examples
curl -X GET http://localhost:8000/health
fetch('http://localhost:8000/health')
.then(res => res.json())
.then(data => console.log(data));
const axios = require('axios');
axios.get('http://localhost:8000/health')
.then(response => console.log(response.data));
/version
Get API version and build information
Response
{
"title": "Gateway ARQ",
"version": "1.0.0",
"description": "Real-time data ingestion system",
"copyright": "© 2025-2026 sanvil"
}
Examples
curl -X GET http://localhost:8000/version
fetch('http://localhost:8000/version')
.then(res => res.json())
.then(data => console.log(`Version: ${data.version}`));
/metrics
Get system metrics (workers, calls, costs)
Response
{
"workers": {
"webcom": { "status": "healthy", "last_run": "2025-11-15T13:30:00Z" },
"webtv": { "status": "healthy", "last_run": "2025-11-15T13:30:00Z" }
},
"calls": {
"webcom_active": 3,
"total_today": 245
},
"webcom": {
"line_ids": ["Sickprod90TLW", "Sickprod80FW", ...]
},
"costs": {
"today": 45.50
},
"timestamp": "2025-11-15T13:30:00Z"
}
Examples
curl -X GET http://localhost:8000/metrics
const axios = require('axios');
async function getMetrics() {
const { data } = await axios.get('http://localhost:8000/metrics');
console.log(`Active calls: ${data.calls.webcom_active}`);
console.log(`Cost today: €${data.costs.today}`);
}
getMetrics();
/api/webcom/lines
Get all WebCom line IDs and details
Response
{
"count": 59,
"lines": [
{
"lineId": "Sickprod28GN",
"number": "800026028",
"lineType": "Green",
"group": "Green",
"relations": ["Read", "Write", "Owner"],
"name": null
},
...
]
}
Examples
curl -X GET http://localhost:8000/api/webcom/lines
fetch('http://localhost:8000/api/webcom/lines')
.then(res => res.json())
.then(data => {
console.log(`Total lines: ${data.count}`);
data.lines.forEach(line => {
console.log(`${line.number}: ${line.lineType}`);
});
});
const axios = require('axios');
axios.get('http://localhost:8000/api/webcom/lines')
.then(response => {
console.log(`Total lines: ${response.data.count}`);
console.log('Lines:', response.data.lines);
});
/api/webcom/calls
Get active WebCom calls
Query Parameters
limit(optional) - Max number of calls to return (default: 50)
Response
{
"count": 5,
"calls": [
{
"id": "691880b00a5a19c9db354ac8",
"lineID": "Sickprod90TLW",
"state": "Pending",
"direction": "Entering",
"caller": "331234567",
"called": "899748963",
"callerOperator": "TIM",
"cost": 0.15,
"lineNumber": "899748963",
"timestamp": 1731671400
},
...
]
}
Examples
curl -X GET "http://localhost:8000/api/webcom/calls?limit=10"
fetch('http://localhost:8000/api/webcom/calls?limit=10')
.then(res => res.json())
.then(data => {
console.log(`Active calls: ${data.count}`);
data.calls.forEach(call => {
console.log(`${call.id}: ${call.state} - ${call.caller} → ${call.called}`);
});
});
const axios = require('axios');
async function getCalls() {
const { data } = await axios.get('http://localhost:8000/api/webcom/calls', {
params: { limit: 10 }
});
console.log(`Found ${data.count} calls`);
return data.calls;
}
getCalls();
/api/webcom/calls/{call_id}
Get specific WebCom call by ID
Path Parameters
call_id- Call identifier (e.g., "691880b00a5a19c9db354ac8")
Response (Success)
{
"id": "691880b00a5a19c9db354ac8",
"lineID": "Sickprod90TLW",
"state": "Ok",
"direction": "Entering",
"caller": "331234567",
"called": "899748963",
"callerOperator": "TIM",
"cost": 0.15,
"duration": 45,
"timestamp": 1731671400
}
Response (Not Found)
{
"error": "Call not found"
}
Examples
curl -X GET http://localhost:8000/api/webcom/calls/691880b00a5a19c9db354ac8
const callId = '691880b00a5a19c9db354ac8';
fetch(`http://localhost:8000/api/webcom/calls/${callId}`)
.then(res => res.json())
.then(call => {
if (call.error) {
console.error('Call not found');
} else {
console.log(`Call ${call.id}: ${call.state}`);
console.log(`Duration: ${call.duration}s, Cost: €${call.cost}`);
}
});
const axios = require('axios');
async function getCall(callId) {
try {
const { data } = await axios.get(
`http://localhost:8000/api/webcom/calls/${callId}`
);
return data;
} catch (error) {
console.error('Error fetching call:', error.message);
}
}
getCall('691880b00a5a19c9db354ac8');
/api/webcom/rebates
Get WebCom rebates for a specific month
Query Parameters
month(optional) - Month in YYYY-MM format (default: current month)
Response
{
"month": "2025-11",
"count": 5,
"updated_at": "1731671400",
"rebates": [
{
"type": "Vas",
"operator": "TIMG",
"cost": 2092.68,
"counter": 923
},
{
"type": "Green",
"operator": "WIND",
"cost": -0.07,
"counter": 8
},
...
]
}
Examples
curl -X GET http://localhost:8000/api/webcom/rebates
curl -X GET "http://localhost:8000/api/webcom/rebates?month=2025-10"
fetch('http://localhost:8000/api/webcom/rebates?month=2025-11')
.then(res => res.json())
.then(data => {
console.log(`Rebates for ${data.month}`);
let totalCost = 0;
data.rebates.forEach(rebate => {
console.log(`${rebate.operator} (${rebate.type}): €${rebate.cost}`);
totalCost += rebate.cost;
});
console.log(`Total: €${totalCost.toFixed(2)}`);
});
const axios = require('axios');
async function getRebates(month = null) {
const params = month ? { month } : {};
const { data } = await axios.get(
'http://localhost:8000/api/webcom/rebates',
{ params }
);
console.log(`Rebates for ${data.month}: ${data.count} entries`);
return data.rebates;
}
// Get current month
getRebates();
// Get specific month
getRebates('2025-10');
/
Root endpoint - returns API information and available endpoints
Response
{
"message": "Gateway ARQ API",
"version": "1.0.0",
"status": "healthy",
"endpoints": {
"health": "/health",
"version": "/version",
"metrics": "/metrics",
"webcom": "/api/webcom/*",
"webtv": "/api/webtv/*",
"websocket": "/ws"
}
}
Examples
curl -H "X-API-Key: sk_live_arq_2024_production_key_change_me" \
http://localhost:8000/
📺 /api/webtv/viewers
Get current WebTV CDN viewers count (real-time)
Response
{
"viewers": 23,
"timestamp": "2025-11-15T18:57:08.177349+00:00"
}
Response Fields
viewers- Current number of viewers (integer)timestamp- Timestamp of data fetch (ISO 8601)
Update Frequency
Data is updated every 5 seconds by the WebTV worker.
Examples
curl -H "X-API-Key: sk_live_arq_2024_production_key_change_me" \
http://localhost:8000/api/webtv/viewers
const response = await fetch('http://localhost:8000/api/webtv/viewers', {
headers: { 'X-API-Key': 'sk_live_arq_2024_production_key_change_me' }
});
const data = await response.json();
console.log(`Current viewers: ${data.viewers}`);
import requests
headers = {'X-API-Key': 'sk_live_arq_2024_production_key_change_me'}
response = requests.get('http://localhost:8000/api/webtv/viewers', headers=headers)
data = response.json()
print(f"Current viewers: {data['viewers']}")
📺 /api/webtv/stats
Get WebTV statistics (today + yesterday + comparison)
Response
{
"today": {
"date": "2025-11-15",
"min": 5,
"max": 23,
"avg": 10,
"current": 23,
"hourly": [0, 0, 0, ..., 12, 23, 0, ...] // 24 values
},
"yesterday": {
"date": "2025-11-14",
"min": 0,
"max": 0,
"avg": 0,
"hourly": [0, 0, 0, ...]
},
"comparison": {
"min_change_pct": 0.0,
"max_change_pct": 0.0,
"avg_change_pct": 0.0
},
"timestamp": "2025-11-15T18:57:08.381807+00:00"
}
Response Fields
today.date- Current date (YYYY-MM-DD)today.min- Minimum viewers todaytoday.max- Maximum viewers todaytoday.avg- Average viewers today (rounded)today.current- Current viewerstoday.hourly- Array of 24 hourly samplesyesterday.*- Same structure for yesterdaycomparison.*_change_pct- Percentage change vs yesterday
Data Retention
Hourly samples and daily stats are stored for 7 days.
Examples
curl -H "X-API-Key: sk_live_arq_2024_production_key_change_me" \
http://localhost:8000/api/webtv/stats
const response = await fetch('http://localhost:8000/api/webtv/stats', {
headers: { 'X-API-Key': 'sk_live_arq_2024_production_key_change_me' }
});
const data = await response.json();
// Create Chart.js graph
const chart = new Chart(ctx, {
type: 'line',
data: {
labels: Array.from({length: 24}, (_, i) => `${i}:00`),
datasets: [{
label: 'Today',
data: data.today.hourly,
borderColor: 'rgb(59, 130, 246)'
}]
}
});
📊 WebCom Statistics
/api/webcom/stats/today
Get call statistics for today (total calls, duration, cost)
Response
{
"date": "2025-12-09",
"total_calls": 245,
"total_duration_seconds": 45600,
"total_cost": 125.50,
"by_line_type": {
"Green": { "calls": 120, "cost": 0 },
"Vas": { "calls": 125, "cost": 125.50 }
}
}
/api/webcom/stats/daily
Get daily call statistics for the last 7 days
Query Parameters
days(optional) - Number of days (default: 7, max: 30)
Response
{
"days": [
{ "date": "2025-12-09", "calls": 245, "cost": 125.50 },
{ "date": "2025-12-08", "calls": 230, "cost": 118.25 },
...
]
}
/api/webcom/stats/hourly
Get hourly call statistics for today
Query Parameters
date(optional) - Date in YYYY-MM-DD format (default: today)
Response
{
"date": "2025-12-09",
"hours": [
{ "hour": 0, "calls": 5, "cost": 2.50 },
{ "hour": 1, "calls": 3, "cost": 1.50 },
...
]
}
/api/webcom/stats/5min
Get WebCom 5-minute call samples for last 3 hours (36 samples)
Response
{
"samples": [
{ "time": "19:05", "calls": 2 },
{ "time": "19:10", "calls": 3 },
...
{ "time": "22:05", "calls": 5 }
],
"count": 36,
"timestamp": "2025-11-18T22:05:00Z"
}
Examples
curl -H "X-API-Key: YOUR_API_KEY" \
http://localhost:8000/api/webcom/stats/5min
const response = await fetch('http://localhost:8000/api/webcom/stats/5min', {
headers: { 'X-API-Key': 'YOUR_API_KEY' }
});
const data = await response.json();
console.log(`Last 3h samples: ${data.count}`);
/api/webtv/hourly
Get WebTV 5-minute samples for last 3 hours (3-hour trend chart)
Response
{
"samples": [
{ "time": "19:05", "viewers": 142 },
{ "time": "19:10", "viewers": 145 },
...
{ "time": "22:05", "viewers": 150 }
],
"count": 36,
"timestamp": "2025-11-16T22:05:00Z"
}
Examples
curl -H "X-API-Key: YOUR_API_KEY" \
http://localhost:8000/api/webtv/hourly
🎰 OCR Lotto Endpoints
/api/ocr/process
Process image with OCR and extract Italian Lotto numbers. Includes AI validation for error correction.
Request Body
{
"image_base64": "...", // Base64 encoded JPEG/PNG
"data_estrazione": "2025-12-02", // Extraction date
"ai_validation": true, // Enable AI error correction
"send_telegram": false, // Send result to Telegram
"auto_upload": false // Upload to lotto.sanvil.net
}
Response
{
"success": true,
"wheels": {
"BARI": ["50", "29", "12", "47", "73"],
"CAGLIARI": ["04", "79", "80", "66", "84"],
...
"NAZIONALE": ["16", "25", "48", "81", "88"]
},
"wheels_count": 11,
"confidence": 100.0,
"ai_validation": { "corrections": 5, "confidence": 98 },
"telegram": { "success": true },
"upload": { "success": true, "wheels_uploaded": 11 }
}
/api/ocr/autobot/status
Get AutoBOT worker status (scheduled OCR extraction at 20:01)
Response
{
"status": "idle", // idle|capturing|ocr|validating|completed|error
"wheels_completed": 0,
"total_wheels": 11,
"last_run": "2025-12-02T20:01:00Z"
}
/api/ocr/autobot/start
Manually start AutoBOT OCR extraction from live stream
Request Body
{
"ai_validation": true,
"telegram_notify": true,
"auto_upload": false
}
/api/ocr/telegram/send
Send OCR results to configured Telegram chat
Request Body
{
"message": "ESTRAZIONE LOTTO...",
"parse_mode": "HTML",
"image_base64": "..." // Optional: attach image
}
/api/ocr/lotto/upload
Upload extracted numbers to lotto.sanvil.net
Request Body
{
"wheels": {
"BARI": ["50", "29", "12", "47", "73"],
...
},
"data_estrazione": "2025-12-02"
}
Response
{
"success": true,
"wheels_uploaded": 11,
"results": [
{ "wheel": "BARI", "success": true },
...
]
}
/api/ocr/config
Get OCR configuration (non-sensitive settings)
Response
{
"ai": {
"enabled": true,
"default_model": "anthropic/claude-sonnet-4.5"
},
"telegram": { "enabled": true },
"upload": { "enabled": true },
"timestamp": "2025-12-09T10:00:00Z"
}
/api/ocr/autobot/config
Get AutoBOT configuration (stream URL, schedule, feature flags)
Response
{
"stream_url": "https://cdn.example.com/stream.m3u8",
"default_stream_url": "https://cdn.example.com/stream.m3u8",
"schedule": "20:01 daily",
"config": {
"ai_validation": true,
"auto_upload": true,
"telegram_notify": true,
"save_to_db": true
},
"timestamp": "2025-12-09T10:00:00Z"
}
/api/ocr/autobot/config
Update AutoBOT configuration. Stream URL is persisted in Redis.
Request Body
{
"stream_url": "https://new-cdn.example.com/stream.m3u8",
"ai_validation": true,
"auto_upload": true,
"telegram_notify": true,
"save_to_db": true
}
Response
{
"success": true,
"config": { "ai_validation": true, "auto_upload": true, ... },
"stream_url": "https://new-cdn.example.com/stream.m3u8",
"message": "Configuration updated",
"timestamp": "2025-12-09T10:00:00Z"
}
/api/ocr/autobot/stop
Stop AutoBOT processing gracefully
Response
{
"success": true,
"status": "idle",
"previous_status": "capturing",
"message": "AutoBOT stopped",
"timestamp": "2025-12-09T10:00:00Z"
}
/api/ocr/ai/validate
Proxy endpoint for OpenRouter AI validation - sends image + prompt to AI vision model
Request Body
{
"image_base64": "...", // Base64 encoded image
"prompt": "Verify these numbers...", // Custom prompt
"model": "anthropic/claude-sonnet-4.5" // Optional
}
Response
{
"success": true,
"model": "anthropic/claude-sonnet-4.5",
"response": "...", // AI response text
"usage": { "prompt_tokens": 100, "completion_tokens": 200 },
"timestamp": "2025-12-09T10:00:00Z"
}
/api/ocr/ai/models
Get available AI vision models from OpenRouter
Response
{
"models": [
{ "id": "anthropic/claude-sonnet-4.5", "name": "Claude Sonnet 4.5", ... },
{ "id": "openai/gpt-4-vision-preview", "name": "GPT-4 Vision", ... }
],
"default": "anthropic/claude-sonnet-4.5",
"count": 12,
"timestamp": "2025-12-09T10:00:00Z"
}
/api/ocr/riscontri
Proxy per la pagina riscontri/vincite di lotto.sanvil.net (con Basic Auth)
Query Parameters
da(optional) - Pagination offset (default: 0)
Response
{
"success": true,
"html": "<html>...</html>",
"current_offset": 0,
"timestamp": "2025-12-09T10:00:00Z"
}
/api/ocr/riscontri2/dates
Get available extraction dates from legacy MySQL database
Query Parameters
limit(optional) - Number of dates to return (default: 10)
Response
{
"status": "ok",
"dates": [
{ "raw": "20251207", "formatted": "2025-12-07", "display": "07/12/2025" },
...
],
"count": 10,
"timestamp": "2025-12-09T10:00:00Z"
}
/api/ocr/riscontri2/extraction
Get current extraction from legacy MySQL database
Response
{
"status": "ok",
"extraction": {
"BA": { "name": "BARI", "numbers": [12, 45, 67, 23, 89] },
"CA": { "name": "CAGLIARI", "numbers": [4, 79, 80, 66, 84] },
...
},
"wheel_count": 11,
"timestamp": "2025-12-09T10:00:00Z"
}
/api/ocr/riscontri2/riscontri
Calculate riscontri between current extraction and predictions
Query Parameters
by_dates(optional) - Number of extraction dates to load (default: 15)
Response
{
"status": "ok",
"extraction": { ... },
"predictions": [ ... ],
"stats": { "total": 100, "estratti": 25, "ambi": 5 },
"stats_last3": { "total": 30, "estratti": 8 },
"timestamp": "2025-12-09T10:00:00Z"
}
/ws
WebSocket endpoint for real-time call updates
Connection URL
ws://localhost:8000/ws
Event Types
system- Connection establishedheartbeat- Keep-alive ping (every 30s)call_event_realtime- WebCom call updaterebates_updated- Rebates data updatedwebtv_update- WebTV viewers update
Call Event Example
{
"id": "691880b00a5a19c9db354ac8",
"lineID": "Sickprod90TLW",
"state": "Pending",
"direction": "Entering",
"caller": "331234567",
"called": "899748963",
"callerOperator": "TIM",
"cost": 0.15,
"lineNumber": "899748963"
}
Examples
const ws = new WebSocket('ws://localhost:8000/ws');
ws.onopen = () => {
console.log('Connected to Gateway ARQ');
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log('Event received:', data);
if (data.id && data.state) {
console.log(`Call ${data.id}: ${data.state}`);
}
};
ws.onerror = (error) => {
console.error('WebSocket error:', error);
};
ws.onclose = () => {
console.log('Disconnected');
};
const WebSocket = require('ws');
const ws = new WebSocket('ws://localhost:8000/ws');
ws.on('open', () => {
console.log('Connected to Gateway ARQ');
});
ws.on('message', (data) => {
const event = JSON.parse(data);
if (event.id && event.state) {
console.log(`Call ${event.id}: ${event.state}`);
console.log(` Caller: ${event.caller}`);
console.log(` Cost: €${event.cost}`);
}
});
ws.on('error', (error) => {
console.error('Error:', error);
});
🎲 Lotto Database Endpoints
/api/lotto/stats
Get database statistics (total extractions, date range, per-wheel counts)
Response
{
"total_records": 75845,
"unique_dates": 6895,
"first_date": "2001/01/02",
"last_date": "2025/12/07",
"by_wheel": {
"BA": 6895, "CA": 6895, "FI": 6895,
"GE": 6895, "MI": 6895, "NA": 6895,
"PA": 6895, "RM": 6895, "TO": 6895,
"VE": 6895, "RN": 6895
}
}
/api/lotto/latest
Get latest extractions (grouped by date)
Query Parameters
limit(optional) - Number of dates (default: 10)
Response
{
"dates": [
{
"date": "2025/12/07",
"wheels": {
"BA": [12, 45, 67, 23, 89],
"CA": [4, 79, 80, 66, 84],
...
}
}
]
}
/api/lotto/date/{data}
Get all wheels for a specific extraction date
Path Parameters
data- Date in YYYY/MM/DD format (e.g., 2025/12/07)
Response
{
"success": true,
"date": "2025/12/07",
"wheels": {
"BA": [12, 45, 67, 23, 89],
"CA": [4, 79, 80, 66, 84],
"FI": [15, 33, 42, 58, 71],
...
},
"timestamp": "2025-12-09T10:00:00Z"
}
/api/lotto/date/{data}/{ruota}
Get single extraction by date and wheel
Path Parameters
data- Date in YYYY/MM/DD formatruota- Wheel code (BA, CA, FI, GE, MI, NA, PA, RM, TO, VE, RN)
Response
{
"success": true,
"data": "2025/12/07",
"ruota": "BA",
"numeri": [12, 45, 67, 23, 89],
"source": "sync",
"timestamp": "2025-12-09T10:00:00Z"
}
/api/lotto/search
Search for number occurrences across extractions
Query Parameters
number(required) - Number to search (1-90)ruota(optional) - Filter by wheel (BA, CA, FI, etc.)limit(optional) - Max results (default: 50)
Response
{
"number": 45,
"total_occurrences": 1234,
"results": [
{ "date": "2025/12/07", "ruota": "BA", "position": 2 },
{ "date": "2025/12/05", "ruota": "MI", "position": 1 },
...
]
}
/api/lotto/range
Get extractions in date range
Query Parameters
from_date(required) - Start date (YYYY/MM/DD)to_date(required) - End date (YYYY/MM/DD)ruota(optional) - Wheel filter (2-letter code)limit(optional) - Max results (default: 100, max: 1000)offset(optional) - Pagination offset (default: 0)
Response
{
"success": true,
"count": 50,
"results": [
{ "data": "2025/12/01", "ruota": "BA", "numeri": [12, 45, 67, 23, 89] },
...
],
"timestamp": "2025-12-09T10:00:00Z"
}
/api/lotto/export
Export database to TSV file
Query Parameters
filename(optional) - Output filename (default: lotto_export.tsv)
Response
{
"success": true,
"exported": 75845,
"file_path": "/tmp/lotto_exports/lotto_export.tsv",
"timestamp": "2025-12-09T10:00:00Z"
}
/api/lotto/save
Save a single wheel extraction
Request Body
{
"data": "2025/12/07",
"ruota": "BA",
"numeri": [12, 45, 67, 23, 89],
"source": "manual" // "manual", "ocr", "sync", "import"
}
Response
{
"success": true,
"data": "2025/12/07",
"ruota": "BA",
"numeri": [12, 45, 67, 23, 89],
"timestamp": "2025-12-09T10:00:00Z"
}
/api/lotto/save-full
Save complete extraction (all wheels) to database
Request Body
{
"data": "2025/12/07",
"wheels": {
"BARI": [12, 45, 67, 23, 89],
"CAGLIARI": [4, 79, 80, 66, 84],
...
},
"source": "ocr"
}
Response
{
"success": true,
"data": "2025/12/07",
"saved": 11,
"total": 11,
"errors": null,
"timestamp": "2025-12-09T10:00:00Z"
}
/api/lotto/import
Import historical data from TSV file. Expected format: YYYY/MM/DD\tRUOTA\tn1\tn2\tn3\tn4\tn5
Request Body
{
"file_path": "/path/to/storico.tsv"
}
Response
{
"success": true,
"inserted": 1234,
"skipped": 500,
"errors": [],
"duration_seconds": 2.5,
"timestamp": "2025-12-09T10:00:00Z"
}
/api/lotto/sync
Sync database from brightstarlottery.it (downloads ZIP, imports missing dates)
Response
{
"success": true,
"imported": 55,
"skipped": 75790,
"message": "Sync completed: 55 new records imported",
"timestamp": "2025-12-09T10:00:00Z"
}
/api/lotto/date/{data}/{ruota}
Delete single extraction by date and wheel
Path Parameters
data- Date in YYYY/MM/DD formatruota- Wheel code (BA, CA, FI, etc.)
Response
{
"success": true,
"message": "Deleted 2025/12/07 BA",
"timestamp": "2025-12-09T10:00:00Z"
}
Examples
curl -X DELETE -H "X-API-Key: YOUR_API_KEY" \
"http://localhost:8000/api/lotto/date/2025/12/07/BA"
/api/lotto/date/{data}
Delete all extractions for a date (all 11 wheels)
Path Parameters
data- Date in YYYY/MM/DD format
Response
{
"success": true,
"deleted": 11,
"message": "Deleted 11 extractions for 2025/12/07",
"timestamp": "2025-12-09T10:00:00Z"
}
Examples
curl -X DELETE -H "X-API-Key: YOUR_API_KEY" \
"http://localhost:8000/api/lotto/date/2025/12/07"
📞 Centralino (jPBX) API
API per l'integrazione con il centralino telefonico (asterisk-monitor).
Questi endpoint sono proxied attraverso nginx a /jpbx-api/.
/jpbx-api/api/calls
Ottiene le chiamate attive sul centralino
Response
{
"active_calls": [
{
"channel_id": "asterisk-pbx-1765265705.475",
"name": "PJSIP/clouditalia-endpoint-000000ab",
"state": "Up",
"caller": "3478893084",
"caller_name": "3478893084",
"extension": "s",
"context": "post-stasis",
"application": "Queue",
"duration": "2025-12-09T08:35:05.936+0100"
}
],
"count": 1
}
/jpbx-api/api/blacklist
Ottiene la lista dei numeri in blacklist
Response
{
"blacklist": [
{
"number": "3883666427",
"reason": "answered-24h",
"created_at": "2025-12-09 07:48:07",
"expires_at": "2025-12-10 08:48:07",
"permanent": 0
},
{
"number": "3408564246",
"reason": "manual-permanent",
"created_at": "2025-12-08 07:18:32",
"expires_at": "2099-12-31 23:59:59",
"permanent": 1
}
],
"count": 25
}
/jpbx-api/api/blacklist
Aggiunge un numero alla blacklist
Request Body
{
"number": "3331234567",
"hours": 24, // Durata in ore (default: 24, ignorato se permanent=true)
"permanent": false // Se true, ban permanente
}
Response
{
"success": true,
"number": "3331234567",
"expires_at": "2025-12-10 11:30:00"
}
/jpbx-api/api/blacklist/{number}
Rimuove un numero dalla blacklist
Response
{
"success": true,
"message": "Number removed from blacklist"
}
/jpbx-api/api/ari/endpoints
Ottiene lo stato degli interni (extensions)
Response
[
{
"resource": "105",
"state": "online",
"channel_ids": ["asterisk-pbx-123.456"]
},
{
"resource": "100",
"state": "offline",
"channel_ids": []
}
]
/jpbx-api/api/status
Ottiene lo stato del monitor centralino
Response
{
"status": "running",
"websocket": "connected",
"stasis_calls": 0,
"blacklisted_this_session": 15,
"ws_clients": 1,
"timestamp": "2025-12-09T10:33:27.464463",
"active_calls": 3
}
/jpbx-ws?api_key=xxx
WebSocket per eventi real-time del centralino
Eventi
ari_event- Eventi ARI raw (ChannelCreated, ChannelDestroyed, etc.)call_passed- Chiamata passata controllo anti-spamcall_blocked- Chiamata bloccata (anonimo/blacklist)blacklist_added- Numero aggiunto a blacklist
Rate Limiting
Currently no rate limiting is enforced. Future versions will implement:
- 100 requests/minute per IP address
- Rate limit headers in responses
- HTTP 429 (Too Many Requests) when exceeded
Error Codes
| Code | Description |
|---|---|
200 |
OK - Request successful |
400 |
Bad Request - Invalid parameters |
404 |
Not Found - Endpoint does not exist |
500 |
Internal Server Error - Server error |