API12 min read

Inbox Placement Test API — complete developer guide

Everything you need to integrate Inbox Check into your backend: authentication, endpoints, webhooks, streaming, rate limits, SDKs, example payloads. One bookmark.

This is the reference most engineers want and rarely find in one place: every endpoint, every parameter, the auth model, the webhook lifecycle, and how to move off a competitor like GlockApps without rewriting your whole integration. Bookmark it and keep moving.

Who this is for

Backend, DevOps and SRE engineers integrating inbox placement tests into a product, a deployment pipeline, or an internal monitoring tool. You know what Bearer means, you prefer JSON over screenshots, and you want a contract you can lint.

What the API does

Inbox Check API runs a placement test: you submit a message, we fan it out to 20+ seed mailboxes across Gmail, Outlook, Yahoo, Mail.ru, Yandex, GMX, ProtonMail and others, record where each copy landed (Inbox, Promotions, Spam, Missing), and return an aggregate verdict together with SPF, DKIM, DMARC, Rspamd and SpamAssassin data.

The API is REST over HTTPS, JSON in and JSON out. The free tier covers unlimited UI tests; the paid tier unlocks programmatic access, longer retention, webhooks, and higher rate limits.

Authentication

Every request carries a Bearer token. Keys are generated in Settings → API keys, live keys are prefixed ic_live_, sandbox keys are prefixed ic_test_. There is no OAuth layer and no session cookie — a token is the whole identity.

Authorization: Bearer ic_live_4fN2q8s...
Content-Type: application/json
Accept: application/json

Keys can be scoped read, write, or webhook-sign. Rotate by generating a new key, pushing it to your secret store, and revoking the old one. Keys never expire automatically — revoke explicitly.

Base URL and versioning

The production base URL is https://check.live-direct-marketing.online. The API is currently unversioned in the path; breaking changes will introduce /v2/ and run in parallel for at least 12 months. Non-breaking additions (new fields, new providers) ship without a version bump.

Endpoints

POST /api/tests — create a test

The only required field is html. Everything else has a sensible default.

POST /api/tests HTTP/1.1
Host: check.live-direct-marketing.online
Authorization: Bearer ic_live_xxx
Content-Type: application/json

{
  "senderDomain": "news.yourbrand.com",
  "fromAddress": "hello@news.yourbrand.com",
  "fromName": "Brand Weekly",
  "subject": "Your Tuesday digest is ready",
  "html": "<html><body><h1>Hello</h1></body></html>",
  "text": "Hello",
  "headers": {
    "List-Unsubscribe": "<https://example.com/u/abc>",
    "List-Unsubscribe-Post": "List-Unsubscribe=One-Click"
  },
  "seedSet": "default",
  "webhookUrl": "https://api.yourapp.com/hooks/inbox-check",
  "tags": ["nightly-monitor", "prod"]
}

Response, 201 Created:

{
  "id": "t_01HG2NQ3B5F8X9WVQ6Z1A2C4D7",
  "status": "queued",
  "createdAt": "2026-06-18T10:14:03.221Z",
  "pollUrl":    "/api/tests/t_01HG2NQ3B5F8X9WVQ6Z1A2C4D7",
  "streamUrl":  "/api/tests/t_01HG2NQ3B5F8X9WVQ6Z1A2C4D7/stream",
  "expectedCompletionAt": "2026-06-18T10:19:03.221Z"
}

GET /api/tests/:id — fetch one test

Returns the current state. Safe to poll every 10–30 seconds until status is complete or failed.

{
  "id": "t_01HG2NQ3B5F8X9WVQ6Z1A2C4D7",
  "status": "complete",
  "createdAt": "2026-06-18T10:14:03.221Z",
  "completedAt": "2026-06-18T10:17:48.002Z",
  "summary": {
    "inboxCount":    17,
    "promoCount":     2,
    "spamCount":      2,
    "missingCount":   1,
    "total":         22,
    "inboxRate":   0.7727
  },
  "auth": {
    "spf":   { "result": "pass", "domain": "news.yourbrand.com" },
    "dkim":  { "result": "pass", "selector": "s1" },
    "dmarc": { "result": "pass", "policy": "quarantine", "aligned": true }
  },
  "content": {
    "spamAssassin": { "score": 1.4, "rules": ["HTML_MESSAGE","MIME_HTML_ONLY"] },
    "rspamd":       { "score": -0.8, "symbols": ["R_DKIM_ALLOW","ARC_NA"] }
  },
  "providers": [
    { "provider": "gmail",     "region": "us",  "placement": "inbox" },
    { "provider": "outlook",   "region": "us",  "placement": "spam"  },
    { "provider": "yahoo",     "region": "us",  "placement": "inbox" },
    { "provider": "mail.ru",   "region": "ru",  "placement": "inbox" },
    { "provider": "yandex",    "region": "ru",  "placement": "promo" }
  ]
}

GET /api/tests/:id/stream — Server-Sent Events

Subscribe once, receive one event per seed-mailbox landing, close after the final complete event. Events are named; the payload is JSON.

event: landing
data: {"provider":"gmail","region":"us","placement":"inbox","at":"2026-06-18T10:14:44Z"}

event: landing
data: {"provider":"outlook","region":"us","placement":"spam","at":"2026-06-18T10:15:02Z"}

event: complete
data: {"id":"t_01HG2NQ3...","summary":{"inboxCount":17,"total":22,"inboxRate":0.7727}}

GET /api/tests — list

Paginated, newest first. Supports ?limit= (max 100), ?cursor=, ?status=, ?tag=, ?since= (ISO timestamp).

GET /api/tests?limit=20&status=complete&tag=prod HTTP/1.1

