API documentation

Vercel AI SDK

The @verdacert/ai-sdk-tools npm package wraps the REST API as a typed Vercel AI SDK tool catalog. Drop one import into your generateText, streamText, or agent loop and the model can quote, submit, poll, refund, and verify end-to-end.

Install

Two peer deps, both standard.

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

ai (v5 or v6) and zod (v3 or v4) are peer dependencies — bring your own version.

Usage

One factory call, one import, all seven tools.

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 when AI_GATEWAY_API_KEY is
  // present (auto-injected on Vercel). Provider-string model.
  model:    "anthropic/claude-sonnet-4",
  tools,
  stopWhen: stepCountIs(20), // multi-step agent loop
  prompt:
    "I have a 3-page Farsi birth certificate at " +
    "https://example.com/cert.pdf. Quote a USCIS-acceptance " +
    "translation, submit it, poll until ready, and give me " +
    "the certified URL.",
});

console.log(text);
Recommended: route through Vercel AI Gateway
Same pricing as the underlying provider, multi-provider failover, observability, one key for many models. On Vercel, AI_GATEWAY_API_KEY is auto-injected — the AI SDK forwards the provider-string model id automatically. If you prefer direct providers, swap to model: anthropic("claude-sonnet-4-20250514") from @ai-sdk/anthropic.

The seven tools

Each is a plain AI SDK Tool — destructure if you only want a subset.

ToolDescription
getCapabilitiesReturns live enums — call once per session to ground the model.
quoteBinding price + ETA. Free; no order created. quoteId valid 24h.
submitPlace the order. Idempotent on (apiKey, idempotencyKey). Returns jobId.
getStatusPoll progress. Safe to back off — start at 30s.
getResultFetch the certified PDF URL + JWS receipt once status === ready.
refundFull or partial refund within 30 days. Stripe-idempotent server-side.
verifyCertificateIndependently verify a Verdacert certificate id.

Subset / extend

// Only some tools? Destructure:
const { quote, submit, getStatus, getResult } =
  createVerdacertTools({ apiKey: process.env.VERDACERT_API_KEY! });

const { text } = await generateText({
  model: "anthropic/claude-sonnet-4",
  tools: { quote, submit, getStatus, getResult },
  prompt: "…",
});

Each entry is a plain AI SDK Tool — wrap or instrument freely. Pre-validate inputs with the exported zod schemas if you want to short-circuit before a tool call:

import { quoteInputSchema } from "@verdacert/ai-sdk-tools";
const parsed = quoteInputSchema.safeParse(input);

Client options

The factory accepts a few overrides for testing and observability.

createVerdacertTools({
  apiKey: process.env.VERDACERT_API_KEY!,

  // Optional:
  baseUrl: "https://verdacert.com",       // staging / self-host override
  fetch: globalThis.fetch,                // inject for tracing or retries
  defaultHeaders: { "x-trace-id": "…" },  // forwarded on every call
});
OptionTypePurpose
apiKeystringRequired. Live or sandbox token.
baseUrlstringOverride the host (default https://verdacert.com).
fetchtypeof fetchInject your own fetch implementation — e.g. OpenTelemetry-wrapped.
defaultHeadersRecord<string,string>Headers added to every request (trace ids, custom User-Agent).

Errors

Non-2xx responses throw VerdacertHttpError with the structured envelope intact.

import { VerdacertHttpError } from "@verdacert/ai-sdk-tools";

try {
  await tools.submit.execute(input, /* AI SDK passes context */);
} catch (err) {
  if (err instanceof VerdacertHttpError) {
    console.error(err.status);            // 402
    console.error(err.body.code);         // "PAYMENT_FAILED"
    console.error(err.body.recoveryHint); // tuned for an LLM consumer
    console.error(err.requestId);         // hand this to support
  }
  throw err;
}

When tools are invoked by the AI SDK itself (e.g. inside generateText), errors flow through the SDK's tool-result channel and the model can react on the next turn — the recoveryHint values are tuned for that path. See /docs/errors for the stable code list.

Streaming

Plug straight into streamText — tool calls work identically.

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

export async function POST(req: Request) {
  const { messages } = await req.json();
  const tools = createVerdacertTools({
    apiKey: process.env.VERDACERT_API_KEY!,
  });

  const result = streamText({
    model: "anthropic/claude-sonnet-4",
    tools,
    stopWhen: stepCountIs(20),
    messages,
  });

  return result.toDataStreamResponse();
}

Verifying certificates client-side

verifyCertificate round-trips through the API and returns the parsed envelope plus a compact JWS. If you want to skip the round-trip and verify entirely against the cached JWKS:

import { jwtVerify, createRemoteJWKSet } from "jose";

const jwks = createRemoteJWKSet(
  new URL("https://verdacert.com/.well-known/jwks.json"),
);

const result = await tools.verifyCertificate.execute(
  { certificateId: "vcrt_…" },
  /* AI SDK context */,
);

const { payload, protectedHeader } = await jwtVerify(result.jws, jwks);
// payload.certificateId, payload.documentSha256, payload.isSandbox

Full walkthrough at /docs/certificates (Python and Go examples too).

Reference agent

A complete working example — Claude using these tools to walk a paralegal through an I-130 immigration case — lives in examples/immigration-paralegal.

git clone https://github.com/mitrakmt/verdacert.git
cd verdacert/examples/immigration-paralegal
pnpm install
cp .env.example .env       # add VERDACERT_API_KEY + ANTHROPIC_API_KEY
pnpm start                 # uses the included sample case
# … or supply your own case file:
pnpm start path/to/case.md

Where to next

Get instant quotePricing