---
title: "Verify — what viewers see and what broke"
method: POST
path: "/v1/artifacts/{id}/verify"
tags: ["Artifacts"]
---

# Verify — what viewers see and what broke

`POST /v1/artifacts/{id}/verify`

## Request

- Base URL: `https://shareout.site`
- URL: `https://shareout.site/v1/artifacts/{id}/verify`
- Auth: HTTP bearer

Opens the page the way its viewers get it — on its content origin, in a fresh browser with no ShareOut session, with the viewer sandbox emulated (storage, cookies and IndexedDB throw `SecurityError`) and the viewer's Content-Security-Policy enforced — on a 1280×800 desktop and a 390×844 phone, and reports script errors (with file:line:col), failed requests (with the `code`/`hint` of ShareOut API errors), blocked CDNs, accessibility (axe-core, WCAG 2.1 A/AA), horizontal overflow, tap targets under 44 px, broken images, blank screens, design lint, LCP/CLS/bytes and common source mistakes. Writes the page makes on load are refused (read-only render). The phone view renders the version's mobile entrypoint when it has one, and a pinned `version` is rendered entirely from that version's files. Verifying the live version also refreshes the thumbnail. Owners and editors only; workspace Agent tokens need `artifacts:publish`. Limited per user per hour (30 unless the instance sets `VERIFY_RUNS_PER_HOUR`). Without a Browser Rendering binding the result is `partial` (source checks only). Typical run: 5–15 s.

## Request body

- VerifyRequest
  - `version` integer: Version number to verify, with all of its files. Defaults to the live version.
  - `viewports` string[]: Defaults to both.
  - `full_page` boolean: Screenshot the whole page height (up to 4000 px) instead of the first screen.

## Response `200`

The verify run (also stored as the latest)

- VerifyResult
  - `id` string: Run id (`vfy_…`).
  - `artifact_id` string
  - `version` integer
  - `version_id` string
  - `live` boolean: Whether the verified version is the one viewers get now.
  - `status` 'pass' | 'warn' | 'fail' | 'partial': `fail` = at least one error, `warn` = warnings only, `pass` = neither, `partial` = the page was not rendered (see `partial_reason`) and only the source was checked.
  - `partial_reason` 'no_browser' | 'render_failed'
  - `summary` string
  - `counts` object
    - `error` integer
    - `warning` integer
    - `info` integer
  - `issues` VerifyIssue[]: Errors first, then warnings, then notes (at most 60).
    - `check` 'render' | 'console' | 'network' | 'a11y' | 'layout' | 'design' | 'performance' | 'source', required
    - `rule` string, required: Stable id, e.g. `js_error`, `storage_blocked`, `request_failed`, `api_error`, `csp_blocked`, `horizontal_overflow`, `small_tap_targets`, `broken_image`, `blank_page`, `absolute_path`, or an axe-core rule id such as `image-alt`.
    - `severity` 'error' | 'warning' | 'info', required
    - `message` string, required
    - `where` string: `file:line:col`, a CSS selector, or a URL.
    - `hint` string: How to fix it.
    - `viewports` string[]
    - `count` integer
  - `viewports` object[]
    - `viewport` 'desktop' | 'mobile'
    - `entrypoint` string: The file this view rendered (the phone renders the mobile entrypoint when there is one).
    - `width` integer
    - `height` integer
    - `dpr` number
    - `screenshot` object, nullable
      - `url` string
      - `path` string
      - `width` integer
      - `height` integer
      - `full_page` boolean
    - `metrics` object, nullable
      - `load_ms` integer
      - `lcp_ms` integer, nullable
      - `cls` number, nullable
      - `bytes` integer, nullable
      - `requests` integer
  - `design` object, nullable: Fonts, accent colors, longest line and missing meta tags, from the first viewport.
  - `thumbnail_refreshed` boolean
  - `duration_ms` integer
  - `created_at` string, date-time

## Other responses

- `400`: Invalid request
- `401`: Authentication required
- `403`: Access denied
- `404`: Resource not found
- `409`: Nothing to render — not published yet (`NOT_PUBLISHED`), paused or taken down
- `429`: Rate limit reached (`RATE_LIMIT_EXCEEDED` on publish / account creation / AI routes, `RATE_LIMITED` on the data plane). Wait for `Retry-After` / `reset`.

## Changes

- **2026-10-26** `f598440d6780`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/shareout/apis/shareout-rest-api/changes/v1/artifacts/:id/verify/post.md)

---

[API](https://skmtc.dev/shareout/apis/shareout-rest-api.md) - [All operations](https://skmtc.dev/shareout/apis/shareout-rest-api/llms.txt) - [OpenAPI document](https://skmtc.dev/shareout/apis/shareout-rest-api/revisions/1e3f7fd34f6d?raw)
