didi-lot2-backend/backend/services/orchestration-layer/agent-v3/API_DOCUMENTATION.md
2026-07-10 03:39:53 -07:00

31 KiB
Raw Blame History

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
  2. Full Pipeline
  3. Manipulation Techniques
  4. AI-Tampered Detection
  5. Claims Verification
  6. Domain Analysis
  7. Polling & Results
  8. Browser Extension API
  9. Error Codes

Authentication

Pass user_id in the request body to identify the user:

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 25) 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 510 minutes. The endpoint returns 400 with code: "ASYNC_REQUIRED". Use POST /api/v3/pipeline/analyze-async for audio and video content instead.

Example:

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):

{
  "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:

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:

{
  "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 to track progress and retrieve results.

This is the required endpoint for audio and video content, since transcription and video processing can take 510 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 16 (affects queue priority). Default: 1
options object No Analysis options

Provide at least one of text, media_url, or url.

Example:

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):

{
  "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:

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):

{
  "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:

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 16. 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:

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):

{
  "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 5079% Mixed signals
POSSIBLY_HUMAN 2049% 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:

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:

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):

{
  "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:

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.


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:

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):

{
  "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:

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.


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:

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):

{
  "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 16. 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:

curl -sk https://localhost:3000/agent-v3/api/v3/pipeline/a63a72ed-de8e-458b-a708-3e80d38f867c/status \

Response (200):

{
  "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:

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:

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:

curl -sk https://localhost:3000/agent-v3/api/v3/pipeline/b7f3a1e2-.../queue-status \

Response (200):

{
  "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:

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