# UXXRAY for agents — pull real specimens, build original work, get it reviewed

You are probably here to DESIGN something. Do not start by reading scores. Start by looking at
what the library actually holds, take as much of it as you want, and build something original.

    see the shelf -> pull as many specimens as you want -> build original concepts
       -> open a review session -> hand your human the link -> read the verdict -> download the bundle

Everything below is MEASURED from live pages: deterministic extraction, every claim carrying the
on-page string that produced it, no LLM judgment anywhere in the data. **UXXRAY does not design.**
It hands you references with receipts and hosts the review; the original work is yours.

## 1 — See the whole shelf
`GET https://api.uxxray.com/api/v1/library/index`

Every facet, every legal value, real counts. No specimens — it is the map, and it is cheap.

**Read the counts before you ask for anything.** The inventory is LUMPY and pretending otherwise
is the one thing this product will not do: hero and faq run to the hundreds while stat_proof is
in single digits, and narrowing by `funnel_type` on top of that thins it further. If you ask for
20 and only 9 exist, the response says `showing 9 of 9 available` rather than let nine read as a
page of many. The index has the live numbers — never quote one from memory.

Two things can select specimens, and you pick ONE per request:

- `kind` — `section` (+ `archetype`), `page` (+ optional `template`), `element`
- `playbook` — funnels measurably running one named play

`funnel_type` is a filter and composes with either. Naming both axes returns 400 with the rule,
because applying one and dropping the other would hand you a set that looks like it honoured your
whole query.

## 2 — Take as much as you want
`GET https://api.uxxray.com/api/v1/library/specimens?kind=section&archetype=hero&scope=broad`

**YOU choose the breadth, and you can change it every round.** The tiers differ in how much of
each specimen you get, not only in how many:

| scope | returns | each specimen carries |
|---|---|---|
| `narrow` | 5 | everything — crop, score, and every tactic receipt with its VERBATIM on-page evidence |
| `broad` | 20 **(default)** | crop, score, and which tactics the funnel runs — pattern ids, no quotes |
| `full` | the whole roster | identity + score only. No crops, no receipts. The map of what exists |

Silence gets you 20. The corpus holds hundreds of hero bands — `scope=full` lists every one as a
roster so YOU pick, then re-request the ones you chose at `scope=narrow` for their receipts. That
is the intended loop: roster to survey, narrow to study.

Every specimen carries:

- `crop_url` — **a real cropped image of THIS band**, ~1440px wide and ~27KB, cut at build
  time from the page's own screenshot. **Fetch this, look at it.** It is `null` only when no
  crop exists, and `crop_unavailable_reason` then says which rule refused: a band too thin to
  frame honestly, or too tall to be a section. `full_url` is never substituted for it.
- `crop` — `y`/`h` as fractions of `full_url`, for a consumer that would rather window
  the whole page. `cut_h` is the height the image was actually cut at; where it differs from
  `h`, the band was thinner than the display floor and the picture includes what follows it.
- `receipts.patterns[]` — every tactic the funnel measurably runs, each with the VERBATIM
  on-page evidence, e.g. `"pricing: comparison table: FREE · TRAVELER · NOMAD"`.
  `receipts.scope` is `"funnel"`: the tactics describe the whole walked funnel, **not** this
  one band. Do not report them as properties of the section.
- `score` — a RANKING signal for references, not a grade. See "What the number is" below.

### One specimen per domain, by default
A ranked response returns at most ONE specimen per domain, so twenty results are twenty different
sites. Score is FUNNEL-scoped — every page of one walk shares it — so without the cap a four-page
funnel takes four consecutive slots; measured, 20 SaaS heroes out of 1,725 came from six domains.
`&per_domain=3` raises it, `&per_domain=all` lifts it for studying one funnel's whole set.
Bands the crop pipeline refuses are not ranked at all. Every reduction is stated in the response
and `availability.available` still reports the true population.

### Never get served the same specimen twice
`&exclude_seen_project=<your project>` with your `x-uxxray-visitor` header excludes every
specimen ANY of your sessions already used for that project. `exclude_seen_session=<id>` does the
same for one session and needs no token; `exclude_seen=<refs>` takes an explicit list.

