Skip to content
Vraelis/Docs
Ways to run/The API
Sign inCreate account
Overview
Getting started with VraelisVerify, approve, run, re-checkWhat you can check
Connect an AI assistantThe command lineThe APIGate a release in CIWebhooks
Approving a planRun activityCompletionFindingsRepairRe-checks
SystemsGuaranteesMemory
← Back to vraelis.comDevelopersChangelogContact support

Ways to run

The API

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 https://vraelis.com.

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

Submit the claim

Request

# 1. Submit the claim. Vraelis writes a plan and asks a person to approve it before anything runs.
curl -X POST https://vraelis.com/api/v1/verifications \
  -H "x-api-key: $VRAELIS_API_KEY" \
  -H "content-type: application/json" \
  -H "idempotency-key: $(uuidgen)" \
  -d '{
    "deployment_url": "https://staging.example.com",
    "claim": "A customer can upgrade to Pro and still have access after signing in again."
  }'

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.

Response

{
  "state": "review_required",
  "review_required": true,
  "claim": "A customer can upgrade to Pro and still have access after signing in again.",
  "requirements": [
    "Upgrading to Pro grants Pro access immediately",
    "Pro access is still present after signing out and back in"
  ],
  "reviewed_plan_id": "rvp_3c9e26ef",
  "reviewed_plan_expires_at": "2026-09-28T19:04:11.000Z",
  "approve_url": "https://app.vraelis.com/review/rvp_3c9e26ef",
  "human_reviewed": false,
  "message": "Vraelis built a plan that can prove this claim, and no person has reviewed it yet. A person approves it at approve_url; then resubmit with reviewed_plan_id to run exactly what was approved. Nothing was run and nothing was charged."
}

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.

Approve, read the plan, then run it

# 2. A person opens approve_url and approves the plan with one click. A key cannot:
curl -X POST https://vraelis.com/api/v1/verifications/plans/rvp_3c9e26ef/approve \
  -H "x-api-key: $VRAELIS_API_KEY"
#    -> 403 { "error": { "code": "plan_requires_human", ... },
#             "approve_url": "https://app.vraelis.com/review/rvp_3c9e26ef" }

# While you wait for the person, read the plan. approve_url is present while it is pending.
curl https://vraelis.com/api/v1/verifications/plans/rvp_3c9e26ef \
  -H "x-api-key: $VRAELIS_API_KEY"
#    -> { "reviewed_plan_id": "rvp_3c9e26ef", "approval_state": "pending",
#         "approve_url": "https://app.vraelis.com/review/rvp_3c9e26ef", ... }

# 3. Once approval_state reads "approved", resubmit the SAME deployment and claim with the plan id.
#    This is the call that starts a run, and the first response that carries a verification_id.
curl -X POST https://vraelis.com/api/v1/verifications \
  -H "x-api-key: $VRAELIS_API_KEY" \
  -H "content-type: application/json" \
  -d '{ "deployment_url": "https://staging.example.com",
        "claim": "A customer can upgrade to Pro and still have access after signing in again.",
        "reviewed_plan_id": "rvp_3c9e26ef" }'
#    -> { "verification_id": "vrf_9c1e0f2a41", "state": "running",
#         "status_url": "/v1/verifications/vrf_9c1e0f2a41", "human_reviewed": true }

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.

Request

# 4. Poll until a decision lands. While the run is going, there is no decision yet.
curl https://vraelis.com/api/v1/verifications/vrf_9c1e0f2a41 \
  -H "x-api-key: $VRAELIS_API_KEY"

Response

{
  "verification_id": "vrf_9c1e0f2a41",
  "state": "completed",
  "decision": "failed",
  "claim": "A customer can upgrade to Pro and still have access after signing in again.",
  "requirements": [
    "Upgrading to Pro grants Pro access immediately",
    "Pro access is still present after signing out and back in"
  ],
  "failures": [
    {
      "severity": "critical",
      "title": "Pro access is lost after signing back in",
      "expected": "The account still shows Pro after re-authenticating",
      "observed": "The account reverted to the Free plan",
      "reproduce": ["Upgrade to Pro", "Sign out", "Sign back in", "Open billing"]
    }
  ],
  "evidence": [
    { "checking": "Upgrade to Pro", "result": "passed", "failed_at_step": null },
    { "checking": "Access persists after re-auth", "result": "failed", "failed_at_step": 3 }
  ],
  "repair_prompt": "Pro entitlement is not re-read on session restore. On sign-in, load the subscription from the source of truth before rendering plan state, and confirm Pro survives a full sign-out and sign-in.",
  "console_url": "https://app.vraelis.com/systems/app_5b7d/passes/9c1e0f2a41",
  "reviewed_plan_id": "rvp_3c9e26ef",
  "recheck_of": null,
  "human_reviewed": true
}

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.

Request

# 5. Deploy the fix, then run the same approved plan again. No new approval inside the window.
curl -X POST https://vraelis.com/api/v1/verifications/vrf_9c1e0f2a41/recheck \
  -H "x-api-key: $VRAELIS_API_KEY"

Response

{
  "verification_id": "vrf_4be27d9c10",
  "state": "running",
  "status_url": "/v1/verifications/vrf_4be27d9c10",
  "recheck_of": "vrf_9c1e0f2a41",
  "human_reviewed": true,
  "reviewed_plan_id": "rvp_3c9e26ef",
  "rechecks_left": 9,
  "recheck_window_ends_at": "2026-09-29T18:04:11.000Z"
}

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.

Request

# Ask "is this claim provable against this build?" before spending anything.
curl -X POST https://vraelis.com/api/v1/verifications \
  -H "x-api-key: $VRAELIS_API_KEY" \
  -H "content-type: application/json" \
  -d '{ "deployment_url": "https://staging.example.com",
        "claim": "A customer can upgrade to Pro and keep access after signing in again.",
        "dry_run": true }'

Response

{
  "dry_run": true,
  "would_launch": true,
  "requirements": ["Upgrading to Pro grants Pro access immediately", "..."],
  "reviewed_plan_id": "rvp_3c9e26ef",
  "reviewed_plan_expires_at": "2026-09-28T19:04:11.000Z",
  "approval_required": true,
  "approve_url": "https://app.vraelis.com/review/rvp_3c9e26ef",
  "human_reviewed": false
}

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.

The same key with a different claim

{
  "error": {
    "code": "idempotency_key_reused",
    "message": "That idempotency key was already used for a different verification. Use a new key, or resend the original request exactly.",
    "request_id": "req_5f3a90"
  }
}

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 (vraelis mcp) and hosted (https://vraelis.com/mcp)
  • Signed verification.completed webhooks, and Slack delivery
SDKA 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.

Related

  • The command line →
  • Gate a release in CI →
  • Webhooks →
← PreviousThe command lineNext →Gate a release in CI
© 2026 Vraelisvraelis.comSecurityPrivacyCookiesTermsAcceptable use

On this page

AuthenticateSubmit the claimApprove, then start the runRead the decisionRe-check after a fixAsk before you commitRequirementsIdempotencyErrorsWhat has shipped
CopiedCopy failed