Skip to content
Vraelis
Sign inOpen Vraelis

Developers

Invoke the verification engine from your own systems.

Send a deployment and a claim, get back an explainable decision with evidence. One call to start, one to read the result, and one exit code to gate a release on. Every shape below is copied from the shipped API.

Create an API key→Read the API→

One capability, exposed

Verification is one capability inside broader oversight.

Vraelis follows agent work from assigned responsibility to trusted completion. This API drives the part that is live and self-serve today: when something claims to be done, Vraelis proves the running software against the claim. The responsibility, memory, and agent-oversight APIs are direction, and are not documented here until they ship.

The API

Create a verification, read the decision.

Two calls. Authenticate with an API key, POST a deployment and a claim, then poll the status URL until a decision lands. Base URL is https://vraelis.com.

AuthEvery 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 a verification needs a key with launch access, because it spends.

bash
# Create a verification: send the deployment and the claim.
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 the id, the derived requirements, and human_reviewed: false.

json
{
  "verification_id": "vrf_9c1e0f2a41",
  "state": "running",
  "status_url": "/v1/verifications/vrf_9c1e0f2a41",
  "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"
  ],
  "human_reviewed": false
}

ReadPoll GET /v1/verifications/{id}. While running, the body is just the id and state. Once complete, decision is one of verified, failed, or blocked.

bash
# 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"
json
{
  "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.",
  "human_reviewed": false
}

RequirementsEvery response echoes the requirements Vraelis derived from your claim, and states human_reviewed: false plainly. A model reading a claim can misread it; the requirements are how you catch a confidently wrong verdict before you trust it.

IdempotencySend 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.

json
{
  "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 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.

Review before you spend

Put a human decision before a paid run.

A dry run synthesizes the plan, checks it can prove the claim, and charges nothing. When it can, it mints a reviewed plan you approve as a separate audited event. The paid run then executes exactly what was approved, and comes back marked human_reviewed.

bash
# 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 }'
json
{
  "dry_run": true,
  "would_launch": true,
  "requirements": ["Upgrading to Pro grants Pro access immediately", "..."],
  "reviewed_plan_id": "rvp_3c9e26ef",
  "reviewed_plan_expires_at": "2026-07-24T19:04:11.000Z",
  "approval_required": true,
  "human_reviewed": false
}
bash
# 1. Approve the reviewed plan. A separate, audited event: holding the id is not approval.
curl -X POST https://vraelis.com/api/v1/verifications/plans/rvp_3c9e26ef/approve \
  -H "x-api-key: $VRAELIS_API_KEY"
#    -> { "reviewed_plan_id": "rvp_3c9e26ef", "approval_state": "approved", "already_approved": false }

# 2. Run exactly what was reviewed. The paid run consumes the approved plan verbatim.
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.",
        "reviewed_plan_id": "rvp_3c9e26ef" }'
#    -> the response carries "human_reviewed": true

CLI

One command. The exit code is the interface.

The vraelis CLI wraps the same endpoint for people and pipelines. In CI it is read by an if-statement far more often than by a person, so the exit code carries the verdict and everything else is decoration.

bash
# One command. The exit code is the interface.
export VRAELIS_API_KEY="<your key>"   # created at app.vraelis.com/api with "Launch runs" access

vraelis verify \
  --url https://staging.example.com \
  --claim "A customer can upgrade to Pro and keep access after signing in again" \
  --wait

# 0 verified   1 failed   2 blocked or could not run
# --repair-prompt prints only the fix package, ready to paste into a coding agent
  • 0Verified. The claim held, with evidence.
  • 1Failed. The claim did not hold; a repair prompt is attached.
  • 2Blocked, or the tool could not run at all.

The CLI collapses “blocked” and “could not run” into 2, because a gate should treat “I could not check” the same as “no verdict.” A hand-rolled gate that polls the API can split those out, exiting 3 when no decision is reached in the window.

js
// gate.mjs: ship only on "verified". The exit code gates the deploy.
// 0 verified   1 failed   2 blocked   3 no decision reached
import { randomUUID } from "node:crypto";

const API = "https://vraelis.com/api/v1/verifications";
const headers = {
  "content-type": "application/json",
  "x-api-key": process.env.VRAELIS_API_KEY,
  "idempotency-key": randomUUID(),
};

