# Agent V3 — API Documentation > DIDI Misinformation Detection Platform — Analysis Engine API > > Version: 3.0.0 ### Base URL | Access Method | Base URL | Notes | |---------------|----------|-------| | **Internal (via nginx proxy)** | `https://localhost:3000/agent-v3` | Through didi-admin nginx container. Self-signed SSL — use `curl -k`. Strips `/agent-v3/` prefix before proxying to agent. | | **Direct (no proxy)** | `http://localhost:24803` | Directly to agent-v3 container. No SSL, no prefix stripping. | | **Public domain** | `https://didi365.eu/agent-v3` | **Currently returns 403 Forbidden.** An external reverse proxy at `213.136.83.198` blocks requests before they reach the staging server (`10.11.10.12`). This needs to be resolved at the infrastructure level. | | **Kong gateway** | `https://localhost:443` | Returns `401 Unauthorized` — Kong enforces JWT validation on this port. Only works with a valid Keycloak JWT. Kong does **not** expose `/api/v3/*` routes — it uses different paths (`/api/analyze`, `/api/pipelines`, etc.) that map to the older agent service interface. | > **Recommendation:** Use `https://localhost:3000/agent-v3` for testing. All curl examples in this document use this base URL with `-k` to accept the self-signed certificate. --- ## Table of Contents 1. [Authentication](#authentication) 2. [Full Pipeline](#1-full-pipeline) 3. [Manipulation Techniques](#2-manipulation-techniques) 4. [AI-Tampered Detection](#3-ai-tampered-detection) 5. [Claims Verification](#4-claims-verification) 6. [Domain Analysis](#5-domain-analysis) 7. [Polling & Results](#6-polling--results) 8. [Browser Extension API](#7-browser-extension-api) 9. [Error Codes](#error-codes) --- ## Authentication Pass `user_id` in the request body to identify the user: ```bash curl -sk -X POST https://localhost:3000/agent-v3/api/v3/pipeline/analyze \ -H "Content-Type: application/json" \ -d '{ "text": "Content to analyze", "media_type": "text", "user_id": "test-user" }' ``` If a JWT `Authorization: Bearer` header is present (from Keycloak), the user identity is extracted from the token and takes precedence over `user_id` in the body. ### Credit System Analysis endpoints check and deduct credits based on `user_id`. If the user's plan has insufficient credits, the API returns `402 Payment Required` with the remaining balance and cost. > **Staging:** When `STAGING_MODE=true` is set (default in staging), all credit limits are bypassed. Any `user_id` value works without needing actual credits. --- ## 1. Full Pipeline Runs all detection components sequentially — **Techniques → AI-Tampered → Claims → Domain** (if URL provided) — then produces an aggregated **verdict** with an overall risk score. This is the primary analysis endpoint. Individual component endpoints (sections 2–5) run only their respective component without producing a verdict. --- ### POST `/api/v3/pipeline/analyze` Synchronous full analysis. Accepts text, media, or URL input. **Parameters:** | Field | Type | Required | Description | |-------|------|----------|-------------| | `text` | string | Conditional | Text content to analyze | | `media_url` | string | Conditional | URL of uploaded media file (image only for sync — audio/video require async) | | `url` | string | Conditional | URL of a webpage to analyze | | `media_type` | string | Yes | One of: `text`, `url`, `image`, `audio`, `video` | | `user_email` | string | No | User email (overridden by JWT if present) | | `options` | object | No | `{ skip_components: string[], scenario: string, topic: string }` | > **Input rule:** Provide at least one of `text`, `media_url`, or `url`. You can combine them — for example, provide both `text` and `url` to analyze text with domain context. > **Audio/video note:** Sync analysis of audio and video media is not supported because transcription can take 5–10 minutes. The endpoint returns `400` with `code: "ASYNC_REQUIRED"`. Use `POST /api/v3/pipeline/analyze-async` for audio and video content instead. **Example:** ```bash curl -sk -X POST https://localhost:3000/agent-v3/api/v3/pipeline/analyze \ -H "Content-Type: application/json" \ -d '{ "text": "Romania'\''s president declared yesterday that the country will leave the European Union by 2025. According to unnamed government sources, this decision was made in secret meetings with Russian officials.", "media_type": "text", "user_id": "test-user" }' ``` **Response (200):** ```json { "success": true, "data": { "session_id": "a63a72ed-de8e-458b-a708-3e80d38f867c", "user_id": "test-user", "status": "completed", "input_type": "text", "components_run": ["techniques", "ai_tampered", "claims"], "components_skipped": ["domain"], "risk_score": 78, "risk_category": "UNRELIABLE", "risk_level": "VERY_HIGH", "confidence": 75, "confidence_level": "MEDIUM", "total_duration_ms": 50500, "techniques": { "manipulation_score": 35, "techniques_count": 1, "dimensions_affected": ["D7"], "techniques_detected": [ { "id": 175, "name": "temporal.embargo_breaking", "dimension": "D7", "subdimension": "Event Timing", "severity": 50, "confidence": 85, "evidence": "The announcement was shared widely on social media before any official press conference." } ], "llm_screening": "qwen35:Qwen3.5-397B-A17B", "llm_deep": "qwen35:Qwen3.5-397B-A17B", "total_duration_ms": 29472 }, "ai_tampered": { "ai_probability": 83, "verdict": "LIKELY_AI", "categories_affected": ["T3", "T4"], "indicators_count": 7, "disclosure_detected": false, "indicators_detected": [ { "id": "T3.1", "name": "Lack of Personal Anecdotes", "confidence": 95 }, { "id": "T3.2", "name": "Absence of Specific Details", "confidence": 85 }, { "id": "T3.3", "name": "No Emotional Depth", "confidence": 90 } ], "total_duration_ms": 43031 }, "claims": { "total_claims": 4, "verified_true": 0, "verified_false": 0, "unverified": 4, "credibility_score": 75, "claims_verified": [ { "id": "claim_1", "text": "Romania's president declared yesterday that the country will leave the EU by 2025.", "type": "RE", "type_name": "Recent Event", "status": "UV", "status_name": "Neverificat", "sources": [] } ], "total_duration_ms": 43495 }, "domain": null, "verdict": { "risk_score": 78, "risk_category": "UNRELIABLE", "risk_category_color": "red", "risk_level": "VERY_HIGH", "severity": "HIGH", "recommended_action": "ESCALATE", "confidence": 75, "score_manipulation": 35, "score_claims": 25, "score_ai": 83, "override_applied": true, "override_reason": "Undisclosed AI content (+15%)", "explanation_en": "The content is likely AI-generated without disclosure, and the claims lack any verifiable web traces, indicating complete fabrication.", "explanation_ro": "Conținutul este generat probabil de inteligența artificială fără dezvăluire, iar afirmațiile nu au nicio sursă verificabilă online.", "virality_score": 26, "virality_level": "MODERATE" } } } ``` --- ### POST `/api/v3/pipeline/analyze-url` Smart URL analysis. Automatically detects the URL type and processes accordingly: | Detected Type | Platforms | Processing | |---------------|-----------|------------| | **Video platform** | YouTube, TikTok, Twitter/X, Instagram, Facebook, Vimeo, Dailymotion, Twitch | Downloads via yt-dlp → transcribes audio → extracts frames → full pipeline | | **Image** | Direct links ending in `.jpg`, `.jpeg`, `.png`, `.gif`, `.webp`, `.bmp` | Downloads image → OCR via vision model → full pipeline | | **Article** | All other URLs | Fetches page text (M17 AI extraction with direct fetch fallback) → full pipeline | > Platform detection is based on URL pattern matching in `detectUrlType()`. For example, any URL containing `youtube.com` or `youtu.be` is classified as a video platform. **Parameters:** | Field | Type | Required | Description | |-------|------|----------|-------------| | `url` | string | Yes | URL to analyze | | `options` | object | No | Analysis options | **Example:** ```bash curl -sk -X POST https://localhost:3000/agent-v3/api/v3/pipeline/analyze-url \ -H "Content-Type: application/json" \ -d '{ "url": "https://example.com/news-article", "user_id": "test-user" }' ``` **Response (200):** Same structure as `/analyze`, with additional `url_metadata`: ```json { "success": true, "data": { "session_id": "...", "risk_score": 45, "url_metadata": { "original_url": "https://example.com/news-article", "detected_type": "article", "processed_as": "url" }, "...": "full pipeline result" } } ``` --- ### POST `/api/v3/pipeline/analyze-async` Asynchronous analysis via RabbitMQ. Returns immediately with a session ID. Use the [polling endpoints](#6-polling--results) to track progress and retrieve results. **This is the required endpoint for audio and video content**, since transcription and video processing can take 5–10 minutes. **Parameters:** | Field | Type | Required | Description | |-------|------|----------|-------------| | `text` | string | Conditional | Text content | | `media_url` | string | Conditional | Media file URL | | `url` | string | Conditional | URL to analyze | | `media_type` | string | Yes | One of: `text`, `url`, `image`, `audio`, `video` | | `plan_type` | integer | No | Subscription tier 1–6 (affects queue priority). Default: `1` | | `options` | object | No | Analysis options | > Provide at least one of `text`, `media_url`, or `url`. **Example:** ```bash curl -sk -X POST https://localhost:3000/agent-v3/api/v3/pipeline/analyze-async \ -H "Content-Type: application/json" \ -d '{ "media_url": "https://didi365.eu/agent-v3/api/v3/media/file/uploads/user/video.mp4", "media_type": "video", "user_id": "test-user", "plan_type": 2 }' ``` **Response (202 Accepted):** ```json { "success": true, "async": true, "data": { "session_id": "b7f3a1e2-...", "status": "processing", "queued_components": ["techniques", "ai_tampered", "claims"], "plan_type": 2, "poll_url": "/api/v3/pipeline/b7f3a1e2-.../queue-status", "result_url": "/api/v3/pipeline/b7f3a1e2-.../result" } } ``` > **Graceful fallback:** If RabbitMQ is unavailable, the request is processed synchronously and returns `200` with `{ "async": false, "data": { ... full result ... } }`. --- ## 2. Manipulation Techniques Detects manipulation techniques across **166 known patterns** in **8 dimensions**. Uses a 2-phase LLM approach: fast screening followed by deep analysis on flagged content. Runs only the techniques component — no verdict is produced. --- ### POST `/api/v3/techniques/analyze` Analyze text for manipulation techniques. **Parameters:** | Field | Type | Required | Description | |-------|------|----------|-------------| | `text` | string | Yes | Text content to analyze | **Example:** ```bash curl -sk -X POST https://localhost:3000/agent-v3/api/v3/techniques/analyze \ -H "Content-Type: application/json" \ -d '{ "text": "Romania'\''s president declared yesterday that the country will leave the European Union by 2025. According to unnamed government sources, this decision was made in secret meetings with Russian officials.", "user_id": "test-user" }' ``` **Response (200):** ```json { "success": true, "data": { "session_id": "c4d5e6f7-...", "status": "completed", "components_run": ["techniques"], "components_skipped": ["ai_tampered", "claims", "domain", "verdict"], "total_duration_ms": 23998, "techniques": { "manipulation_score": 35, "total_severity": 50, "dimensions_affected": ["D7"], "techniques_count": 1, "techniques_detected": [ { "id": 175, "name": "temporal.embargo_breaking", "dimension": "D7", "subdimension": "Event Timing", "severity": 50, "confidence": 85, "intensity": 2, "evidence": "The announcement was shared widely on social media before any official press conference." } ], "coupling_context": { "for_claims": { "has_emotional_manipulation": false, "has_logical_fallacies": false, "has_source_manipulation": false, "manipulation_level": "CRITICAL", "top_techniques": ["temporal.embargo_breaking"] }, "for_verdict": { "risk_score": 35, "dimension_count": 1, "severe_technique_count": 1, "needs_override_check": true } }, "llm_screening": "qwen35:Qwen3.5-397B-A17B", "llm_deep": "qwen35:Qwen3.5-397B-A17B", "screening_duration_ms": 9521, "deep_analysis_duration_ms": 19942, "total_duration_ms": 29472, "fallbacks_screening": 0, "fallbacks_deep": 0 } } } ``` --- ### POST `/api/v3/techniques/analyze-media` Analyze media for manipulation techniques. The API extracts text first (OCR for images, transcription for audio/video, page fetch for URLs), then runs the techniques analysis on the extracted text. **Parameters:** | Field | Type | Required | Description | |-------|------|----------|-------------| | `media_url` | string | Yes | URL of the media file | | `media_type` | string | Yes | One of: `image`, `audio`, `video`, `url` | **Example:** ```bash curl -sk -X POST https://localhost:3000/agent-v3/api/v3/techniques/analyze-media \ -H "Content-Type: application/json" \ -d '{ "media_url": "https://didi365.eu/agent-v3/api/v3/media/file/uploads/user/screenshot.png", "media_type": "image", "user_id": "test-user" }' ``` --- ### POST `/api/v3/techniques/analyze-async` Queue-based asynchronous techniques analysis. Same async pattern as the full pipeline. **Parameters:** | Field | Type | Required | Description | |-------|------|----------|-------------| | `text` | string | Conditional | Text content | | `media_url` | string | Conditional | Media file URL | | `url` | string | Conditional | URL to fetch and analyze | | `media_type` | string | No | One of: `text`, `image`, `audio`, `video`, `url` (auto-detected if omitted) | | `plan_type` | integer | No | Queue priority tier 1–6. Default: `1` | --- ## 3. AI-Tampered Detection Detects AI-generated content. Uses 2-phase LLM analysis for text and a vision model cascade (local Qwen → Gemini → GPT-4o) for images. --- ### POST `/api/v3/ai-tampered/analyze` Analyze text for AI-generated content indicators. **Parameters:** | Field | Type | Required | Description | |-------|------|----------|-------------| | `text` | string | Yes | Text content to analyze | **Example:** ```bash curl -sk -X POST https://localhost:3000/agent-v3/api/v3/ai-tampered/analyze \ -H "Content-Type: application/json" \ -d '{ "text": "Romania'\''s president declared yesterday that the country will leave the European Union by 2025. According to unnamed government sources, this decision was made in secret meetings with Russian officials.", "user_id": "test-user" }' ``` **Response (200):** ```json { "success": true, "data": { "session_id": "d8e9f0a1-...", "status": "completed", "components_run": ["ai_tampered"], "total_duration_ms": 17920, "ai_tampered": { "ai_probability": 86, "verdict": "LIKELY_AI", "risk_score": 86, "categories_affected": ["T3", "T4"], "indicators_count": 6, "disclosure_detected": false, "indicators_detected": [ { "id": "T3.1", "category": "T3", "name": "Lack of Personal Anecdotes", "confidence": 95, "evidence": "The text is written entirely in the third person with no first-person narratives." }, { "id": "T3.2", "category": "T3", "name": "Absence of Specific Details", "confidence": 90, "evidence": "Critical verifiable facts are missing — 'unnamed government sources', 'secret meetings' without dates or names." }, { "id": "T3.3", "category": "T3", "name": "No Emotional Depth", "confidence": 92, "evidence": "Tone is purely informational and flat, lacking genuine sentiment." }, { "id": "T4.3", "category": "T4", "name": "Low Burstiness", "confidence": 78, "evidence": "Uniform sentence structure and length, lacking natural variation." }, { "id": "T4.4", "category": "T4", "name": "Repetitive N-grams", "confidence": 65, "evidence": "Repetitive passive constructions: 'was made in', 'was shared widely'." } ], "coupling_context": { "for_verdict": { "ai_risk_score": 86, "undisclosed_ai": true, "confidence_level": "HIGH", "needs_manual_review": true } }, "llm_screening": "qwen35:Qwen3.5-397B-A17B", "llm_deep": "qwen35:Qwen3.5-397B-A17B", "total_duration_ms": 17920, "fallbacks_screening": 0, "fallbacks_deep": 0, "content_type": "text" } } } ``` **Verdict scale:** | Verdict | AI Probability | Meaning | |---------|---------------|---------| | `LIKELY_AI` | ≥ 80% | Strong AI-generation indicators | | `UNCERTAIN` | 50–79% | Mixed signals | | `POSSIBLY_HUMAN` | 20–49% | Mostly human-written | | `LIKELY_HUMAN` | < 20% | No significant AI indicators | --- ### POST `/api/v3/ai-tampered/analyze-media` Analyze media for AI-generated content. Supports image (vision analysis), audio (transcription → text analysis), and video (frames + transcript analysis). **Parameters:** | Field | Type | Required | Description | |-------|------|----------|-------------| | `media_url` | string | Yes | URL of the media file | | `media_type` | string | Yes | One of: `image`, `audio`, `video` | **Example:** ```bash curl -sk -X POST https://localhost:3000/agent-v3/api/v3/ai-tampered/analyze-media \ -H "Content-Type: application/json" \ -d '{ "media_url": "https://didi365.eu/agent-v3/api/v3/media/file/uploads/user/photo.jpg", "media_type": "image", "user_id": "test-user" }' ``` --- ### POST `/api/v3/ai-tampered/analyze-image` Quick image-only AI detection via vision model cascade. Lighter response format than `/analyze-media`. **Parameters:** | Field | Type | Required | Description | |-------|------|----------|-------------| | `image_url` | string | Yes | URL of the image to analyze | **Example:** ```bash curl -sk -X POST https://localhost:3000/agent-v3/api/v3/ai-tampered/analyze-image \ -H "Content-Type: application/json" \ -d '{ "image_url": "https://didi365.eu/agent-v3/api/v3/media/file/uploads/user/suspect.jpg", "user_id": "test-user" }' ``` **Response (200):** ```json { "success": true, "data": { "ai_probability": 75, "verdict": "POSSIBLY_AI", "indicators": ["overly smooth skin texture", "background artifacts"], "evidence": "Image shows characteristic AI generation patterns in skin rendering and background consistency.", "model_used": "qwen-vision-local" } } ``` --- ### POST `/api/v3/ai-tampered/quick` Fast heuristic-only screening — **no LLM calls**. Returns instantly. Useful for real-time filtering before committing to a full analysis. **Parameters:** | Field | Type | Required | Description | |-------|------|----------|-------------| | `text` | string | Yes | Text to screen | **Example:** ```bash curl -sk -X POST https://localhost:3000/agent-v3/api/v3/ai-tampered/quick \ -H "Content-Type: application/json" \ -d '{"text": "Some text to screen quickly", "user_id": "test-user"}' ``` --- ### POST `/api/v3/ai-tampered/analyze-async` Queue-based asynchronous AI detection. Same async pattern as the full pipeline. **Parameters:** Same as [techniques/analyze-async](#post-apiv3techniquesanalyze-async). --- ## 4. Claims Verification Extracts factual claims from content and verifies them against web sources. Pipeline: **LLM extraction → web evidence search → LLM per-claim verification**. --- ### POST `/api/v3/claims/analyze` Analyze text for factual claims and verify them. **Parameters:** | Field | Type | Required | Description | |-------|------|----------|-------------| | `text` | string | Yes | Text content to analyze | **Example:** ```bash curl -sk -X POST https://localhost:3000/agent-v3/api/v3/claims/analyze \ -H "Content-Type: application/json" \ -d '{ "text": "Romania'\''s president declared yesterday that the country will leave the European Union by 2025. According to unnamed government sources, this decision was made in secret meetings with Russian officials.", "user_id": "test-user" }' ``` **Response (200):** ```json { "success": true, "data": { "session_id": "e1f2a3b4-...", "status": "completed", "components_run": ["claims"], "total_duration_ms": 17787, "claims": { "total_claims": 5, "verified_true": 0, "verified_false": 0, "unverified": 5, "opinions": 0, "credibility_score": 75, "interpretation": "Substantial agreement", "claims_by_status": { "UV": 5 }, "claims_by_type": { "RE": 3, "PC": 1, "QA": 1 }, "claims_verified": [ { "id": "claim_1", "text": "Romania's president declared yesterday that the country will leave the EU by 2025.", "type": "RE", "type_name": "Recent Event", "priority": "high", "context": "Asserts a specific recent declaration by a head of state.", "status": "UV", "status_name": "Neverificat", "status_color": "gray", "confidence": 0, "agreement_score": 0, "sources": [], "reasoning": "No web sources found for verification", "verification_method": "N/A" }, { "id": "claim_2", "text": "Romania will leave the European Union by 2025.", "type": "PC", "type_name": "Predictive Claim", "priority": "high", "status": "UV", "status_name": "Neverificat", "sources": [], "reasoning": "No web sources found for verification" }, { "id": "claim_3", "text": "The decision to leave the EU was made in secret meetings with Russian officials.", "type": "RE", "type_name": "Recent Event", "priority": "high", "status": "UV", "status_name": "Neverificat", "sources": [], "reasoning": "No web sources found for verification" } ], "llm_extraction": "qwen35:Qwen3.5-397B-A17B", "llm_verification": "unknown", "extraction_duration_ms": 34240, "verification_duration_ms": 9250, "total_duration_ms": 17787, "web_searches_made": 0 } } } ``` **Claim types:** | Code | Name | Description | |------|------|-------------| | `VF` | Verifiable Fact | Objectively checkable statement | | `RE` | Recent Event | Assertion about a recent occurrence | | `PC` | Predictive Claim | Future prediction | | `QA` | Quoted Attribution | Claim attributed to a source | | `ST` | Statistical | Numeric/statistical claim | | `OP` | Opinion | Subjective statement | **Claim statuses:** | Code | Name | Meaning | |------|------|---------| | `VT` | Verified True | Confirmed by web sources | | `VF` | Verified False | Contradicted by web sources | | `PT` | Partially True | Mixed evidence | | `UV` | Unverified | No sources found | | `OP` | Opinion | Not verifiable | --- ### POST `/api/v3/claims/analyze-media` Analyze media for claims. Extracts text first (OCR, transcription, URL fetch), then runs claims analysis. **Parameters:** | Field | Type | Required | Description | |-------|------|----------|-------------| | `media_url` | string | Yes | URL of the media file | | `media_type` | string | Yes | One of: `image`, `audio`, `video`, `url` | **Example:** ```bash curl -sk -X POST https://localhost:3000/agent-v3/api/v3/claims/analyze-media \ -H "Content-Type: application/json" \ -d '{ "media_url": "https://didi365.eu/agent-v3/api/v3/media/file/uploads/user/recording.mp3", "media_type": "audio", "user_id": "test-user" }' ``` --- ### POST `/api/v3/claims/analyze-async` Queue-based asynchronous claims analysis. Same async pattern as the full pipeline. **Parameters:** Same as [techniques/analyze-async](#post-apiv3techniquesanalyze-async). --- ## 5. Domain Analysis Analyzes domain credibility using WHOIS, DNS, SSL, blacklist, and IP intelligence checks. **Does not use LLM** — purely infrastructure-based analysis. --- ### POST `/api/v3/domain/analyze` Analyze a domain for trustworthiness indicators. **Parameters:** | Field | Type | Required | Description | |-------|------|----------|-------------| | `domain` | string | Conditional | Domain name (e.g., `reuters.com`) | | `url` | string | Conditional | Full URL — domain is extracted automatically | > Provide at least one. If both are given, `domain` takes precedence. **Example:** ```bash curl -sk -X POST https://localhost:3000/agent-v3/api/v3/domain/analyze \ -H "Content-Type: application/json" \ -d '{"url": "https://reuters.com", "user_id": "test-user"}' ``` **Response (200):** ```json { "success": true, "data": { "domain": "reuters.com", "verdict": "TRUSTED", "trust_score": 90, "risk_level": "LOW", "age": { "days": 11977, "category": "WELL_ESTABLISHED", "created_at": "1993-06-17T00:00:00Z" }, "blacklist": { "is_blacklisted": false, "reputation_score": 100 }, "ssl": { "has_ssl": true, "is_valid": true, "issuer": "CN=Sectigo Public Server Authentication CA OV R40, O=Sectigo Limited, C=GB" }, "ownership": { "registrar": "CSC Corporate Domains, Inc.", "organization": "Thomson Reuters Enterprise Centre GmbH", "country": "CH" }, "red_flags": [], "warnings": [], "metadata": { "duration_ms": 8054 } } } ``` **Verdict values:** | Verdict | Meaning | |---------|---------| | `TRUSTED` | Established domain, high reputation, no flags | | `NEUTRAL` | No strong signals either way | | `SUSPICIOUS` | One red flag or multiple warnings | | `UNTRUSTED` | Multiple red flags or blacklisted | **Possible red flags:** `DOMAIN_VERY_NEW`, `BLACKLISTED`, `LOW_REPUTATION`, `NO_SSL`, `INVALID_SSL`, `NO_DNS_RECORDS`, `SUSPICIOUS_DOMAIN` **Possible warnings:** `DOMAIN_RELATIVELY_NEW`, `MEDIUM_REPUTATION`, `SELF_SIGNED_SSL`, `NO_EMAIL_SECURITY`, `HOSTED_IN_DATACENTER`, `WHOIS_PRIVACY_ENABLED` --- ### POST `/api/v3/domain/analyze-async` Queue-based asynchronous domain analysis. **Parameters:** | Field | Type | Required | Description | |-------|------|----------|-------------| | `domain` | string | Conditional | Domain name | | `url` | string | Conditional | URL (domain extracted) | | `plan_type` | integer | No | Queue priority tier 1–6. Default: `1` | --- ## 6. Polling & Results After submitting an async analysis, use these endpoints to track progress and retrieve results. --- ### GET `/api/v3/pipeline/:sessionId/status` Poll the status of a running or completed analysis. **Example:** ```bash curl -sk https://localhost:3000/agent-v3/api/v3/pipeline/a63a72ed-de8e-458b-a708-3e80d38f867c/status \ ``` **Response (200):** ```json { "success": true, "data": { "session_id": "a63a72ed-...", "status": "completed", "components": { "domain": { "status": "skipped" }, "techniques": { "status": "completed" }, "ai_tampered": { "status": "completed" }, "claims": { "status": "completed" }, "verdict": { "status": "completed" } }, "progress": { "completed": 4, "total": 4, "percentage": 100 } } } ``` **Component status values:** `pending` | `running` | `completed` | `failed` | `skipped` --- ### GET `/api/v3/pipeline/:sessionId/result` Get the full result of a completed analysis. Returns the complete `AnalysisSession` object (same structure as the `/analyze` response `data`). Falls back to PostgreSQL if the session has expired from Redis cache. **Example:** ```bash curl -sk https://localhost:3000/agent-v3/api/v3/pipeline/a63a72ed-de8e-458b-a708-3e80d38f867c/result \ ``` --- ### GET `/api/v3/pipeline/:sessionId/component/:name` Get a single component's result from a completed analysis. **Path parameter:** `:name` — one of: `techniques`, `ai_tampered`, `claims`, `domain`, `verdict` **Example:** ```bash curl -sk https://localhost:3000/agent-v3/api/v3/pipeline/a63a72ed-.../component/verdict \ ``` --- ### GET `/api/v3/pipeline/:sessionId/queue-status` Poll progress of an async (RabbitMQ) job. Returns partial results as components complete. **Example:** ```bash curl -sk https://localhost:3000/agent-v3/api/v3/pipeline/b7f3a1e2-.../queue-status \ ``` **Response (200):** ```json { "success": true, "data": { "session_id": "b7f3a1e2-...", "status": "running", "techniques": { "manipulation_score": 35, "..." : "..." }, "ai_tampered": null, "claims": null, "_queue": { "progress": 33, "total_components": 3, "completed_components": ["techniques"], "elapsed_ms": 25000, "plan_type": 2 } } } ``` --- ## 7. Browser Extension API Separate authentication flow using API keys instead of JWT. Designed for the DIDI browser extension. --- ### POST `/api/v3/pipeline/extension/analyze` Analyze content using an API key. **Headers:** | Header | Required | Description | |--------|----------|-------------| | `X-API-Key` | Yes | Extension API key (obtained from the admin dashboard) | | `Content-Type` | Yes | `application/json` | **Parameters:** | Field | Type | Required | Description | |-------|------|----------|-------------| | `text` | string | Conditional | Text to analyze | | `image_url` | string | Conditional | Image URL to analyze | | `url` | string | Conditional | URL to analyze | | `options` | object | No | `{ skip_components: string[] }` | > Provide at least one of `text`, `image_url`, or `url`. **Example:** ```bash curl -sk -X POST https://localhost:3000/agent-v3/api/v3/pipeline/extension/analyze \ -H "Content-Type: application/json" \ -H "X-API-Key: didi_ext_abc123..." \ -d '{"text": "Content to check for misinformation"}' ``` **Response (200):** Same structure as `/pipeline/analyze`, with an additional `analysis_type` field indicating what was analyzed (`text`, `image`, or `url`). --- ## Error Codes | HTTP | Code | Description | |------|------|-------------| | `400` | `INVALID_TEXT_INPUT` | Text validation failed (too short, too long, invalid encoding) | | `400` | `ASYNC_REQUIRED` | Audio/video content must use the async endpoint | | `401` | — | Missing or invalid JWT token / API key | | `402` | — | Insufficient credits. Response includes `creditsRemained` and `creditCost` | | `404` | — | Session not found | | `500` | — | Internal server error | --- ## Rate Limits Applied by Kong at the gateway level: | Window | Limit | |--------|-------| | Per minute | 100 requests | | Per hour | 2,000 requests | | Per day | 10,000 requests | --- ## Timeouts | Endpoint Type | Timeout | |---------------|---------| | Full pipeline (text) | 180 seconds | | Full pipeline (video) | 660 seconds (11 min) | | Individual component (text) | 180 seconds | | Individual component (media) | 300 seconds (5 min) | | Domain analysis | 90 seconds |