Attesto

Price and check certified document translations for U.S. immigration (USCIS): live per-page pricing and quotes, the 80 supported languages, document types and the USCIS translation-certification rules. Read-only, no sign-up.

Hosted MCP Server

npx add-mcp 'https://attestodocs.com/mcp'

Installs into Claude Code, Codex, Cursor and more

Documentation

API documentation

Everything the site does, as REST. Versioned at /api/v1, key authentication, idempotent POSTs, HMAC-signed webhooks. OpenAPI spec →

Authentication

Create keys in your firm portal. Live keys start atk\_live\_, sandbox keys atk\_test\_ — sandbox orders complete instantly with clearly-marked fake deliverables and cost nothing. Send the key on every request:


Authorization: Bearer atk_live_xxxxxxxx

POSTs accept an Idempotency-Key header — retries with the same key replay the original response. Rate limit: 60 requests/minute per key (429 with your limit when exceeded).

Place an order — cURL


# 1. Presign an upload
curl -s https://attestodocs.com/api/v1/documents \
  -H "Authorization: Bearer $ATTESTO_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: upl-001" \
  -d '{"filename":"birth-certificate.pdf","contentType":"application/pdf","byteSize":18037}'
# → { "key": "documents/…", "uploadUrl": "…" }

# 2. Upload the file bytes
curl -s -X PUT "$UPLOAD_URL" -H "Content-Type: application/pdf" \
  --data-binary @birth-certificate.pdf

# 3. Quote (page count + language detection + locked price)
curl -s https://attestodocs.com/api/v1/quotes \
  -H "Authorization: Bearer $ATTESTO_KEY" \
  -H "Content-Type: application/json" \
  -d '{"documents":[{"key":"'$KEY'","filename":"birth-certificate.pdf","mimeType":"application/pdf"}]}'
# → { "quoteToken": "…", "totalCents": 2495, "totalPages": 1, … }

# 4. Create the order
curl -s https://attestodocs.com/api/v1/orders \
  -H "Authorization: Bearer $ATTESTO_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: ord-001" \
  -d '{"quoteToken":"'$QUOTE_TOKEN'","email":"paralegal@firm.example","matterNumber":"2026-0142"}'
# → { "orderNumber": "AT-…", "status": "PAID", "billing": "invoice_net30", … }

# 5. Poll status (or subscribe a webhook instead)
curl -s https://attestodocs.com/api/v1/orders/$ORDER_NUMBER \
  -H "Authorization: Bearer $ATTESTO_KEY"

# 6. Download deliverables when status is CLIENT_REVIEW or DELIVERED
curl -s https://attestodocs.com/api/v1/orders/$ORDER_NUMBER/deliverables \
  -H "Authorization: Bearer $ATTESTO_KEY"

Node.js


const BASE = "https://attestodocs.com/api/v1";
const KEY = process.env.ATTESTO_KEY;
const h = { authorization: `Bearer ${KEY}`, "content-type": "application/json" };

// 1–2. presign + upload
const bytes = await fs.promises.readFile("birth-certificate.pdf");
const presign = await fetch(`${BASE}/documents`, {
  method: "POST", headers: h,
  body: JSON.stringify({ filename: "birth-certificate.pdf", contentType: "application/pdf", byteSize: bytes.length }),
}).then(r => r.json());
await fetch(presign.uploadUrl, { method: "PUT", headers: { "content-type": "application/pdf" }, body: bytes });

// 3. quote
const quote = await fetch(`${BASE}/quotes`, {
  method: "POST", headers: h,
  body: JSON.stringify({ documents: [{ key: presign.key, filename: "birth-certificate.pdf", mimeType: "application/pdf" }] }),
}).then(r => r.json());

// 4. order
const order = await fetch(`${BASE}/orders`, {
  method: "POST", headers: { ...h, "idempotency-key": "ord-001" },
  body: JSON.stringify({ quoteToken: quote.quoteToken, email: "paralegal@firm.example", matterNumber: "2026-0142" }),
}).then(r => r.json());
console.log(order.orderNumber, order.status);

Python


import os, requests

BASE = "https://attestodocs.com/api/v1"
H = {"Authorization": f"Bearer {os.environ['ATTESTO_KEY']}"}

# 1–2. presign + upload
data = open("birth-certificate.pdf", "rb").read()
presign = requests.post(f"{BASE}/documents", headers=H, json={
    "filename": "birth-certificate.pdf", "contentType": "application/pdf", "byteSize": len(data),
}).json()
requests.put(presign["uploadUrl"], data=data, headers={"Content-Type": "application/pdf"})

# 3. quote
quote = requests.post(f"{BASE}/quotes", headers=H, json={
    "documents": [{"key": presign["key"], "filename": "birth-certificate.pdf", "mimeType": "application/pdf"}],
}).json()

# 4. order
order = requests.post(f"{BASE}/orders", headers={**H, "Idempotency-Key": "ord-001"}, json={
    "quoteToken": quote["quoteToken"], "email": "paralegal@firm.example", "matterNumber": "2026-0142",
}).json()
print(order["orderNumber"], order["status"])

Webhooks

Subscribe with POST /webhooks to order.paid, order.client\_review, order.delivered and every other transition. Each delivery is signed; verify like this:


import { createHmac, timingSafeEqual } from "crypto";

function verify(req, secret) {
  const ts = req.headers["x-attesto-timestamp"];
  const sig = req.headers["x-attesto-signature"]; // "sha256=…"
  const expected = "sha256=" + createHmac("sha256", secret)
    .update(`${ts}.${req.rawBody}`).digest("hex");
  return timingSafeEqual(Buffer.from(sig), Buffer.from(expected))
    && Math.abs(Date.now() / 1000 - Number(ts)) < 300; // 5-min tolerance
}

Errors

Every failure returns { "error": { "code", "message" } } with a stable code: unauthorized, insufficient_scope, rate_limited, invalid_request, document_not_found, unreadable_document, quote_expired, matter_number_required, not_found, not_ready.


Source: https://attestodocs.com/docs/api