# Extractors API ## Base URL ``` {BASE_URL} ``` - **Local development:** `http://localhost:54400` - **Docker (internal):** `http://extractors:54400` - **Production:** use your configured hostname (port `14400`) ## Authentication None at the service level — access is mediated by the platform API gateway (Bearer token at the perimeter). Do not expose this service directly. ## Endpoints ### GET /health Liveness probe. ```json { "status": "ok", "version": "0.1.0" } ``` ### GET /ready Readiness + optional tooling availability (informational; the service degrades gracefully if ffprobe/ffmpeg are absent). ```json { "status": "ready", "ffprobe": true, "ffmpeg": true } ``` ### POST /v1/metadata Extract deterministic media metadata & integrity features. The applicable extractors are chosen automatically from the detected media type. **Request** — `multipart/form-data` | Field | Type | Description | |-------|------|-------------| | `file` | file | Image, video or audio file | ```bash curl -X POST http://localhost:54400/v1/metadata \ -F "file=@photo.jpg" ``` **Response** `200 OK` ```json { "filename": "photo.jpg", "media_type": "image", "sha256": "9f86d081884c7d65...", "size_bytes": 84211, "analyses": { "integrity": { "tool_id": "integrity", "name": "Integrity & signature", "ok": true, "results": { "container": "JPEG", "sha256": "9f86...", "size_bytes": 84211 }, "evidence": ["Container: JPEG.", "SHA-256: 9f86d081884c7d65…"], "anomalies": [], "confidence": 1.0 }, "exif": { "tool_id": "exif", "name": "EXIF metadata", "ok": true, "results": { "format": "JPEG", "dimensions": [4032, 3024], "make": "Apple", "model": "iPhone 13", "datetimeoriginal": "2024:06:15 14:30:00", "gps": { "latitude": 44.426, "longitude": 26.102 }, "software": "Adobe Photoshop 25.0" }, "evidence": ["Captured with Apple iPhone 13.", "GPS location present: 44.426, 26.102."], "anomalies": ["Editing/generation software detected in EXIF: Adobe Photoshop 25.0."], "confidence": 0.95 }, "ela": { "tool_id": "ela", "name": "Error Level Analysis", "ok": true, "results": { "quality": 90, "mean_error": 6.1, "max_error": 211.0, "p99_error": 38.0, "hot_pixel_fraction": 0.031 }, "evidence": ["ELA mean error 6.1, p99 38.0 (quality=90)."], "anomalies": ["Localized high-error region(s) detected — possible splice/edit (3.1% of pixels)."], "confidence": 0.6 } }, "evidence": ["..."], "anomalies": ["..."], "execution_time_ms": 42.7 } ``` For **video** inputs the `analyses` block contains `integrity`, `video_metadata` (codec/width/height/fps/bitrate/encoder) and `spectrogram`. For **audio**: `integrity` + `spectrogram`. Each extractor returns a uniform `FeatureResult`: | Field | Type | Description | |-------|------|-------------| | `tool_id` | string | Stable extractor id | | `name` | string | Human-readable name | | `ok` | bool | Ran without error | | `results` | object | Structured extracted data | | `evidence` | string[] | Neutral findings (LLM-readable) | | `anomalies` | string[] | Tampering/edit hints | | `confidence` | number\|null | 0..1 (extraction confidence, not a verdict) | | `error` | string\|null | Set when `ok` is false | ### POST /v1/sentiment Classify the sentiment of a text via the LLM gateway (Romanian-aware prompt, detects irony/sarcasm). **Delegated to the LLM gateway** — returns `503` if no gateway is configured. **Request** — `application/json` | Field | Type | Description | |-------|------|-------------| | `text` | string | Text to analyze (min length 1) | ```bash curl -X POST http://localhost:54400/v1/sentiment \ -H "Content-Type: application/json" \ -d '{"text": "Ce zi frumoasă!"}' ``` **Response** `200 OK` — a `FeatureResult` (same schema as above), e.g.: ```json { "tool_id": "sentiment", "name": "Sentiment", "ok": true, "results": { "label": "positive", "score": 0.92 }, "evidence": ["Sentiment: positive (0.92)."], "anomalies": [], "confidence": 0.92 } ``` ### POST /v1/ner Extract named entities via GLiNER multilingual (`urchade/gliner_multi-v2.1`). **Requires the optional `ml` extra** — returns `503` if the model is unavailable. **Request** — `application/json` | Field | Type | Description | |-------|------|-------------| | `text` | string | Text to analyze (min length 1) | | `labels` | string[] \| null | Entity types to extract (defaults to the RO set) | ```bash curl -X POST http://localhost:54400/v1/ner \ -H "Content-Type: application/json" \ -d '{"text": "Klaus Iohannis și Guvernul României."}' ``` **Response** `200 OK` — a `FeatureResult`; `results` carries the extracted entities (text, label, span, score). ### POST /v1/ocr Extract visible text verbatim from an image via the LLM vision model. **Delegated to the LLM gateway** — returns `503` if no gateway is configured. **Request** — `multipart/form-data` | Field | Type | Description | |-------|------|-------------| | `file` | file | Image file | ```bash curl -X POST http://localhost:54400/v1/ocr \ -F "file=@scan.png" ``` **Response** `200 OK` — a `FeatureResult`; `results` carries the recognized text. ### POST /v1/detect Detect objects (COCO classes) via YOLO (`yolov8n`), returning boxes + confidence. **Requires the optional `ml` extra** — returns `503` if the model is unavailable. **Request** — `multipart/form-data` | Field | Type | Description | |-------|------|-------------| | `file` | file | Image file | Optional query param: `threshold` (float, 0..1) — confidence threshold. ```bash curl -X POST "http://localhost:54400/v1/detect?threshold=0.4" \ -F "file=@street.jpg" ``` **Response** `200 OK` — a `FeatureResult`; `results` carries detected objects (label, box, confidence). ## Error Responses | Status | Meaning | |--------|---------| | 400 | Empty file | | 413 | File exceeds `EXTRACTORS_MAX_UPLOAD_MB` | | 422 | Missing `file` field | | 502 | `LLMError` — the LLM gateway returned an error (`/v1/sentiment`, `/v1/ocr`) | | 503 | `LLMNotConfigured` (no gateway for `/v1/sentiment`, `/v1/ocr`) or the `ml` extra/model is unavailable (`/v1/ner`, `/v1/detect`) | ```json { "detail": "empty file" } ``` ## Request Headers | Header | Required | Notes | |--------|----------|-------| | `Content-Type` | yes | `multipart/form-data` (set by the client) |