TrustOriginality.ai Detection API

Programmatic access to TrustOriginality.ai's multimodal AI-content detection engine. Analyze text, images, audio, and video for AI-generation likelihood and receive a forensic PDF report for every analysis.

Base URL: https://panel.trustoriginality.ai

Use of this API is governed by the API Terms of Use, the Acceptable Use Policy, and the AI liability disclaimer. By sending authenticated requests you agree to those documents in addition to your subscription or order form.

Authentication

Create an API key in the panel under Account > API Keys. Send it with every request, either as a header:

X-Api-Key: to_live_xxxxxxxxxxxxxxxxxxxx

or as a bearer token:

Authorization: Bearer to_live_xxxxxxxxxxxxxxxxxxxx

Keys are shown only once at creation time and can be revoked at any moment from the panel.

Credits and limits

  • Every analysis (any modality) consumes 1 credit from your plan's monthly allowance. API usage and panel usage share the same credit pool.
  • Credit packs can be purchased in the panel under Account > Credits. Pack credits never expire, are consumed only after the monthly allowance is exhausted, and keep the API working even while a subscription is lapsed.
  • When no credits remain, the API returns 402 Payment Required with creditsUsed, creditsLimit and packCreditsRemaining fields.
  • Free plan: 1 text-only analysis per calendar month in the web portal — no API, image, audio or video or media analysis. Upgrade to a paid plan for API access and higher limits.
  • Quick Check plan: entry subscription at €4.99/month with 3 analyses per calendar month — ideal for testing an integration before upgrading to Starter or higher.
  • Requests are rate limited to 20 per minute per IP (HTTP 429 when exceeded).

Every analysis in the panel's Activity Log has a Copy link button that produces a public, HMAC-signed, time-limited (30 days) verification URL of the form /verify/{id}?e=...&s=.... Anyone with the link can view the verdict and download the PDF report without an account; the link cannot be forged or extended.

In addition, every generated PDF report embeds its own signed verification link as a QR code (valid 1 year), so a printed or forwarded report can always be checked against the original at /verify/r/{runId}.

Endpoints

POST /api/text/analyze

Content-Type: application/json

curl -X POST https://panel.trustoriginality.ai/api/text/analyze \
  -H "X-Api-Key: to_live_..." \
  -H "Content-Type: application/json" \
  -d '{"text": "The content you want to analyze..."}'

POST /api/image/analyze

Content-Type: multipart/form-data — field file (jpg, jpeg, png, webp, bmp, gif, tif, tiff; max 30 MB). Optional field name to label the analysis.

Every image analysis runs a Verify Suite cross-layer audit in addition to forensic detectors. The response evidences array includes a consistency_audit entry (weight 0, informational) summarizing contradictions between declared provenance and forensic findings.

curl -X POST https://panel.trustoriginality.ai/api/image/analyze \
  -H "X-Api-Key: to_live_..." \
  -F "file=@photo.jpg" \
  -F "name=Product photo check"

Additional response fields (pHash pipeline): contentHash, perceptualHash, provenanceRegistered, similarMatches[] (near-duplicates with hammingDistance and verifyUrl).

POST /api/image/phash/scan

Lightweight pHash-only scan (no forensic ensemble, no credit charge for resolve-only lookup). Same multipart file input as image analyze. Requires AnalyzeAccess.

Returns contentHash, perceptualHash, exactMatch, provenanceRegistered, similarMatches[].

curl -X POST https://panel.trustoriginality.ai/api/image/phash/scan \
  -H "X-Api-Key: to_live_..." \
  -F "file=@recompressed-from-instagram.jpg"

Background pipeline: ProvenancePhashBackgroundService backfills missing pHashes from C2PA thumbnails. Optional ProvenanceWatch config polls a directory for newly dropped images and fires a webhook when a near-duplicate is detected (re-compress ingest watch).

Verify Suite signals (detected automatically during analysis):

