REST

API reference

For AI agents → Connect and install the pluginMCP endpoint: https://directmailamerica.com/api/mcp. Standard MCP price estimates need no account; expanded artwork quotes and workspace tools use OAuth or a securely configured Bearer key. Start with get_connection_status.

Expanded products: quote, then send

Use GET /api/v1/products for flats, Pro postcards, statements, coupon sheets, and print options. New products require an exact quote before ordering. Coupon books are excluded.

Create a held quote with POST /api/v1/product-quotes: send options (productId, paper, color, doubleSided, returnEnvelope, electronicReturnReceipt), US sender and recipient addresses, and pdfBase64. The PDF must match the selected dimensions. The response includes the total and a quote ID; this does not release mail.

After approving the total and physical mailing, use PUT /api/v1/product-quotes with the quote ID, action: "send", and confirmed: true. This spends workspace credits and releases the order once. Recover with GET /api/v1/product-quotes?id=…. Staging keys never mail. A processing or needs-review result must not be replaced by a new order.

To pay for that order directly with x402 USDC, use POST /api/v1/orders with quoteId, confirmed: true and the approved expectedTotalCents. The unsigned request returns its exact payment challenge without spending credits. Repeat the same body with PAYMENT-SIGNATURE to pay and release the saved mailing once. This supports letters and both postcard formats; no account top-up is required. Order payment examples and recovery.

Read current prices from GET /api/v1/pricing. Letters are priced by mail class, page count and print options; Express postcards have a flat price per piece, with color included (set document.color to true; false converts the mailing PDF to grayscale) at 5.5 × 4.25 inches. Supply one landscape 396 × 306 point PDF artwork page, without added bleed or crop marks; the provider adds the address reverse. PDFs are limited to 25 MiB.

Base path /api/v1. Authenticate with Authorization: Bearer lbl_live_... or lbl_test_.... Machine-readable spec: /api/v1/openapi.json.

Auth

  • Create keys in the workspace Developers page. Production keys start with lbl_live_ and mail on this live deployment. Staging keys start with lbl_test_ and never purchase postage (developer sandbox). Credit debits and payments can still be real.
  • Keys are hashed at rest and shown once.
  • Missing or invalid keys return HTTP 401 with { "error": "..." }.

curl · quote

curl -sS https://directmailamerica.com/api/v1/pricing?mailClass=first_class&pageCount=2 \
  -H "Authorization: Bearer lbl_live_your_key"

Endpoints

  • POST /letters — create a mailing
  • GET /letters — list mailings
  • GET /letters/:id — status
  • POST /addresses/validate — format stub (not USPS CASS)
  • GET /products — public expanded product catalog
  • POST /product-quotes — hold a quote
  • GET /product-quotes?id=… — recover a quote
  • PUT /product-quotes — confirm a quote
  • POST /orders — pay an approved quote with x402 and send
  • GET /pricing — quote
  • POST /credits — x402 credit purchase

Create a letter

Example only — these addresses are fictional placeholders for copy-paste. Replace every field before you mail.

If the workspace has credits, they are spent. Otherwise the API returns HTTP 402 with a PAYMENT-REQUIRED header. Retry with PAYMENT-SIGNATURE to pay per job in USDC on Base or Solana, or top up with Square in the dashboard. Hosted MCP send_letter uses this same rail and also allows guest (no-key) x402 — see MCP docs.

curl

curl -sS -X POST https://directmailamerica.com/api/v1/letters \
  -H "Authorization: Bearer lbl_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "mailClass": "first_class",
    "from": {
      "name": "Your Name",
      "line1": "123 Example Street",
      "city": "New Haven",
      "state": "CT",
      "postal": "06510"
    },
    "recipients": [{
      "name": "Recipient Name",
      "line1": "456 Example Avenue",
      "city": "Austin",
      "state": "TX",
      "postal": "78701"
    }],
    "document": {
      "kind": "text",
      "content": "Hello from the DirectMailAmerica API."
    }
  }'

TypeScript

const key = process.env.DIRECTMAILAMERICA_API_KEY!; // still lbl_live_... or lbl_test_...

export async function sendLetter() {
  const res = await fetch("https://directmailamerica.com/api/v1/letters", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${key}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      mailClass: "first_class",
      from: {
        name: "Your Name",
        line1: "123 Example Street",
        city: "New Haven",
        state: "CT",
        postal: "06510",
      },
      recipients: [
        {
          name: "Recipient Name",
          line1: "456 Example Avenue",
          city: "Austin",
          state: "TX",
          postal: "78701",
        },
      ],
      document: { kind: "text", content: "Hello from the API." },
    }),
  });

  if (res.status === 402) {
    const challenge = res.headers.get("PAYMENT-REQUIRED");
    throw new Error(`Payment required. Header: ${challenge}`);
  }
  if (!res.ok) throw new Error(await res.text());
  return res.json();
}

Webhooks

Set a destination on the Developers page. Delivery attempts are logged there. We POST JSON on letter.created, letter.updated, credits.purchased, and webhook.test. Verify X-DirectMailAmerica-Signature: sha256=<hmac> using your org webhook secret (or org id if you have not set a secret).

payload

{
  "id": "evt_...",
  "type": "letter.created",
  "createdAt": "2026-09-09T00:00:00.000Z",
  "data": {
    "id": "job_...",
    "status": "in_production",
    "statusLabel": "In Production",
    "mailClass": "first_class",
    "priceCents": 149,
    "trackingNumber": null
  }
}

Error codes

  • 400 — validation or malformed body
  • 401 — missing/invalid API key or session
  • 402 — payment_required / insufficient_credits
  • 403 — admin-only route
  • 404 — letter not found
  • 422 — address validation failed