**Use it on every round after the first.** A ranked pool returns its best matches in the same
order every time, so a second round without this asks the same question and gets the same answer.
That is not a hypothetical: a real worker built 15 concepts across three sessions from FIVE
distinct specimens because nothing told it there were more.

**LOOK at the crops.** You can read images. The screenshots are the ground truth the data was
measured from, and the composition is the part no JSON field carries.

### If you would rather be handed a shortlist
`GET https://api.uxxray.com/api/v1/library/resolve?task=build_review_section` maps design-task language to
corpus vocabulary, and `GET https://api.uxxray.com/api/v1/library/brief?task=…&top=3` returns a small curated
set with `selected_because` on each. Both still work and are a fine way to start — but they are a
**shortcut, not the product**. The library is bigger than any brief, and the brief cannot know
what you already used.

## 3 — Build original concepts
Structural and strategic reference only. Original layout, original copy, original visual style.
Do NOT copy source DOM, CSS, brand colours, logos, imagery or verbatim copy. The evidence strings
prove a tactic is real on that page — they are not text to reuse.

Aim for 3-4 genuinely different directions, not one idea in four skins.

## 4 — Open a Design Factory session
`POST https://api.uxxray.com/api/v1/factory/sessions`

The step-2 response hands you the body already filled in — see `next.create_session`; it pre-seeds
`source_specimens` with the refs of the specimens you were just served. That is what makes the
finished artifact traceable back to measured sources, **and it is what makes
`exclude_seen_project` work on your next round.** Register the refs you actually used, or the
library has no way to know what to stop showing you.

**`task` — KEEP IT UNDER 118 CHARACTERS.** It is the review page's headline, not a brief. The API
accepts 120 and will truncate silently at exactly 120, mid-word, which is how one real session
shipped a title ending `...and a real "why `. 118 is measured, not chosen, and it is RE-measured
whenever the h1 changes: `node scripts/measure-task-limit.mjs` sweeps lengths against the rule
that actually ships. It was 72 until 2026-08-07, when the task became a one-line disclosure at a
smaller type scale — the same string now costs a third of the height, so a tighter limit would be a
number derived from a page nobody serves. Put the detail in each concept's
`brief_md`, which has room for it and is rendered where a reader wants it.

  good: `Rebuild the /vpn/ hero: personalized, ONE provider, no sub-nav`   (61)
  bad:  `Rebuild the /vpn/ hero: personalized (quiz answer + device + region), ONE provider not two, no sub-nav, and a real "why it beats the rest"`   (137, truncated to 120)

**KEEP THE `session_token` THE RESPONSE GIVES YOU.** It is shown once and cannot be recovered —
only its hash is stored. It is what lets you register concepts. Two different things come back
and they are not interchangeable:

- `session_id` — read the session and leave feedback. **This is the review link. It is safe to
  hand a human**, and it is all they need.
- `session_token` — register concepts. **Yours only.** Send it as the
  `x-uxxray-session-token` header. Never put it in a URL — URLs leak through referrer headers,
  browser history and screenshots.

Sessions are **private by default**: reachable only by someone who already has the id, and in no
listing anywhere. Pass `"privacy": "public"` only if the human explicitly wants it listed.

Then register each concept:
`POST https://api.uxxray.com/api/v1/factory/sessions/{session_id}/concepts`
with header `x-uxxray-session-token: <your token>`
and body `{concept_id, title, brief_md, sources, artifact:{html, css, tokens}}`.

Without the header this returns **401** — that is the review link failing to authorise a write,
which is the point. `artifact` must carry non-empty `html` or `css`, or registration is
rejected: a concept nobody can look at is a failed registration, and you should hear about it
rather than the human discovering a blank card.

Keep artifacts portable and compact — a section, not a project bundle. Oversize payloads are
rejected rather than truncated.

## 5 — Hand your human the review link
The session response carries `review_url`:

    https://uxxray.com/factory/sessions/?id={session_id}