Evidence type Source Role in audit
c2pa_provenance Embedded C2PA / Content Credentials manifest (JUMBF + COSE) Cryptographic signature validity, generative-AI declaration
watermark_signature Producer metadata watermarks (Stable Diffusion, DALL-E, Firefly, …) Declared AI origin from tool fingerprints
trustoriginality_watermark TrustOriginality DCT/LSB invisible watermark + registry lookup Registered owner, declaration, license
consistency_audit Cross-layer rule engine (ProvenanceCrossCheckService) Final verdict and finding codes

consistency_audit metrics:

Field Values Meaning
status contradiction, warning, consistent, consistent_declared, no_conflict Overall audit status
finding_codes Comma-separated codes (see below) Actionable finding identifiers
c2pa_signature_valid True, False, none COSE signature verification result
declared_ai_origin boolean Any declared layer claims AI involvement
trustoriginality_watermark_registered boolean NeuroSeal watermark resolves to a registry record
forensic_score 0.0–1.0 or n/a Weighted forensic ensemble score

Finding codes (shared with POST /api/verify/cross-check):

Code Severity Meaning
c2pa_signature_invalid contradiction Manifest present but COSE signature failed — altered or re-signed
c2pa_signature_not_verified warning Manifest present; signature algorithm not supported for verification
c2pa_signature_valid ok Signature cryptographically verified
manifest_vs_forensics contradiction Provenance claims non-AI origin; forensics indicate AI generation
watermark_vs_forensics contradiction Registered TrustOriginality watermark says human-created; forensics indicate AI
declaration_conflict contradiction Registry says human-created; C2PA manifest declares generative-AI
registry_signature_invalid contradiction Registry record HMAC does not match
manifest_stripped contradiction Content was registered with a manifest; file no longer carries one
manifest_replaced contradiction In-file manifest differs from the one archived at registration
manifest_reattached warning Archived manifest matches but file bytes differ from registered original
manifest_matches_archive ok File is byte-identical to registered content
phash_similar_match info No exact hash match; perceptually similar registered image found (re-compressed copy)
c2pa-signer-untrusted warning C2PA signer not on the attestation trust list or signature invalid
no_provenance info No registry record and no embedded C2PA manifest

Example consistency_audit excerpt:

{
  "type": "consistency_audit",
  "summary": "CONTRADICTION: provenance manifest claims non-AI origin, but forensic analysis indicates AI generation.",
  "metrics": {
    "status": "contradiction",
    "finding_codes": "manifest_vs_forensics",
    "c2pa_signature_valid": "True",
    "declared_ai_origin": false,
    "forensic_score": 0.742
  },
  "weight": 0,
  "confidence": 0.5
}

The forensic PDF report includes the same Verify Suite block with C2PA signature details, TrustOriginality watermark status, and finding codes highlighted in red (contradiction) or orange (warning).

POST /api/audio/analyze

Content-Type: multipart/form-data — field file (mp3, wav, m4a, aac, ogg, oga, flac; max 75 MB).

POST /api/video/analyze

Content-Type: multipart/form-data — field file (mp4, mov, avi, mkv, webm, m4v; max 300 MB).

POST /api/watermark/embed

Embeds an invisible watermark into an image and returns the watermarked PNG. The image's SHA-256 is registered in the Provenance Registry so the mark resolves back to a verifiable registry record. Two methods:

  • method=robust (default) — DCT-domain mark carrying the provenance hash; survives JPEG re-compression (tested down to quality 60). Requires images of at least ~140x140 px.
  • method=lsb — pixel-LSB mark with an arbitrary payload (max 512 bytes); higher capacity but lossless formats (PNG/BMP) only.

Content-Type: multipart/form-data — field file (image), optional method, optional payload (lsb only).

curl -X POST https://panel.trustoriginality.ai/api/watermark/embed \
  -H "X-Api-Key: to_live_..." \
  -F "file=@artwork.png" -o artwork-watermarked.png

POST /api/watermark/extract

Content-Type: multipart/form-data — field file (image). Tries the robust mark first, then LSB. Returns { "found": true, "method": "robust|lsb", "payload": "...", "provenance": { ... } }; provenance is filled when the payload references a registry record.