const created = await fetch(API, {
  method: "POST",
  headers,
  body: JSON.stringify({ deployment_url: process.env.PREVIEW_URL, claim: process.env.VRAELIS_CLAIM }),
});
const { verification_id } = await created.json();

// While running, decision is absent; keep polling until it lands.
let decision = null, out;
for (let i = 0; i < 120 && decision === null; i++) {
  await new Promise((r) => setTimeout(r, 5000));
  out = await (await fetch(API + "/" + verification_id, { headers })).json();
  decision = out.decision ?? null;
}

// Gate on the decision, never the run state. A finished run is not a pass.
switch (decision) {
  case "verified": process.exit(0);
  case "failed":   process.exit(1);
  case "blocked":  process.exit(2);
  default:         process.exit(3); // no decision within the polling window
}

Webhooks

Get the decision pushed to you.

Connect an endpoint and Vraelis POSTs a signed verification.completed event the moment a verification finalizes. It carries only owner-safe facts: the decision, flow counts, ids, and a link to the evidence. Never a session id, token, credential, or signed artifact URL.

EventOne event, verification.completed, delivered with the headers x-vraelis-event, x-vraelis-timestamp, and x-vraelis-signature.

json
{
  "event": "verification.completed",
  "run_id": "9c1e0f2a41",
  "application_id": "app_5b7d",
  "decision": "failed",
  "flows_total": 4,
  "flows_passed": 3,
  "deployment_url": "https://staging.example.com",
  "completed_at": "2026-07-24T18:04:11.220Z",
  "report_url": "https://app.vraelis.com/systems/app_5b7d/passes/9c1e0f2a41"
}

VerifyThe signature is an HMAC over the raw body prefixed with the timestamp, so recompute over the exact bytes you received before trusting the payload.

js
// Verify the delivery: HMAC-SHA256 over `${timestamp}.${rawBody}`.
import { createHmac, timingSafeEqual } from "node:crypto";

const timestamp = req.headers["x-vraelis-timestamp"];
const signature = req.headers["x-vraelis-signature"];   // "sha256=<hex>"
const expected = "sha256=" + createHmac("sha256", process.env.VRAELIS_SECRET_KEY)
  .update(`${timestamp}.${rawBody}`)
  .digest("hex");

const ok = Boolean(signature) && timingSafeEqual(Buffer.from(signature), Buffer.from(expected));

Point the same endpoint at a Slack incoming webhook and the event arrives as a formatted message in your channel instead of raw JSON, with the decision, flows passed, and a link to the evidence.

Integrations

GitHub, Vercel, and Slack, from the same primitives.

Run the CLI in GitHub Actions to gate a deploy, point a verification at a Vercel preview or production URL, and route the result into Slack. Each one is the API, the CLI, or a webhook wired to a place you already work, not a separate product.

See all integrations→

Honest about what is live

We will not document an endpoint we have not shipped.

Live today

  • POST /api/v1/verifications, create, dry-run, or run a reviewed plan
  • GET /api/v1/verifications/{id}, decision, evidence, repair prompt
  • Reviewed-plan approval before a paid run
  • The vraelis verify CLI and its CI exit codes
  • Signed verification.completed webhooks
  • GitHub Actions, Vercel deployment URLs, Slack

Direction

  • Responsibility and assignment APIs
  • Agent memory and reliability APIs
  • Continuous agent-activity ingestion
  • IDE, desktop, and MCP surfaces

These are where oversight is going. When one ships, it appears here with a real example you can run.


Wire the decision into the place you ship from.

Start a verification from CI, gate on the exit code, and get the evidence pushed back. One key, real endpoints, no dashboard to watch.

Create an API key→See integrations

Product

PlatformWhat it can reachWhat is builtAgentsIntegrationsPricingEnterprise

Developers

DocumentationAPICLIWebhooks

Company

Who it is forHow this is differentResearchMethodIn publicREADMEChangelogAbout

Trust

SecurityLimitationsPrivacyTermsData rightsSubprocessorsTrademarkContact
© 2026 Vraelis
XLinkedInSecurityPrivacyTerms