**Give it to them. This is the step agents skip.** They star, rate and comment on each concept in
a workspace that previews your artifacts in sandboxed iframes. You cannot judge your own design
work, and the whole point of the session is that a human does not have to read your code to react
to it.

## 6 — Read the verdict back
`GET https://api.uxxray.com/api/v1/factory/sessions/{session_id}/feedback`

Returns per-concept stars, ratings, comments and a summary naming what was starred. Refine the
winner from the actual comment; do not restart from scratch.

**Register the refinement with `parent_concept_id` set to the concept you refined.** That link is
the only thing that makes the workspace read as a design history instead of a growing pile: it
puts the new version on the SAME card, behind a version toggle, instead of adding a fourth tile.
Omit the parent only when you mean a genuinely new direction.

You never send a version NUMBER — 1.0 / 1.1 / 1.2 is derived from that link, so it cannot drift.
You may send an optional `version_label` (max 40 chars) NAMING the version — "tighter proof",
"warm paper". It is printed on the toggle and the derived number stays beside it.

## 7 — Download it into their project
`GET https://api.uxxray.com/api/v1/factory/sessions/{session_id}/concepts/{concept_id}/artifact`

Stack-neutral bundle: `index.html`, `style.css`, `tokens.json`, `sources.json`, `brief.md`.
`sources.json` preserves the provenance chain — which measured specimens informed it.

You are almost certainly working in the USER'S repo, not UXXRAY's, so just fetch that endpoint
and write the files yourself — it needs no tooling and no auth. Suggested location:
`.uxxray/factory/<session_id>/<concept_id>/` (add `.uxxray/` to their .gitignore; these are
re-pullable working copies, never source of truth).

A convenience adapter exists for anyone who has the UXXRAY repo checked out
(`npm run factory:pull -- <session_id> --concept starred`), but there is no published CLI —
do not tell a user to run `npx uxxray`.

## Going deeper than one section
When the task is a whole funnel rather than one band:

- `GET https://api.uxxray.com/api/v1/playbooks` — the named plays and which funnels measurably run each.
- `GET https://api.uxxray.com/api/v1/templates` — recurring section-skeletons real pages are built from.
- `GET https://api.uxxray.com/api/v1/patterns` (+ `/{pattern_id}`) — each tactic with up to 60 verbatim examples.
- `GET https://api.uxxray.com/api/v1/sections` — archetype prevalence and where each band typically sits.

Read one strong funnel end to end when you need the whole composition:
- ainexfinder.com (affiliate): `GET https://api.uxxray.com/api/v1/teardown/ainexfinder/bundle`
- comparitech.com (affiliate): `GET https://api.uxxray.com/api/v1/teardown/comparitech/bundle`
- safewise.com (affiliate): `GET https://api.uxxray.com/api/v1/teardown/safewise/bundle`
- amabrik.com (saas): `GET https://api.uxxray.com/api/v1/teardown/amabrik/bundle`
- anakin.io (saas): `GET https://api.uxxray.com/api/v1/teardown/anakin-io/bundle`
- doppio.sh (saas): `GET https://api.uxxray.com/api/v1/teardown/doppio-sh/bundle`

## What the number is, and is not
The /100 is **detected conversion-tactic coverage**, funnel-type-aware. It is not a quality
grade, not a UX score, and not taste. Its job here is to RANK references so the library can put
something useful first — **the crop is the product, the score is the sort order.** A well-built
unconventional funnel can register low. Never tell a user their site is "bad" because of it.

## Rules that keep you honest
- Every claim carries evidence. If a signal is absent it was NOT measured — never guess it onto a site.
- Prevalence is scoped to the crawled corpus (SaaS-heavy today), never "the web".
- Playbook matches are SURFACE matches; ads and emails are unobservable from a crawl.
- Specimens are references. Shipping a copy of someone's section is not what this is for.

## ★ Rate this
How useful was this? 1 = poor, 5 = excellent. Pass the question to your user if one is present
(via:"user"), else answer yourself (via:"agent"):
`POST https://api.uxxray.com/api/v1/rate {"rating": 1-5, "context": "curriculum", "via": "agent", "comment": "optional"}`