POST /api/watermark/audio/embed

Embeds an inaudible LSB watermark into a 16-bit PCM WAV file and returns the watermarked WAV. Without a payload field the audio's SHA-256 is registered in the Provenance Registry (optional license field, e.g. CC BY 4.0) and to:<hash> is embedded. Lossless audio only — MP3/AAC re-encoding destroys the mark.

Content-Type: multipart/form-data — field file (WAV, max 75 MB), optional payload (max 512 bytes), optional license.

POST /api/watermark/audio/extract

Content-Type: multipart/form-data — field file (WAV). Same response shape as the image extract endpoint.

GET /api/rights/

Rights query (NeuroSeal DRM): "who owns this content?" Resolves a SHA-256 content hash — typically extracted from a watermark — to the registered owner, declaration and license:

{
  "registered": true,
  "contentHash": "…64 hex chars…",
  "owner": "Jane Doe",
  "declaration": "human-created",
  "license": "CC BY 4.0",
  "registeredAt": "2026-06-12T10:31:36Z",
  "signatureValid": true
}

Returns 404 with { "registered": false } for unregistered hashes. The license field is set at registration time via the optional license form field of POST /api/provenance/register and the watermark embed endpoints.

GET /api/provenance/

Returns the C2PA manifest archived at registration time for a registered content hash. When content is registered via POST /api/provenance/register (or any watermark embed endpoint) and the file carries a C2PA / Content Credentials manifest, the raw JUMBF manifest store is parsed (claim, COSE signature, signer certificate) and archived. Social platforms strip C2PA metadata on re-encode — the archive lets the original provenance be recovered from the hash alone.

  • default / ?format=json — parsed summary: claim generator, title, digital source types, actions, assertion labels, signature algorithm, cryptographic signature validity (COSE_Sign1 ES256/384/512, PS256/384/512, RS256), signer subject/issuer.
  • ?format=raw — the original JUMBF manifest store bytes as a download.

Returns 404 with { "found": false } when no manifest was archived for the hash.

Public recovery (no API key):

  • GET /api/provenance/public/{hash}/manifest — same as above, rate-limited, no authentication.
  • GET /verify/content/{hash}/manifest?format=raw|json — human-facing verification site.
  • Public registry page: GET /verify/content/{hash} shows archived manifest metadata and a download link when present.

POST /api/provenance/resolve

Public, rate-limited content resolver. Upload a file and get:

  • Exact SHA-256 registry match (if any)
  • Archived C2PA manifest for that hash (if registered with a manifest)
  • Content-only manifest lookup (finds the original registration after C2PA stripping)
  • Perceptual near-duplicates (similarMatches) — registered images with Hamming distance ≤ 15 on the 64-bit DCT pHash

Content-Type: multipart/form-data — field file (image, max 50 MB). No API key required.

curl -X POST https://panel.trustoriginality.ai/api/provenance/resolve \
  -F "file=@recompressed-from-instagram.jpg"

Response fields: contentHash, perceptualHash, exactMatch, registry, archivedManifest, relatedManifest (content-only-hash match), similarMatches[] with hammingDistance.

Use this when a social platform re-encoded the file: SHA-256 will differ, but pHash may still find the original registration.

GET /api/provenance/

Public near-duplicate lookup for an already-registered content hash. Computes similarity against other registry entries using the stored perceptual hash.

Query params: maxDistance (default 15), limit (default 5, max 20).

Returns { "contentHash", "perceptualHash", "similar": [ { "contentHash", "hammingDistance", … } ] }.

Perceptual hash at registration: image registrations (POST /api/provenance/register, watermark embed endpoints) store a 16-hex-char DCT pHash on Tbl_ProvenanceRecords.PerceptualHash and a numeric PhashBits index for faster similarity queries. Re-registering an existing hash backfills pHash when missing. A background job also backfills legacy rows from archived C2PA claim thumbnails when available.

GET /verify/anchors and /verify/anchors.json

