# The API

> **Historical. This product is retired.** This page describes the earlier browser-testing product and is kept only as history. Its service, API, console and accounts are closed: do not run the install commands or call the endpoints shown here.

Submit a claim, have a person approve the plan, start the run, read the decision and re-check after a fix, over HTTP.

- **Outcome:** You can start a check from your own code and read the decision with its evidence.
- **Does not do:** An API key cannot approve a plan: every key gets 403 plan_requires_human and the link a person opens.

Authenticate with an API key, POST a deployment and a claim, send the `approve_url` to a person, resubmit with the approved plan id to start the run, then poll until a decision lands. After a fix, re-check the same plan. Base URL is (retired endpoint).

## Authenticate

Every request carries your key in the `x-api-key` header. Keys are created in the app, shown once, and stored only as a hash. Launching or re-checking needs a key with launch access, because it spends. [Create an API key]((retired endpoint))

## Submit the claim

> **Removed.** This example called the earlier service, which is retired. Its commands and endpoints are no longer shown.

Returns `202` with `state: "review_required"`, the derived requirements, the plan to approve, and the `approve_url` a person opens. No run started, nothing charged, and no verification id yet. The response also carries `contract_id` and `contract_version`.

> **Removed.** This example called the earlier service, which is retired. Its commands and endpoints are no longer shown.

## Approve, then start the run

Only a signed-in person approves a plan, with one click at the `approve_url`. The approval is its own recorded event: who approved which plan, and when. Every API key is refused with `403 plan_requires_human` and the same link, so the tool that asked for the check can never sign off on it. The run then executes exactly the approved plan, with no re-derivation.

> **Removed.** This example called the earlier service, which is retired. Its commands and endpoints are no longer shown.

## Read the decision

Poll `GET /v1/verifications/{id}`. While running, the body is just the id and state. Once complete, `decision` is one of `verified`, `failed`, or `blocked`. `recheck_of` names the verification a re-check repeated, or is null.

> **Removed.** This example called the earlier service, which is retired. Its commands and endpoints are no longer shown.

> **Removed.** This example called the earlier service, which is retired. Its commands and endpoints are no longer shown.

## Re-check after a fix

After a Failed, deploy the fix and call `POST /v1/verifications/{id}/recheck`. It runs every journey of the same approved plan again and returns a new verification id; the earlier record is never touched. No new approval is needed within 24 hours of the approval, for at most 10 re-checks, on the same scheme and host. An optional `deployment_url` may name another path on that same site. Past those limits the API answers `recheck_window_closed` or `recheck_limit_reached`, and you start a new verification. Each re-check is billed as one verification.

> **Removed.** This example called the earlier service, which is retired. Its commands and endpoints are no longer shown.

> **Removed.** This example called the earlier service, which is retired. Its commands and endpoints are no longer shown.

## Ask before you commit

A dry run derives the plan, checks it can actually prove the claim, and charges nothing. When it can, it mints the same plan a person approves in step 2 above, with its `approve_url`. When it cannot, it says so with a repair prompt, and there is nothing to approve.

> **Removed.** This example called the earlier service, which is retired. Its commands and endpoints are no longer shown.

> **Removed.** This example called the earlier service, which is retired. Its commands and endpoints are no longer shown.

## Requirements

Every response echoes the requirements Vraelis derived from your claim, and states whether a person approved them in `human_reviewed`. A model reading a claim can misread it; the requirements are what the person is approving, and they are how you catch a confidently wrong verdict before you trust it.

## Idempotency

Send an `idempotency-key` header. A retry with the same key, deployment, and claim replays the original verification instead of starting and paying for a second one. The same key with a different claim is refused, so a changed request can never be answered with an earlier run.

> **Removed.** This example called the earlier service, which is retired. Its commands and endpoints are no longer shown.

## Errors

Errors share one envelope: `{ error: { code, message, request_id } }`, with the id also on the `X-Request-Id` header. A claim that cannot be proven returns `claim_not_provable` (422) with a repair prompt, and nothing is charged.

## What has shipped

We will not document an endpoint we have not shipped. These are the ones that answer today.

- `POST /api/v1/verifications`, create, dry-run, or run an approved plan
- `GET /api/v1/verifications/plans/{id}`, the plan, its approval state, and `approve_url` while it is pending
- `GET /api/v1/verifications/{id}`, decision, evidence, repair prompt, `recheck_of`
- `POST /api/v1/verifications/{id}/recheck`, the same approved plan after a fix
- `POST /api/v1/verifications/plans/{id}/approve`, for a signed-in person only; every API key gets `403 plan_requires_human`
- The vraelis CLI: `verify`, `recheck`, `result`, `init`, `mcp`
- The MCP server, local ((retired command)) and hosted (`(retired endpoint)`)
- Signed `verification.completed` webhooks, and Slack delivery

> **SDK.** A TypeScript SDK, @vraelis/sdk 0.3.0, wraps these calls as prepare, getPlan, waitForApproval, run, waitForResult, recheck and get. It is built and tested in the repository and is not yet published to npm, so it cannot be installed today.

---

Vraelis documentation, Earlier references. https://docs.vraelis.com/api
