API6 min read

cURL examples for every endpoint

Before you pull in an SDK, you want to hit the API raw. Here is a copy-paste cURL cheat sheet for every Inbox Check endpoint.

Every SDK ever written is a wrapper around cURL. When an integration misbehaves, the first thing to do is drop to the shell and hit the API directly. This page is a cheat sheet: one Pre block per endpoint, with request and a realistic response you can diff against.

Before you start

Every example below uses $IC as the Bearer token variable. Export it once — export IC=ic_live_xxx — and every snippet below is copy-paste runnable. Keys starting with ic_live_ hit production; ic_test_ hit the sandbox that returns fake seed data for integration tests.

Why cURL still wins for debugging

SDKs silently swallow headers. HTTP clients in browsers strip CORS detail. Postman is fine until you need to share the reproduction with a teammate over Slack. cURL is the lingua franca: every engineer on earth can paste your command into a terminal and see the exact same bytes on the wire. When you file a support ticket and attach a cURL line with --verbose, we can answer in minutes instead of hours.

Authentication header

Every request uses HTTP Bearer auth. The header is identical across endpoints:

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

The Accept header is optional for JSON endpoints but required for the SSE stream (where it switches to text/event-stream).

POST /api/tests — create a test

Start a new placement test. The request is accepted synchronously and returns a 202 with an id you use to fetch results.

curl -sS -X POST https://check.live-direct-marketing.online/api/tests \
  -H "Authorization: Bearer $IC" \
  -H "Content-Type: application/json" \
  -d '{
    "from":    "hello@news.yourbrand.com",
    "subject": "Weekly digest #42",
    "html":    "<html><body><p>Hi, here is your digest.</p></body></html>",
    "text":    "Hi, here is your digest."
  }'

Response:

HTTP/1.1 202 Accepted
Location: /api/tests/t_01H9XABC4D5E6F7G8H

{
  "data": {
    "id": "t_01H9XABC4D5E6F7G8H",
    "status": "pending",
    "createdAt": "2026-06-30T11:02:14Z",
    "seedCount": 22,
    "estimatedSeconds": 90
  },
  "meta": { "requestId": "req_01H9X...", "creditsRemaining": 248 }
}

GET /api/tests/:id — poll for the result

The cheapest way to wait. Poll every 10–15 seconds until status becomes complete.

curl -sS https://check.live-direct-marketing.online/api/tests/t_01H9XABC4D5E6F7G8H \
  -H "Authorization: Bearer $IC"
HTTP/1.1 200 OK

{
  "data": {
    "id": "t_01H9XABC4D5E6F7G8H",
    "status": "complete",
    "summary": {
      "inboxCount":   18,
      "spamCount":     3,
      "missingCount":  1,
      "total":        22
    },
    "auth": { "spf": "pass", "dkim": "pass", "dmarc": "pass" },
    "spamAssassinScore": 1.2,
    "providers": [
      { "provider": "gmail",     "folder": "inbox" },
      { "provider": "outlook",   "folder": "spam"  },
      { "provider": "yahoo",     "folder": "inbox" }
    ]
  },
  "meta": { "requestId": "req_01H9X..." }
}

GET /api/tests/:id/stream — SSE stream

If you want each seed-landing event as it happens, subscribe to the SSE endpoint. The stream emits one landing event per seed mailbox, then a final complete event with the aggregate summary.

curl -N -sS https://check.live-direct-marketing.online/api/tests/t_01H9XABC4D5E6F7G8H/stream \
  -H "Authorization: Bearer $IC" \
  -H "Accept: text/event-stream"
event: landing
data: {"provider":"gmail","folder":"inbox","tookMs":4120}

event: landing
data: {"provider":"outlook","folder":"spam","tookMs":6810}

event: landing
data: {"provider":"yahoo","folder":"inbox","tookMs":5010}

event: complete
data: {"id":"t_01H9XABC4D5E6F7G8H","status":"complete","summary":{"inboxCount":18,"spamCount":3,"missingCount":1,"total":22}}

The -N flag disables output buffering so events print as they arrive. Without it, cURL buffers until the stream ends and you lose the realtime signal.

GET /api/tests — list with pagination

Paginated with a cursor. Pass ?limit=50&cursor=... to walk the history.