Public, no authentication. Daily Merkle anchors over the Provenance Registry: each day's root commits to every content hash registered that day and is HMAC-signed by the registry. Anchors created after the 2C release also include a manifest Merkle root (manifestMerkleRoot) over archived C2PA manifest hashes for that day.

Roots are additionally published to OpenTimestamps calendar servers (Bitcoin-anchored, free): the externalRef field names the calendar and links the downloadable .ots timestamp proof served under /anchors/.

Merkle inclusion proofs (public):

  • GET /verify/anchors/{yyyy-MM-dd}/proof/{contentHash} — proves a content hash is included in the day's registry Merkle tree.
  • GET /verify/anchors/{yyyy-MM-dd}/manifest-proof/{contentHash} — proves the archived manifest hash for that content is included in the day's manifest Merkle tree.

Each response includes leaf, root, steps[] (sibling hashes), and verified: true/false.

C2PA container support (2C): structural parsing and manifest extraction now include JPEG APP11, PNG caBX, WebP C2PA, plus HEIC/HEIF/AVIF (ISO BMFF scan) and PDF (embedded JUMBF scan).

TrustOriginality Box offline registry: air-gapped deployments expose the same registry semantics via SQLite — POST /registry/register, GET /registry/{hash}, GET /registry/{hash}/manifest?format=raw, GET /registry/export.json. See TrustOriginality_Box/README.md.

POST /api/verify/cross-check

Cross-layer provenance audit for a single file. Compares three independent layers and reports contradictions:

  1. In-file C2PA manifest — structurally parsed (JPEG APP11 / PNG caBX / WebP), COSE signature cryptographically verified.
  2. Provenance Registry record — declaration, license, HMAC integrity.
  3. Archived manifest — the manifest captured at registration. Lookup also works by content-only hash (file bytes with C2PA segments removed), so a stripped or replaced manifest is still traced back to the original registration.

Content-Type: multipart/form-data — field file (max 300 MB).

curl -X POST https://panel.trustoriginality.ai/api/verify/cross-check \
  -H "X-Api-Key: to_live_..." \
  -F "file=@suspect.jpg"

Response:

{
  "contentHash": "…64 hex chars…",
  "verdict": "consistent",
  "signerTrust": {
    "status": "trusted",
    "matchedRoot": "Adobe Content Authenticity",
    "signerSubject": "CN=…"
  },
  "findings": [
    { "severity": "ok", "code": "c2pa_signature_valid", "message": "C2PA manifest signature verified (PS256, signer: …)." },
    { "severity": "ok", "code": "manifest_matches_archive", "message": "The file is byte-identical to the registered content; its C2PA manifest matches the archived copy." }
  ],
  "layers": {
    "fileManifest": {
      "present": true,
      "parseSucceeded": true,
      "claimGenerator": "…",
      "digitalSourceTypes": [],
      "signatureAlgorithm": "PS256",
      "signatureValid": true,
      "signer": "CN=…"
    },
    "registry": {
      "registered": true,
      "declaration": "human-created",
      "license": "All rights reserved",
      "registeredAt": "2026-06-12T10:31:36Z",
      "signatureValid": true
    },
    "archive": {
      "matchedBy": "exact-hash",
      "registeredContentHash": "…",
      "archivedAt": "2026-06-12T10:31:36Z",
      "manifestHash": "…",
      "manifestSizeBytes": 51118
    }
  }
}
  • verdictconsistent, warning, or contradiction (same rule engine as image analysis consistency_audit).
  • findings[].severitycontradiction, warning, ok, or info.
  • layers.archive.matchedByexact-hash (full file match) or content-only-hash (manifest-independent lookup after C2PA strip).

Notable finding codes: c2pa_signature_invalid (manifest altered or re-signed), manifest_stripped (registered with a manifest the file no longer has), manifest_replaced (in-file manifest differs from the archived one), declaration_conflict (registered as human-created but the manifest declares generative-AI origin), watermark_vs_forensics and manifest_vs_forensics when forensic context is supplied via analysis rather than this endpoint.

