API documentation

Quickstart

End-to-end pipeline in under five minutes using a free sandbox key. Three flavors — pick whichever fits your stack. Each one finishes at a verifiable certified PDF + JWS receipt.

Prerequisites

Two things, both free, both self-serve.

  • A Verdacert account. Sign up here — magic-link auth, no password.
  • A sandbox key minted in the agent portal. Sandbox keys run a deterministic state machine — no real translation, no charge, ideal for development.
What the sandbox does for you
Sandbox orders walk through the entire status lifecycle on a wall clock: created → paid → processing → in_review → ready in ~2 minutes for full translation, or created → paid → reviewing_draft → ready in ~90s for Review-and-Certify. The certified artifact you get back is a real Ed25519-signed receipt — verify it against the live JWKS exactly the same way you would in production.

Path A · Plain REST

Any language with HTTP + JSON. Curl below; trivially portable.

1. Ground the agent on live enums

curl https://verdacert.com/api/v1/capabilities \
  -H "Authorization: Bearer vc_sandbox_…"

Returns supported languages, document types, speed tiers, add-ons (and whether each is currently available), and the USCIS acceptance guarantee URL. Cacheable for ~1h on your side.

2. Get a binding quote

curl -X POST https://verdacert.com/api/v1/quote \
  -H "Authorization: Bearer vc_sandbox_…" \
  -H "Content-Type: application/json" \
  -d '{
    "sourceLanguage": "fa",
    "useCase":        "uscis",
    "pageCount":      2,
    "speedTier":      "standard"
  }'

Response carries quoteId, totalCents, an itemized breakdown, promisedDeliveryAt, and expiresAt (24h TTL). Show totalCents / 100 to your end-user; ask for confirmation; then submit.

3. Submit the job

curl -X POST https://verdacert.com/api/v1/submit \
  -H "Authorization: Bearer vc_sandbox_…" \
  -H "Content-Type: application/json" \
  -d '{
    "quoteId":        "q_aabbccdd_1716480000000_x9k3",
    "idempotencyKey": "demo-order-0001",
    "echoedInput": {
      "sourceLanguage": "fa",
      "useCase":        "uscis",
      "pageCount":      2,
      "speedTier":      "standard"
    },
    "documents": [
      { "url": "https://example.com/birth-cert.pdf" }
    ]
  }'

Returns a jobId immediately. The idempotencyKey is yours to choose; reuse it to safely retry the same submit without creating a duplicate order.

Why echoedInput?
quote is stateless — there is no quotes table. submit re-prices server-side using echoedInput and binds the quote id to the calling key so a stale or stolen quoteId can't change what gets ordered.

4. Poll until ready

# Sandbox flips through states on a wall clock
# in ~2 minutes; recommend exponential backoff starting at 30s.
curl https://verdacert.com/api/v1/status/<jobId> \
  -H "Authorization: Bearer vc_sandbox_…"

Returns status, progressPercent (0–100), statusDescription, and an events array. Stop polling when status === "ready", or skip polling entirely and use webhooks.

5. Fetch the certified result

curl https://verdacert.com/api/v1/result/<jobId> \
  -H "Authorization: Bearer vc_sandbox_…"

Returns the certified PDF URL, the certificate metadata (issuer, translator, public verify URL), and a compact JWS you can verify against the live JWKS without calling us.

6. Verify the certificate (public, no auth)

curl https://verdacert.com/api/v1/verify/<certificateId>

The verification endpoint never requires a key. That's the design: a USCIS reviewer, an opposing lawyer, or a university registrar can verify a Verdacert receipt with zero setup. Full walkthrough at /docs/certificates.

Path B · Vercel AI SDK

One import gives you all seven tools, typed, ready to drop into generateText / streamText / agent loops. Full reference at /docs/ai-sdk.

Install

pnpm add @verdacert/ai-sdk-tools ai zod
# or: npm i @verdacert/ai-sdk-tools ai zod

Use

import { generateText, stepCountIs } from "ai";
import { createVerdacertTools } from "@verdacert/ai-sdk-tools";

const tools = createVerdacertTools({
  apiKey: process.env.VERDACERT_API_KEY!,
});

const { text } = await generateText({
  // Routes through Vercel AI Gateway automatically when
  // AI_GATEWAY_API_KEY is present (auto-injected on Vercel).
  model:    "anthropic/claude-sonnet-4",
  tools,
  stopWhen: stepCountIs(20),
  prompt:
    "I have a 3-page Farsi birth certificate at " +
    "https://example.com/cert.pdf that I need certified " +
    "for USCIS. Quote it, submit it, poll until ready, " +
    "and give me back the certified URL.",
});

console.log(text);
Recommended: route through Vercel AI Gateway
Same pricing as the provider, multi-provider failover, observability, one key for many models. Set AI_GATEWAY_API_KEY (auto-injected on Vercel) and the provider-string model (anthropic/claude-sonnet-4) does the routing automatically.

Path C · MCP (Claude Desktop / Cursor / any MCP client)

Streamable HTTP MCP server at https://verdacert.com/api/mcp. Six tools. Stateless. Full reference at /docs/mcp.

Claude Desktop

Add to ~/Library/Application Support/Claude/claude_desktop_config.json and restart Claude Desktop:

{
  "mcpServers": {
    "verdacert": {
      "url": "https://verdacert.com/api/mcp",
      "headers": {
        "Authorization": "Bearer vc_sandbox_…"
      }
    }
  }
}

Cursor

Settings → MCP → Add new MCP server. Same JSON as above.

Any HTTP client (raw JSON-RPC)

curl https://verdacert.com/api/mcp \
  -H 'Authorization: Bearer vc_sandbox_…' \
  -H 'Accept: application/json, text/event-stream' \
  -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc": "2.0",
    "id":      1,
    "method":  "tools/list",
    "params":  {}
  }'

Going live

When you've validated against sandbox and want to make real orders.

  1. Open /portal/api, add a default payment method, and mint a live key (vc_live_…).
  2. Swap your sandbox token for the live token. Token is the only thing that changes — code paths are identical.
  3. Configure your webhook URL on the key (or pass webhookUrl per-call on submit) so you can skip polling. See /docs/webhooks.
  4. Set a spend cap in the portal if you want a safety rail (per-day, per-month, or both). Caps are enforced server-side and return SPEND_LIMIT_EXCEEDED when crossed.
Live keys charge real cards
A successful submitcall on a live key triggers an off-session Stripe charge against your default payment method. There's no separate “approve charge” step. Test thoroughly on sandbox first; sandbox is byte-identical to live aside from the no-bill and synthetic-status behavior.

Where to next

Get instant quotePricing