curl -sS "https://check.live-direct-marketing.online/api/tests?limit=25" \
  -H "Authorization: Bearer $IC"
{
  "data": [
    { "id": "t_01H9XABC...", "status": "complete", "createdAt": "2026-06-30T11:02:14Z" },
    { "id": "t_01H9XAAA...", "status": "complete", "createdAt": "2026-06-30T10:44:02Z" },
    { "id": "t_01H9X999...", "status": "pending",  "createdAt": "2026-06-30T10:40:18Z" }
  ],
  "meta": {
    "nextCursor": "eyJpZCI6InRfMDFIOVg5OTkifQ==",
    "hasMore":    true
  }
}

Read the Link response header for the same cursor in RFC-5988 form — useful if your client follows rel="next" automatically.

DELETE /api/tests/:id — cancel a pending test

Only works while the test is in pending or running. Completed tests are immutable.

curl -sS -X DELETE https://check.live-direct-marketing.online/api/tests/t_01H9XABC4D5E6F7G8H \
  -H "Authorization: Bearer $IC"
HTTP/1.1 200 OK

{
  "data": { "id": "t_01H9XABC4D5E6F7G8H", "status": "cancelled" },
  "meta": { "creditsRefunded": 1 }
}

Cancel before the seeds receive the message and your credit is refunded automatically. After delivery the credit is consumed.

GET /api/me — quota and key info

Cheap introspection — useful for dashboards and "are we near the limit?" pre-flight checks.

curl -sS https://check.live-direct-marketing.online/api/me \
  -H "Authorization: Bearer $IC"
{
  "data": {
    "key":   { "id": "k_01H9XAAA...", "prefix": "ic_live_", "createdAt": "2026-04-11T10:00:00Z" },
    "plan":  "free",
    "quota": {
      "testsPerDay":       50,
      "testsPerMonth":     1000,
      "requestsPerMinute": 60,
      "concurrentStreams": 5
    },
    "usage": {
      "testsToday":    12,
      "testsThisMonth": 140,
      "creditsRemaining": 248
    }
  }
}

Using --fail and jq for pipelines

When you put cURL in a shell script, two flags are essential. --fail makes cURL exit non-zero on any 4xx/5xx (instead of happily printing the error body). --silent --show-error hides the progress meter but still shows network failures. Pipe through jq for field extraction:

set -euo pipefail

ID=$(curl --fail -sS -X POST https://check.live-direct-marketing.online/api/tests \
  -H "Authorization: Bearer $IC" \
  -H "Content-Type: application/json" \
  -d @payload.json \
  | jq -r .data.id)

while :; do
  STATUS=$(curl --fail -sS https://check.live-direct-marketing.online/api/tests/$ID \
    -H "Authorization: Bearer $IC" | jq -r .data.status)
  [[ "$STATUS" == "complete" ]] && break
  sleep 10
done

curl --fail -sS https://check.live-direct-marketing.online/api/tests/$ID \
  -H "Authorization: Bearer $IC" | jq .data.summary

That is a full CI check in twelve lines of bash. Drop it into a GitHub Action step and you have a pre-deploy deliverability gate.

Saving output to a file

Two common patterns. -o result.json writes the body to a file; -D headers.txt dumps headers separately. Combine them to archive full request/response pairs when reporting bugs:

curl -sS \
  -D headers.txt \
  -o body.json \
  https://check.live-direct-marketing.online/api/tests/t_01H9XABC4D5E6F7G8H \
  -H "Authorization: Bearer $IC"

# Then:
head -1 headers.txt       # HTTP/1.1 200 OK
jq .meta.requestId body.json
When you open a support ticket

Include the meta.requestId from the response, a timestamp, and your cURL command with -v. With those three, we can find your exact request in our logs in under a minute. Without them, expect a day of back-and-forth.

Frequently asked questions

Does the API accept application/x-www-form-urlencoded?

No. Every write endpoint is JSON-only. Pass Content-Type: application/json and a JSON body. We reject form-encoded writes with 415 Unsupported Media Type — the response body explains what to do.

How do I test against a staging environment?

Use a key prefixed with ic_test_ instead of ic_live_. Staging reuses the same endpoints but returns deterministic fake seed results — handy for integration tests where you do not want to burn real credits or wait 90 seconds per run.

Why does --include (-i) sometimes break my jq pipeline?

Because -i prepends HTTP headers to the output and jq tries to parse them as JSON. Use -D headers.txt to dump headers to a separate file, then pipe only the body to jq.

Can I use HTTP/2 or HTTP/3?

Yes. The API serves HTTP/2 by default and HTTP/3 when your cURL build supports QUIC. Add --http2 or --http3 to force a specific version for debugging. It makes no functional difference, but HTTP/3 is measurably faster on long SSE streams from high-latency regions.
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