Alignment with image analysis: /api/image/analyze and /api/verify/cross-check both use ProvenanceCrossCheckService — the same finding codes apply to the consistency_audit evidence in analysis responses and to the findings array here. Archive-layer codes (manifest_stripped, manifest_replaced) require a prior registry registration with manifest archival; they appear on cross-check when content-only hash lookup finds a related registration.

Attestation Service

TrustOriginality issues ECDSA-P256-SHA256 attestations verifiable with a published public key — no shared secret required for third-party verification.

GET /.well-known/trustoriginality-attestation.json

Public key document (JWK-style PEM + verify endpoint URLs). No authentication.

GET /.well-known/trustoriginality-trust-list.json

Public C2PA producer trust list (trustoriginality-trust-list/1.1). Lists active trustedProducers with signerPattern, optional keyId, publicKeyPem, and caCertificatePem. Includes ownCaRoot URL for the platform PKIX root. Cross-check and EU labels use this list (signerTrust / c2pa-signer-untrusted).

Manage roots in the panel under CA Trust Roots. Seed defaults with SeedAttestationTrustRoots.sql. On startup the platform auto-registers its own C2PA signer.

GET /.well-known/trustoriginality-ca-root.pem

PEM-encoded PKIX root certificate for TrustOriginality-issued C2PA leaf signers.

POST /api/attestation/verify

Verify an attestation document signature (ECDSA-P256). Body options:

{ "contentHash": "abc123..." }
{ "runId": "guid" }
{ "attestation": { "format": "trustoriginality-attestation/1.0", ... } }

Returns { valid, signatureValid, errors[] }.

Verifiable Credentials (JWT VC)

W3C Verifiable Credentials in JWT format (trustoriginality-jwt-vc/1.0), signed with the same ECDSA-P256 key as attestations. Non-qualified issuer — not QEAA or eIDAS qualified trust services.

Full reference: docs/VERIFIABLE-CREDENTIALS.md

GET /.well-known/trustoriginality-credential-issuer.json

Issuer metadata, supported credential types, and schema URLs. Public.

GET /.well-known/vc-schemas/content-authenticity.json

JSON Schema for TrustOriginalityContentAuthenticityCredential. Public.

GET /.well-known/vc-schemas/analysis-report.json

JSON Schema for TrustOriginalityAnalysisReportCredential. Public.

GET /api/credentials/content/

Issue a content authenticity VC for a registered SHA-256 hash. Requires AnalyzeAccess; authenticated user must own the provenance registration.

GET /api/credentials/analysis/

Issue an analysis report VC. Requires AnalyzeAccess; authenticated user must own the run. Also available from panel Activity Log (Download VC).

POST /api/credentials/verify

Verify a JWT VC. Public — no API key required.

curl -sk -X POST https://panel.trustoriginality.ai/api/credentials/verify \
  -H "Content-Type: application/json" \
  -d '{"jwt":"eyJhbGciOiJFUzI1NiIs..."}'

POST /api/credentials/revoke

Revoke a credential by jti. Requires AnalyzeAccess; only the issuing account owner can revoke.

curl -sk -X POST https://panel.trustoriginality.ai/api/credentials/revoke \
  -H "X-Api-Key: to_live_..." \
  -H "Content-Type: application/json" \
  -d '{"jti":"vc-...","reason":"optional reason"}'

POST /api/verify/evidence

Upload a signed evidence package zip from the panel Activity Log. Returns file integrity, HMAC validity (legacy) and ECDSA public signature validity.

curl -X POST https://panel.trustoriginality.ai/api/verify/evidence \
  -F "file=@evidence-abc123.zip"

Evidence packages exported after this release use format trustoriginality-evidence/2.0 (HMAC + ECDSA dual signature).

GET /api/attestation/content/

Downloadable provenance registry attestation for a registered content hash: declaration, registry HMAC status, optional archived C2PA manifest reference, daily Merkle anchor, and ECDSA attestation signature.

Public, rate-limited. Also linked from /verify/content/{hash}.

GET /api/attestation/analysis/

Signed attestation of an analysis result (score, verdict, timestamp). Public for any known runId (same identifier embedded in PDF QR codes and evidence packages).

