API Reference#
Complete REST API documentation for the Take-Away Order Accuracy service.
Table of Contents#
Overview#
The Order Accuracy API provides RESTful endpoints for video upload, VLM processing, and order validation. All responses are in JSON format.
API Version#
Current API version: v1
Content Types#
Request:
application/json,multipart/form-dataResponse:
application/json
Authentication#
Currently, the API does not require authentication. For production deployments, configure API key or OAuth2 authentication.
Future Authentication (Planned)#
# API Key Header
curl -H "X-API-Key: your-api-key" http://localhost:8000/api/v1/...
# Bearer Token
curl -H "Authorization: Bearer your-token" http://localhost:8000/api/v1/...
Base URL#
Environment |
URL |
|---|---|
Development |
|
Docker Network |
|
Production |
|
Health Endpoints#
GET /health#
Check service health status.
Request:
curl http://localhost:8000/health
Response (200 OK):
{
"status": "healthy",
"service": "order-accuracy",
"version": "1.0.0",
"mode": "single",
"uptime_seconds": 3600,
"timestamp": "2025-01-15T10:30:00Z"
}
Response Fields:
Field |
Type |
Description |
|---|---|---|
status |
string |
Health status: |
service |
string |
Service name |
version |
string |
API version |
mode |
string |
Service mode: |
uptime_seconds |
integer |
Seconds since service start |
timestamp |
string |
ISO 8601 timestamp |
GET /health/detailed#
Get detailed health status including dependencies.
Request:
curl http://localhost:8000/health/detailed
Response (200 OK):
{
"status": "healthy",
"service": "order-accuracy",
"dependencies": {
"ovms": {
"status": "healthy",
"latency_ms": 15,
"endpoint": "http://ovms-vlm:8000"
},
"minio": {
"status": "healthy",
"latency_ms": 5,
"endpoint": "minio:9000"
},
"semantic_service": {
"status": "healthy",
"latency_ms": 10,
"endpoint": "http://oa_semantic_service:8080"
}
},
"memory_mb": 512,
"cpu_percent": 25.5
}
Video Processing Endpoints#
POST /upload-video#
Upload a video file for processing.
Request:
curl -X POST http://localhost:8000/upload-video \
-F "file=@video.mp4" \
-F "video_id=order_001" \
-F "station_id=station_1"
Parameters:
Parameter |
Type |
Required |
Description |
|---|---|---|---|
file |
file |
Yes |
Video file (MP4, AVI, MOV) |
video_id |
string |
Yes |
Unique identifier for the video |
station_id |
string |
No |
Station identifier (default: station_1) |
Response (200 OK):
{
"status": "success",
"video_id": "order_001",
"station_id": "station_1",
"message": "Video uploaded successfully",
"file_size_bytes": 15728640,
"frames_estimated": 450,
"upload_time_ms": 1250
}
Error Responses:
Status |
Description |
|---|---|
400 |
Invalid file format or missing parameters |
413 |
File too large (max 500MB) |
500 |
Server error during upload |
POST /run-video#
Process an uploaded video with VLM inference.
Request:
curl -X POST http://localhost:8000/run-video \
-H "Content-Type: application/json" \
-d '{
"video_id": "order_001",
"expected_items": [
{"name": "burger", "quantity": 2},
{"name": "fries", "quantity": 1},
{"name": "drink", "quantity": 1}
],
"options": {
"matching_strategy": "hybrid",
"similarity_threshold": 0.85
}
}'
Request Body:
Field |
Type |
Required |
Description |
|---|---|---|---|
video_id |
string |
Yes |
Video ID from upload |
expected_items |
array |
Yes |
Array of expected order items |
expected_items[].name |
string |
Yes |
Item name |
expected_items[].quantity |
integer |
Yes |
Expected quantity |
options |
object |
No |
Processing options |
options.matching_strategy |
string |
No |
|
options.similarity_threshold |
float |
No |
0.0-1.0 (default: 0.85) |
Response (202 Accepted):
{
"status": "processing",
"video_id": "order_001",
"task_id": "task_abc123def456",
"estimated_time_ms": 5000,
"message": "Video queued for processing"
}
VLM Processing Endpoints#
POST /run_vlm#
Direct VLM inference on an image.
Request:
curl -X POST http://localhost:8000/run_vlm \
-F "image=@frame.jpg" \
-F "prompt=Identify all food items in this image"
Parameters:
Parameter |
Type |
Required |
Description |
|---|---|---|---|
image |
file |
Yes |
Image file (JPEG, PNG) |
prompt |
string |
No |
Custom prompt (default: item detection) |
Response (200 OK):
{
"status": "success",
"detected_items": [
{ "name": "burger", "quantity": 2, "confidence": 0.95 },
{ "name": "fries", "quantity": 1, "confidence": 0.88 }
],
"raw_response": "...",
"processing_time_ms": 2850,
"token_usage": {
"prompt_tokens": 1250,
"completion_tokens": 85,
"total_tokens": 1335
}
}
GET /vlm/results#
Get VLM processing results.
Request:
curl "http://localhost:8000/vlm/results?video_id=order_001"
Query Parameters:
Parameter |
Type |
Required |
Description |
|---|---|---|---|
video_id |
string |
Yes |
Video ID to retrieve results |
Response (200 OK):
{
"video_id": "order_001",
"status": "completed",
"frames_processed": 3,
"detections": [
{
"frame_id": 1,
"items": [{ "name": "burger", "quantity": 2 }]
},
{
"frame_id": 2,
"items": [
{ "name": "burger", "quantity": 2 },
{ "name": "fries", "quantity": 1 }
]
}
],
"aggregated_detection": [
{ "name": "burger", "quantity": 2, "confidence": 0.95 },
{ "name": "fries", "quantity": 1, "confidence": 0.88 }
]
}
Results Endpoints#
GET /results/{order_id}#
Get validation results for an order.
Request:
curl http://localhost:8000/results/order_001
Path Parameters:
Parameter |
Type |
Description |
|---|---|---|
order_id |
string |
Order/video identifier |
Response (200 OK):
{
"order_id": "order_001",
"station_id": "station_1",
"status": "completed",
"timestamp": "2025-01-15T10:35:00Z",
"validation": {
"matched": [
{
"name": "burger",
"expected_quantity": 2,
"detected_quantity": 2,
"match_type": "exact",
"confidence": 0.95
},
{
"name": "fries",
"expected_quantity": 1,
"detected_quantity": 1,
"match_type": "semantic",
"confidence": 0.88,
"detected_as": "french fries"
}
],
"missing": [],
"extra": [
{
"name": "ketchup packet",
"detected_quantity": 2,
"reason": "not_in_order"
}
],
"quantity_mismatch": []
},
"summary": {
"total_expected_items": 2,
"total_expected_quantity": 3,
"matched_items": 2,
"matched_quantity": 3,
"missing_items": 0,
"extra_items": 1,
"accuracy_score": 1.0,
"order_complete": true
},
"metadata": {
"video_duration_sec": 15,
"frames_extracted": 450,
"frames_selected": 3,
"vlm_latency_ms": 3200,
"total_processing_ms": 5500,
"matching_strategy": "hybrid"
}
}
Response Fields:
Field |
Type |
Description |
|---|---|---|
matched |
array |
Items correctly found |
missing |
array |
Expected items not found |
extra |
array |
Found items not in order |
quantity_mismatch |
array |
Items with wrong quantity |
accuracy_score |
float |
0.0-1.0 validation score |
GET /results/station/{station_id}#
Get recent results for a station.
Request:
curl "http://localhost:8000/results/station/station_1?limit=10"
Query Parameters:
Parameter |
Type |
Default |
Description |
|---|---|---|---|
limit |
integer |
10 |
Max results to return |
offset |
integer |
0 |
Pagination offset |
since |
string |
- |
ISO 8601 timestamp filter |
Response (200 OK):
{
"station_id": "station_1",
"results": [
{
"order_id": "order_003",
"timestamp": "2025-01-15T10:35:00Z",
"accuracy_score": 1.0,
"order_complete": true
},
{
"order_id": "order_002",
"timestamp": "2025-01-15T10:30:00Z",
"accuracy_score": 0.67,
"order_complete": false
}
],
"pagination": {
"limit": 10,
"offset": 0,
"total": 45
}
}
Error Handling#
Error Response Format#
All errors follow a standard format:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid video format",
"details": {
"supported_formats": ["mp4", "avi", "mov"],
"received": "webm"
},
"timestamp": "2025-01-15T10:30:00Z",
"request_id": "req_abc123"
}
}
Error Codes#
Code |
HTTP Status |
Description |
|---|---|---|
VALIDATION_ERROR |
400 |
Invalid request parameters |
NOT_FOUND |
404 |
Resource not found |
FILE_TOO_LARGE |
413 |
Upload exceeds size limit |
PROCESSING_ERROR |
500 |
VLM or internal error |
SERVICE_UNAVAILABLE |
503 |
Dependency unavailable |
TIMEOUT |
504 |
Processing timeout |
Common Error Responses#
400 Bad Request:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Missing required field: expected_items"
}
}
404 Not Found:
{
"error": {
"code": "NOT_FOUND",
"message": "Video order_001 not found"
}
}
500 Internal Server Error:
{
"error": {
"code": "PROCESSING_ERROR",
"message": "VLM inference failed",
"details": {
"ovms_status": "timeout"
}
}
}
Rate Limiting#
Default Limits#
Endpoint |
Limit |
Window |
|---|---|---|
/upload-video |
10 |
per minute |
/run-video |
20 |
per minute |
/run_vlm |
30 |
per minute |
/results/* |
100 |
per minute |
/health |
unlimited |
- |
HTTP Rate Limit Headers#
X-RateLimit-Limit: 20
X-RateLimit-Remaining: 15
X-RateLimit-Reset: 1705312800
Rate Limit Exceeded#
Response (429 Too Many Requests):
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Retry after 45 seconds.",
"retry_after": 45
}
}
OpenAPI Specification#
Access the interactive API documentation:
Swagger UI:
http://localhost:8000/docsReDoc:
http://localhost:8000/redocOpenAPI JSON:
http://localhost:8000/openapi.json
SDK Examples#
Python#
import requests
class OrderAccuracyClient:
def __init__(self, base_url="http://localhost:8000"):
self.base_url = base_url
def upload_video(self, file_path, video_id):
with open(file_path, 'rb') as f:
response = requests.post(
f"{self.base_url}/upload-video",
files={"file": f},
data={"video_id": video_id}
)
return response.json()
def run_validation(self, video_id, expected_items):
response = requests.post(
f"{self.base_url}/run-video",
json={
"video_id": video_id,
"expected_items": expected_items
}
)
return response.json()
def get_results(self, order_id):
response = requests.get(f"{self.base_url}/results/{order_id}")
return response.json()
# Usage
client = OrderAccuracyClient()
client.upload_video("order.mp4", "order_001")
client.run_validation("order_001", [{"name": "burger", "quantity": 2}])
results = client.get_results("order_001")
print(results)
cURL#
# Complete workflow
VIDEO_ID="order_$(date +%s)"
# 1. Upload
curl -X POST http://localhost:8000/upload-video \
-F "file=@video.mp4" \
-F "video_id=${VIDEO_ID}"
# 2. Process
curl -X POST http://localhost:8000/run-video \
-H "Content-Type: application/json" \
-d '{
"video_id": "'${VIDEO_ID}'",
"expected_items": [{"name": "burger", "quantity": 2}]
}'
# 3. Wait and get results
sleep 10
curl http://localhost:8000/results/${VIDEO_ID}