---
title: "Get analyse results as clean JSON"
method: GET
path: "/api/analyse/result/{jobUid}"
tags: ["Analyse"]
---

# Get analyse results as clean JSON

`GET /api/analyse/result/{jobUid}`

## Request

- Base URL: `https://snapwonders.com`
- URL: `https://snapwonders.com/api/analyse/result/{jobUid}`
- Auth: API key in header `X-Api-Key`

Returns analysis results as clean JSON — file names, grades, and detection counts only. No internal fields, no HTML. Useful when you want to fetch or share results without parsing the full job response. The `job_uid` is returned by `POST /api/analyse/job` and `GET /api/analyse/job/{uid}/results`. **Authentication:** `X-Api-Key` header required. The API key must match the key used to create the session.

## Path parameters

- `jobUid` string, uuid, required

## Response `200`

Clean JSON result

- object
  - `files` object[]: One entry per analysed file.
    - `name` string: Original filename
    - `grade` 'A' | 'B' | 'C' | 'D' | 'F', nullable: AUTHENTICITY grade (since 2026-09-27): the weakest of the Origin, Manipulation and AI-generation grades, softened one step at medium confidence and two at low, but never to `A` over a finding. It answers "was this edited, generated or re-encoded?" - privacy findings (GPS, faces, text) are in `exposure_grade`, never mixed in. Rows graded before 2026-09-27 hold the earlier all-category overall. `A` = no significant finding: no real-weight check fired (trace-weight checks may still be listed). Since 2026-09-30 (regime gse-v9) any finding, at any confidence, holds the grade at `B` or worse. Read the per-check findings to see what drove it.
    - `exposure_grade` 'A' | 'B' | 'C' | 'D' | 'F', nullable: EXPOSURE grade (since 2026-09-27): the weakest of the Privacy and Security grades, softened by confidence the same way and likewise never to `A` over a finding - what the file gives away (location, identity, hidden data). A face or text found always means `B` or worse. Never combined with overall_grade. `null` on rows graded before the change, or when withheld.
    - `exposure_confidence` 'low' | 'medium' | 'high', nullable: Confidence of the category that decided exposure_grade. Ordinal, never a percentage.
    - `confidence` 'low' | 'medium' | 'high', nullable: How much to lean on the grade: the confidence of the category that decided it - how reliable the checks that fired are, how many applicable checks actually ran, and whether any disagreed. `null` means nothing could be assessed - which is NOT the same as low confidence. Ordinal by design, never a percentage: a number would claim a calibration that does not exist.
    - `face_count` integer, nullable: Number of faces detected.
    - `text_region_count` integer, nullable: Number of text regions detected.
    - `watermark_flagged` boolean, nullable: `true` if the blind watermark bit-decode fired (NOT a match against a known payload — see the `steganography` verdict for the honest framing).
    - `verdicts` object: Curated, user-safe forensic verdicts — mirrors exactly what the public web report shows for this file, never internal scores/thresholds/pipeline detail. Every key is present only when the underlying check produced a result; absent otherwise (except `steganography`, always present — see its description).
      - `ai_generation` object: AI-generation verdict, as the web report shows it.
        - `verdict` 'likely_authentic' | 'likely_real' | 'real_edited' | 'no_evidence' | 'inconclusive' | 'ai_edited' | 'ai_processed' | 'possible_aigc' | 'declared_ai': The report's AI-generation card. `likely_authentic` only when signed Content Credentials from a trusted issuer record a camera capture that is untouched since capture, and no AI evidence was found; `likely_real` when measured camera-origin signals point to a real capture and no AI evidence was found (not issued yet); `real_edited` when the signed Content Credentials history shows a real camera capture later edited without AI tools, every step signed by a trusted signer; `no_evidence` when nothing points either way (this is not a finding that the file is real); `inconclusive` when the pixel estimate is inconclusive, or the pixel analysis found signs of AI generation that are not enough on their own, or the Content Credentials record a camera capture whose history cannot be confirmed; `ai_edited` when the signed Content Credentials history shows a real camera capture later edited with AI tools (D, or F when the later step declares fully AI-generated output); `ai_processed` when a known image-generator watermark was found — it may be a generated image or a real photo edited with an AI tool; `possible_aigc` when the pixel estimate suggests AI generation; `declared_ai` when Content Credentials or the file's own metadata declare AI generation or editing. Omitted only when no AI-generation check produced a result and nothing proves a capture.
        - `pixel_analysis` 'flagged' | 'clear' | 'not_assessable': Pixel analysis result: `flagged` (signs of AI generation found), `clear` (none found — not proof of authenticity: this check can miss images from newer AI tools) or `not_assessable` (not yet calibrated for this file type or size). Absent when it did not run.
      - `c2pa` object: Content Credentials (C2PA) status.
        - `verdict` string
        - `applicable` boolean
        - `has_manifest` boolean
        - `trusted` boolean
      - `camera_fingerprint` object: JPEG quantisation-table (DQT) device match — the match only, never the underlying signature/hash.
        - `applicable` boolean
        - `matched` boolean
        - `encoder_name` string, nullable
        - `encoder_family` string, nullable
        - `quality_level` integer, nullable
      - `findings` object[]: Key forensic findings. `actual_value`/`expected_value` are deliberately not exposed here.
        - `label` string
        - `severity` string
      - `steganography` object: Hidden-content / invisible-watermark result. ALWAYS present, deliberately: "checked, found nothing" (`checks_run` non-empty, `verdict: none`) and "never checked" (`checks_run: []`, `verdict: not_analysed`) are different facts — collapsing them into a boolean would tell a caller a file is clean when nobody actually checked.
        - `verdict` 'not_analysed' | 'none' | 'anomalies' | 'watermark_pattern_unconfirmed' | 'generator_watermark_matched'
        - `checks_run` string[]
        - `conclusive` boolean: True only for `generator_watermark_matched` — a match against a published watermark payload. Every other verdict is a probabilistic read, not a conclusive one.
      - `forensic` object: ELA / noise-inconsistency summary — tile COUNTS only, never the tile coordinates or raw pixel data.
        - `ela` object
          - `high_fraction` number, float: Fraction of the image at high ELA residual.
          - `anomaly_tile_count` integer
        - `noise_inconsistency` object
          - `anomaly_tile_count` integer
      - `audio_splice` object: Video only. Background-noise-consistency / discontinuity check. `verdict` is the DERIVED value shown on the web report — always matches it, never the raw stored field.
        - `applicable` boolean
        - `verdict` 'clean' | 'possible' | 'suspect'
        - `spike_count` integer
        - `noise_cov` number, float
        - `duration_s` number, float
        - `spike_positions` object[]
          - `time_s` number, float
      - `video_tamper` object: Video only. Four independent frame/GPS tamper checks, grouped by finding.
        - `inter_frame_tamper` object: Abrupt frame-to-frame differences — consistent with cuts, splices, or frame insertions.
          - `verdict` 'clean' | 'suspect' | 'not_applicable'
          - `spike_count` integer
          - `frame_count_checked` integer
        - `frame_duplicate` object: Near-identical consecutive frames — consistent with frame insertion or dropped-frame cover-up.
          - `dup_verdict` 'clean' | 'suspect' | 'not_applicable'
          - `dup_count` integer
        - `pframe_fft` object: Periodic P-frame bitrate signal — double-compression / re-encode indicator.
          - `applicable` boolean
          - `verdict` 'good' | 'warn' | 'bad'
          - `peak_period_frames` integer
        - `gps_triangle` object: GPS coordinates vs the two independent clocks stamped into the file (satellite UTC, camera local time). A mismatch means the location and the file's two clocks did not close — see the "GPS timezone triangle" writeup on kennethbspringer.au for the full mechanism.
          - `applicable` boolean
          - `verdict` 'ok' | 'warn' | 'bad' | 'skip'
          - `delta_secs` integer, nullable
          - `timezone` string, nullable
    - `assets` object[]: Analysis image maps generated for this file (face overlays, ELA maps, text maps, etc.). Empty while job is processing.
      - `asset_id` string, uuid: Pass to `GET /api/analyse/asset/{assetId}` with the same `X-Api-Key` to download the image.
      - `category` 'face_map' | 'text_map' | 'forensic_ela' | 'forensic_clone' | 'exif_thumbnail' | 'forensic_nss_chart': Type of analysis map
      - `mime_type` string
      - `file_size` integer: File size in bytes
      - `download_path` string: Relative path — authenticated fetch, same `X-Api-Key`. Relative because the API serves clearnet/Tor/I2P; an absolute URL would be wrong for darknet clients.

## Other responses

- `401`: Not authenticated. `error` names the exact cause: `missing_api_key`, `malformed_api_key`, `invalid_api_key` (key unknown/revoked/expired), or — when the key itself is valid — `account_not_verified` / `account_inactive`.
- `403`: This result does not belong to a session owned by your API key
- `404`: Result not found
- `410`: Result has expired

---

[API](https://skmtc.dev/snapwonders/apis/snapwonders-api-mcp.md) · [All operations](https://skmtc.dev/snapwonders/apis/snapwonders-api-mcp/llms.txt) · [OpenAPI document](https://skmtc.dev/snapwonders/apis/snapwonders-api-mcp/revisions/645bbccc9550?raw)