POST /api/attest/content

Producer attestation workflow: register content in the Provenance Registry and return a signed registry attestation in one call. Requires AnalyzeAccess (panel session or API key).

curl -X POST https://panel.trustoriginality.ai/api/attest/content \
  -H "X-Api-Key: to_live_..." \
  -F "file=@photo.jpg" \
  -F "declaration=human-created" \
  -F "license=CC-BY-4.0"

Form fields:

Field Required Description
file yes Image or media file to register
declaration no human-created, ai-assisted, or ai-generated
license no SPDX or free-text license label
embedC2pa no true to embed a signed C2PA manifest (JPEG, PNG, or WebP) before registration
returnFile no With embedC2pa=true, return the signed image instead of JSON

JSON response includes the full attestation document plus contentHash, verifyUrl, and attestationUrl. When returnFile=true, the signed JPEG is returned with X-TrustOriginality-Content-Hash and X-TrustOriginality-Attestation-Url headers.

POST /api/c2pa/sign

Embed a minimal signed C2PA manifest (ES256, c2pa.created action) into a JPEG, PNG, or WebP image without registering in the Provenance Registry. Requires AnalyzeAccess.

curl -X POST https://panel.trustoriginality.ai/api/c2pa/sign \
  -H "X-Api-Key: to_live_..." \
  -F "file=@photo.png" \
  -F "declaration=human-created" \
  -o photo-c2pa.png

Returns the signed image (same format as input). Response header X-TrustOriginality-C2pa-Manifest names the manifest URN. Verify with any C2PA-aware reader or POST /api/verify/cross-check.

Response

All endpoints return the same shape on success (HTTP 200):

{
  "isAIGeneratedLikely": true,
  "score": 0.87,
  "evidences": [
    { "detector": "PseudoPerplexityDetector", "weight": 0.4, "note": "..." }
  ],
  "pdf": "/reports/3f2a9c1e-....pdf",
  "activityId": 1234,
  "verifyUrl": "https://panel.trustoriginality.ai/verify/1234?e=...&s=...",
  "credits": { "used": 12, "limit": 50, "plan": "Starter" }
}
  • score — 0.0 (human) to 1.0 (AI-generated) likelihood.
  • pdf — relative URL of the forensic PDF report (authenticated download).
  • activityId / verifyUrl — present when the caller is authenticated (panel cookie or API key); use for LMS feedback snippets and EU AI Act audit trails.
  • credits — your usage after this analysis.

LTI 1.3 (LMS integration)

Panel routes for Moodle / Canvas / Blackboard tool registration:

Route Purpose
GET/POST /lti/login OIDC login initiation
POST /lti/launch Receives id_token, opens analyze UI
POST /lti/submit Multimodal integrity submission (text + image + audio + video)
POST /lti/record Record completed single-artifact analysis to integrity audit trail
POST /lti/grade AGS score passback (requires score scope + lineitem in launch)
GET /lti/jwks Tool public JWKS (alias: /.well-known/jwks.json)
GET /Lti/Analyze Instructor submission check UI
GET /Integrity/Report Per-course integrity report (CSV/PDF export)

See docs/INTEGRITY-SUITE.md for the education workflow.

POST /api/insurance/verify

Composite insurance claim screening (damage photo + invoice + ID + voice). See docs/INSURANCE-CLAIMS.md.

curl -X POST https://panel.trustoriginality.ai/api/insurance/verify \
  -H "X-Api-Key: to_live_..." \
  -F "damagePhoto=@damage.jpg" \
  -F "invoice=@estimate.jpg" \
  -F "claimRef=CLM-2026-001"

POST /api/publish-gate/check

CMS pre-publish gate (text + optional hero image). See docs/PUBLISH-GATE.md.

curl -X POST https://panel.trustoriginality.ai/api/publish-gate/check \
  -H "X-Api-Key: to_live_..." \
  -F "title=Headline" \
  -F "text=Article body…" \
  -F "image=@hero.jpg"

POST /api/agent/scan

Agent / RAG / copilot output scanner. See docs/AGENT-SCANNER.md.