{
  "data": [ /* test objects */ ],
  "nextCursor": "c_2026-06-18T09:00:00Z",
  "hasMore": true
}

GET /api/me — who am I

Returns the key's plan, rate limits and usage counters. Useful for health checks and quota dashboards.

{
  "key": { "id": "k_01HF...", "scopes": ["read","write"], "prefix": "ic_live_4fN2q8" },
  "plan": "scale",
  "limits": { "testsPerMinute": 10, "testsPerMonth": 5000 },
  "usage": { "testsThisMonth": 412, "resetsAt": "2026-07-01T00:00:00Z" }
}

Webhook lifecycle and signature verification

If webhookUrl is set on a test (or configured globally in Settings), we POST a signed payload on test.completed and test.failed. Every request carries two headers:

  • X-IC-Signature: sha256=<hex> — HMAC of the raw body with the webhook secret.
  • X-IC-Event: test.completed — event name, use for routing.

Retries: 5 attempts over 24 hours with exponential backoff (30s, 2m, 10m, 1h, 6h). Any 2xx response acknowledges delivery; anything else is retried. Receivers must be idempotent — the same X-IC-Delivery header may be replayed.

Rate limits and 429 handling

Every response includes rate-limit headers so you don't have to guess:

  • X-RateLimit-Limit — requests per minute allowed on this key.
  • X-RateLimit-Remaining — requests left in the current window.
  • X-RateLimit-Reset — Unix timestamp when the window resets.
  • Retry-After — seconds to wait, only on 429.

On 429, honour Retry-After, then back off exponentially with a cap at 2 minutes. Do not hot-loop.

SDKs

Two official SDKs ship today; a Go SDK is on the roadmap.

Python

pip install inbox-check

from inbox_check import Client
ic = Client(api_key="ic_live_xxx")

test = ic.tests.create(
    sender_domain="news.yourbrand.com",
    subject="Weekly digest",
    html="<p>Hello</p>",
)
result = ic.tests.wait(test.id, timeout=300)
print(result.summary.inbox_rate)

Node.js

npm install @inbox-check/sdk

import { InboxCheck } from '@inbox-check/sdk';
const ic = new InboxCheck({ apiKey: process.env.IC_KEY });

const test = await ic.tests.create({
  senderDomain: 'news.yourbrand.com',
  subject: 'Weekly digest',
  html: '<p>Hello</p>',
});
const result = await ic.tests.wait(test.id);
console.log(result.summary.inboxRate);

Polling vs streaming vs webhooks — which to pick

  1. Polling (GET /api/tests/:id). Use in CI jobs under 5 minutes. Dead simple, survives flaky networks. Poll every 15s.
  2. Streaming (SSE). Use in a long-lived process that wants live per-mailbox updates. Connection survives 30 minutes; one test takes 2–10 minutes.
  3. Webhooks. Use for anything serverless, event-driven, or user-facing. No connection to keep open, no cron to run.
Rule of thumb

CI pipelines poll. Dashboards stream. Production systems webhook. Do not mix streaming and webhooks for the same test — you'll end up double-processing the result.

Migration guide from GlockApps API

If you're moving off GlockApps, the mapping is almost 1:1. The concepts (test, seed list, placement, summary) are the same; the names differ.

  • GlockApps POST /tests → Inbox Check POST /api/tests. Body fields: subject, html, from all map directly. seedList becomes seedSet.
  • GlockApps GET /tests/:id → same path, same semantics. Summary fields renamed: inboxinboxCount, deliverabilityinboxRate (0..1 instead of 0..100).
  • Auth: Bearer token instead of X-Api-Key. Rename the header, done.
  • Webhooks: identical HMAC-SHA256 scheme, header name changes from X-GA-Signature to X-IC-Signature.
  • Cost: no per-test overage surprises. Quotas are monthly; once exhausted you get 402 until reset or a plan upgrade.

A typical migration takes a senior engineer under a day. The GlockApps → Inbox Check shim used internally is 80 lines of TypeScript.

Error shape

Every 4xx / 5xx response carries the same JSON shape:

{
  "error": {
    "code": "rate_limited",
    "message": "10 requests per minute exceeded",
    "docsUrl": "https://check.live-direct-marketing.online/docs/errors#rate_limited",
    "requestId": "req_01HG2NR4..."
  }
}

Include requestId in support tickets — it pulls up the full trace on our side.

Frequently asked questions

How long does a single test take to complete?

2 to 10 minutes depending on provider response times. Gmail and Outlook land within 3 minutes on the happy path; Mail.ru and Yandex occasionally take the full 10. The API will not time out before 15 minutes.

Can I test the same template against multiple sender domains in one call?

No — one test, one sender. Parallelise on your side by firing N POST requests and waiting for N webhooks. The rate limit applies per key, so batch through a queue if you are testing dozens of senders simultaneously.

Is there a difference between the free UI and the paid API?

Functionally, no. The API exposes everything the UI does plus webhooks, tags, history retention beyond 30 days, and higher concurrency. The free UI tests are unlimited but cannot be driven programmatically and are not retained long term.

Do you support MCP for AI agents?

Yes. The ldm-inbox-check-mcp package gives Claude, Cursor and any MCP-compatible agent direct tool access to the same endpoints documented here. Unlike GlockApps, MCP support is first-class and free to use.
Related reading

Check your deliverability across 20+ providers

Gmail, Outlook, Yahoo, Mail.ru, Yandex, GMX, ProtonMail and more. Real inbox screenshots, SPF/DKIM/DMARC, spam engine verdicts. Free, no signup.

Run Free Test →

Unlimited tests · 20+ seed mailboxes · Live results · No account required