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 withlbl_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 body401— missing/invalid API key or session402—payment_required/insufficient_credits403— admin-only route404— letter not found422— address validation failed