curl -X POST https://panel.trustoriginality.ai/api/agent/scan \
  -H "X-Api-Key: to_live_..." \
  -H "Content-Type: application/json" \
  -d '{"text":"Agent output…","agentId":"support-bot"}'

GET /api/threat-intel/feed

Public curated deepfake threat briefs. See docs/THREAT-INTEL.md.

curl https://panel.trustoriginality.ai/api/threat-intel/feed

Also: GET /.well-known/trustoriginality-threat-feed.json

GET /.well-known/trustoriginality-compliance-pack.json

EU AI Act Compliance Pack sales/technical manifest (components, pricing, Art. 50 deadlines).

GET /Compliance/ExportAuditBundle

Panel session — ZIP with CSV audit trail, JSON-LD labels, and pack manifest for the selected period.

Call Guard (Teams / Zoom)

Route Auth Purpose
POST /api/call-guard/integrations/hook/{webhookKey} HMAC signature Ingest meeting audio/video chunk
GET /CallGuard Panel session Connector setup + active meeting EMA

See docs/CALL-GUARD.md.

Public Sector Pack

Route Auth Purpose
GET /.well-known/trustoriginality-public-sector-pack.json Public Kamu ihale paket manifest
GET /PublicSector Panel session Pack overview + pilot applications

See docs/PUBLIC-SECTOR-PACK.md and docs/KAMU-IHALE.md.

Setup: register platforms under Account → LMS / LTI (Tbl_LtiPlatforms). Each platform row maps issuer, client_id, deployment_id to your institution account (credit pool owner).

Configure in LMS tool registration:

  • Login URL: https://panel.trustoriginality.ai/lti/login
  • Launch / redirect URL: https://panel.trustoriginality.ai/lti/launch
  • JWKS URL: https://panel.trustoriginality.ai/.well-known/jwks.json

Optional Lti:ToolBaseUrl in appsettings when the public URL differs from the request host.

Live monitoring (WebSocket + RTSP)

Route Auth Purpose
WS /ws/live-analyze Cookie session Real-time audio/video chunk analysis with EMA scores
POST /api/live/streams Cookie session Start RTSP/HTTP stream sampling (ffmpeg)
GET /api/live/streams Cookie session List active stream sessions
GET /api/live/streams/{id} Cookie session Stream status + recent samples
DELETE /api/live/streams/{id} Cookie session Stop stream session
GET /Live Panel session Demo UI (microphone + stream monitor)

WebSocket client messages: { "type": "audio"|"video", "dataBase64": "…" }, optional { "type": "config", "webhookUrl": "…" }, { "type": "end" }.

Stream start JSON body: { "url": "rtsp://…", "name": "…", "sampleIntervalSeconds": 5, "alertThreshold": 0.6, "webhookUrl": "…" }.

Configure Live:AlertWebhookUrl and ProvenanceWatch in appsettings (see deploy checklist).

EU AI Act machine-readable labels

Route Auth Output
GET /api/compliance/label/{activityId} Cookie or API key JSON-LD label for one analysis
GET /Compliance/ExportLabel?id={activityId} Panel session Download .jsonld
GET /Compliance/ExportLabels?from=&to= Panel session Bulk labels for audit period
GET /Compliance/ExportDsaTransparency?from=&to= Panel session DSA transparency JSON (moderation statistics)

Label format: trustoriginality-eu-ai-act-label/1.0 with verdict, AI likelihood score, IPTC digital source type hint, signed verify URL, and disclosure statement aligned with Art. 50 transparency documentation.

Error responses

Status Meaning
400 Invalid input (missing text/file, unsupported type, file too large)
401 Missing, invalid, or revoked API key
402 Subscription inactive or monthly credit limit reached
429 Rate limit exceeded (20 requests/minute per IP)
500 Analysis failed unexpectedly

Error body example:

{
  "error": "Monthly credit limit reached (50/50). Your credits reset at the start of next month, or you can upgrade your plan.",
  "creditsUsed": 50,
  "creditsLimit": 50,
  "plan": "Starter"
}