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.
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/jsonThe 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.summaryThat 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.jsonInclude 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.