Our API NEW IN 2.0

Contract review, as an endpoint.

Post a document against one of your playbooks and get a run back. Subscribe to the webhook and the findings arrive the moment they exist, the same review, the same two scores and the same audit record as every other way into Vern.

ONE DEAL, END TO END api.askvern.ai
POST /v1/reviews
{
"playbook_id": "pb_uk_client_terms",
"file_url": "…/meridian-tob-v2.docx",
"matter_ref": "MER-118"
}
202 Accepted 142 ms
{ "run_id": "run_01JX8K", "reserved": 0.5 }
HOOK review.completed
{ "playbook_score": 48, "band": "Negotiate",
"flagged": 3, "new_clauses": 1 }
ROUND 2 OF MER-118 0.5 CREDIT · SAME AS THE APP
NO POLLING · SIGNED WEBHOOKS · IDEMPOTENT SUBMITS
Version
2026-04-01
Auth
Scoped keys
Webhooks
Signed and retried
Sandbox
Free, with fixtures
The surface

Six calls is the whole of it.

Small enough to read in one sitting. Everything a review does in the app, it does here.

POST /v1/reviews Submit a document against a playbook. Returns a run immediately; the findings follow on the webhook. 1.0 credit
POST /v1/reviews/{id}/rounds Their next version on the same deal. Diffed against the round before it rather than reviewed cold. 0.5 credit
GET /v1/reviews/{id} Status, both scores, the band, and how long the run took. free
GET /v1/reviews/{id}/findings Clause by clause: Playbook Score, Vern Score, the position it breaches and suggested wording. free
GET /v1/playbooks Your published positions and their fallback tiers. Read-only, editing stays in the app, on purpose. free
GET /v1/usage Credits used, reserved and remaining this period, the same numbers your admins see. free

Multipart upload is supported everywhere a file_url is, if you'd rather not expose one. Both paths honour the same quota, the same scope and the same audit trail.

A real exchange · pick one

What goes out, what comes back.

Trimmed for the page, not invented, these are the shapes the reference documents.

REQUEST cURL
curl -X POST https://api.askvern.ai/v1/reviews \
-H "Authorization: Bearer $VERN_KEY" \
-H "Idempotency-Key: mer-118-r1" \
-d '{
"playbook_id": "pb_uk_client_terms",
"file_url": "…/meridian-tob.docx",
"matter_ref": "MER-118",
"callback_url": "…/hooks/vern"
}'
RESPONSE 202 Accepted
{
"run_id": "run_01JX8K",
"status": "queued",
"round": 1,
"credits_reserved": 1.0,
"expect_webhook": "review.completed"
}
The reservation is soft

If the run fails, it’s released and you’re charged nothing, a retry with the same idempotency key won’t double it either.

Two scores per clause

Never merged into one number: how far it sits from your position, and how well it’s drafted.

The webhook for a round carries the movement too

What improved, what regressed, and any clause that wasn’t in the version before.

Nothing is computed twice

The same figures as the usage screen, from the same table we invoice off.

Webhooks

You shouldn't have to poll us.

A review takes as long as it takes, usually under two minutes, longer for a hundred-page master agreement. So we push. Every event is signed, delivered at least once, and retried on a schedule you can plan around.

THE EVENTS
review.completed Scores, findings, the lot
review.failed With a reason, and nothing charged
round.completed Plus what moved since last time
expert_review.released When a human’s revision lands
quota.reached Before the refusals start
VERIFY BEFORE YOU TRUST IT
const sig = req.headers['vern-signature']
const ts  = req.headers['vern-timestamp']
if (!verify(rawBody, ts, sig, secret))
return res.status(400).end()
// HMAC-SHA256 over the raw body
// 5-minute replay window, then rejected
IF YOUR ENDPOINT IS DOWN

We retry at one minute, five, thirty, two hours and six, then dead-letter it. Nothing is silently dropped, failed deliveries are listed in the dashboard and you can replay any of them by hand.

1m5m30m2h6h dead letter · replayable
When it goes wrong

Errors that tell you what to do next.

Every failure names the field, the limit or the reason. And the billing rule is the same one the rest of Vern runs on: if it didn't reach you, you didn't pay for it.

STATUS CODES YOU'LL ACTUALLY SEE
400 Malformed body, with the offending field named rather than a generic complaint.
402 Out of credits. Refused outright rather than queued, nothing runs and nothing is charged.
403 Your key can’t reach that. Row-level security applies to the API exactly as it does in the app.
409 Same idempotency key as before, we hand back the original run instead of creating a second one.
415 A file we can’t parse. DOCX and PDF in, scans only if there’s a text layer.
429 Over your key’s rate limit, with a Retry-After you can respect.
5xx Ours. The reservation is released, the run is retryable, and it never appears on your invoice.
Retry as hard as you like

Send an Idempotency-Key with every submit and a repeat gets you the run you already have. Retries after a timeout, a redeploy or a queue replay cannot cost you a second credit.

Billed identically

The API isn't a separate meter. A first review is 1.0, a later round 0.5, re-running the same version is free, and a failure costs nothing, the same as an upload or a forwarded email.

How credits work →
Getting on it

A key, a sandbox, then production.

Keys are issued per organisation and scoped to it, a key cannot see another customer's anything, and every call is attributed and audit-logged like any other action in Vern.

Versions are dated. Additive changes ship whenever they're ready; a breaking one gets a new date and twelve months' notice, and we tell you which of your keys is still on the old one.

OpenAPI specPostman collectionNode and Python snippetsUK/EU residency
01
Generate a key

Issued from your organisation’s admin area where API access is part of your agreement, with the rate limit set to whatever your volume needs.

02
Build against the sandbox

Fixture contracts, deterministic scores, real webhooks. It consumes no credits, so hammer it.

03
Swap the base URL

Nothing else changes. Runs you create appear on the matter in Vern, next to the ones people made by hand.

KEYS ROTATABLE AND REVOCABLE · VERSION 2026-04-01

Send us a contract from your own system.

Bring an endpoint and one real document to the call. We'll walk the whole exchange end to end, from the request to the signed webhook.