Contents12 endpoints

API reference

Seven layers, behind one header.

12 endpoints over HTTP and JSON. Verify a single address while a form is still open, or push a CSV through the same pipeline and collect three sheets when it finishes. Every page below is generated from this engine's own OpenAPI document, which you can also read as JSON.

Your first call

1 Create a key

In Settings. It is shown once and stored hashed, so keep it where your other secrets live.

2 Send one address

A POST with a JSON body of one field. Nothing else is required, and every option defaults to what this engine is configured to do.

3 Read status, then sub_status

The verdict, and the reason under it. settled_at_layer tells you which of the seven layers produced the answer.

Full reference for this endpoint
Request
curl -X POST https://validrow.inboxrow.com/v1/verify \
  -H "X-API-Key: $VALIDROW_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "john.doe@gmail.com"
  }'
import os
import requests

KEY = os.environ["VALIDROW_KEY"]

r = requests.post(
    "https://validrow.inboxrow.com/v1/verify",
    headers={"X-API-Key": KEY},
    json={
        "email": "john.doe@gmail.com",
    },
)
r.raise_for_status()
print(r.json())
const key = process.env.VALIDROW_KEY

const res = await fetch("https://validrow.inboxrow.com/v1/verify", {
  method: "POST",
  headers: {
    "X-API-Key": key,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "email": "john.doe@gmail.com"
  }),
})

const data = await res.json()
Response200
{
  "email": "john@gmial.com",
  "status": "undeliverable",
  "sub_status": "no_mx",
  "score": 4,
  "normalized_email": "john@gmial.com",
  "dedupe_key": "john@gmial.com",
  "domain": "gmial.com",
  "suggested_correction": "john@gmail.com",
  "is_disposable": false,
  "is_role": false,
  "is_free": false,
  "is_catch_all": false,
  "mx_found": false,
  "tags": [
    "typo_suspected"
  ],
  "checks": {
    "mx": "none",
    "normalize": "ok",
    "syntax": "ok",
    "typo": "gmial.com -> gmail.com"
  }
}
Base URL

Every path below hangs off https://validrow.inboxrow.com. There is no other host: the engine that answers the API is the engine that serves this page.

Authentication

Send your key as X-API-Key, or as Authorization: Bearer for clients that make that easier. Create one in Settings; it is shown once and stored hashed, so a lost key is replaced rather than recovered.

Rate limits

60 requests a minute per key on the endpoints that cost a network call: verify, upload and job creation. A request over the limit is refused with 429 rather than queued.

Upload size

A CSV up to 100 MB. The cap is enforced while the body is being read, not from the Content-Length header, so a chunked upload cannot talk its way past it.

The four verdicts

Every answer this API gives rolls up to one of these. Unknown is a real answer and is never rounded up to Deliverable, so a client that treats it as a third state rather than a failure gets the most out of the engine.

deliverable

The mailbox was probed and the receiving server answered for it.

risky

Real, but not a clean send. A role account, or a catch-all domain whose acceptance settles nothing.

unknown

Greylisting, a timeout, or a provider that will not answer honestly. Retried on a schedule, and never rounded up to Deliverable.

undeliverable

Invalid syntax, no MX, a disposable domain, or a mailbox the server rejected outright.

01verify

One address, checked now

Runs the full pipeline on a single address and answers on the same request. Use it while a form is still open; use the file pipeline below for anything larger than a form.

POST/v1/verify

Verify

Validate a single address in real time. Runs the (blocking, DNS-touching) engine in a threadpool so the event loop stays free.

Request body · application/json

FieldTypeDescription
emailreq string The address to verify. Parsed, normalised and probed as sent.
check_dnsopt boolean Override the engine's DNS setting for this call. With DNS off, nothing past layer 3 can run and the verdict comes back Unknown.
check_smtpopt boolean Override the engine's SMTP setting for this call. With the probe off, a deliverable-looking address is still reported Unknown rather than guessed at.

Response · 200

FieldTypeDescription
emailreq string The address exactly as it was sent.
statusreq string The verdict: deliverable, risky, unknown or undeliverable.
sub_statusreq string The reason under the verdict, such as no_mx, role_account or catch_all.
scorereq integer Confidence in the verdict, 0 to 100.
normalized_emailopt string The address with provider-specific spelling collapsed: Gmail dots and plus tags removed, case folded.
dedupe_keyopt string The key two spellings of one mailbox share. Count this, not the address, to count people.
domainopt string The domain part, lower-cased.
suggested_correctionopt string A likely intended address when the domain looks misspelled. A suggestion, never an automatic substitution.
is_disposablereq boolean The domain is on the vendored disposable list.
is_rolereq boolean The local part reaches a desk rather than a person.
is_freereq boolean The domain is a free consumer provider.
is_catch_allreq boolean The domain accepts every recipient, so its acceptance of this one proves nothing.
mx_foundreq boolean The domain published usable MX records.
tagsreq string[] Flags raised along the way, as a list.
checksreq object One entry per layer that ran, in order, with what it returned. This is the trace behind the verdict.
Request
curl -X POST https://validrow.inboxrow.com/v1/verify \
  -H "X-API-Key: $VALIDROW_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "john.doe@gmail.com"
  }'
import os
import requests

KEY = os.environ["VALIDROW_KEY"]

r = requests.post(
    "https://validrow.inboxrow.com/v1/verify",
    headers={"X-API-Key": KEY},
    json={
        "email": "john.doe@gmail.com",
    },
)
r.raise_for_status()
print(r.json())
const key = process.env.VALIDROW_KEY

const res = await fetch("https://validrow.inboxrow.com/v1/verify", {
  method: "POST",
  headers: {
    "X-API-Key": key,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "email": "john.doe@gmail.com"
  }),
})

const data = await res.json()
Response200
{
  "email": "john@gmial.com",
  "status": "undeliverable",
  "sub_status": "no_mx",
  "score": 4,
  "normalized_email": "john@gmial.com",
  "dedupe_key": "john@gmial.com",
  "domain": "gmial.com",
  "suggested_correction": "john@gmail.com",
  "is_disposable": false,
  "is_role": false,
  "is_free": false,
  "is_catch_all": false,
  "mx_found": false,
  "tags": [
    "typo_suspected"
  ],
  "checks": {
    "mx": "none",
    "normalize": "ok",
    "syntax": "ok",
    "typo": "gmial.com -> gmail.com"
  }
}

02files

Uploading a list

A bulk run is two calls: upload the CSV, then start a job against the file id you get back. The upload answers with the header row and a guess at which column holds the address, so a client can confirm the mapping instead of asking for it blind.

POST/v1/files

Upload file

Store an uploaded CSV and return detected columns for mapping.

Request body · multipart/form-data

FieldTypeDescription
filereq string

Response · 200

FieldTypeDescription
file_idreq string The storage key to pass to POST /v1/jobs.
filenamereq string The name the file was uploaded under.
detectionreq ColumnDetection What the header sniffer found, for mapping.
detection.columnsreq string[] The header row, in file order.
detection.sample_rowsreq object[] The first few rows, for confirming the mapping.
detection.guessed_emailopt string The column that most likely holds the address.
detection.guessed_first_nameopt string A likely first-name column.
detection.guessed_last_nameopt string A likely last-name column.
detection.delimiterreq string The delimiter found in the file. The output is written back with this one.
Request
curl -X POST https://validrow.inboxrow.com/v1/files \
  -H "X-API-Key: $VALIDROW_KEY" \
  -F "file=@list.csv"
import os
import requests

KEY = os.environ["VALIDROW_KEY"]

r = requests.post(
    "https://validrow.inboxrow.com/v1/files",
    headers={"X-API-Key": KEY},
    files={"file": open("list.csv", "rb")},
)
r.raise_for_status()
print(r.json())
const key = process.env.VALIDROW_KEY

const form = new FormData()
form.append("file", file, "list.csv")

const res = await fetch("https://validrow.inboxrow.com/v1/files", {
  method: "POST",
  headers: { "X-API-Key": key },
  body: form,
})

const data = await res.json()
Response200
{
  "file_id": "f_8s21kd_list.csv",
  "filename": "list.csv",
  "detection": {
    "columns": [
      "email",
      "company",
      "signed_up"
    ],
    "delimiter": ",",
    "guessed_email": "email",
    "sample_rows": [
      {
        "company": "Acme",
        "email": "jane.doe@acme.io",
        "signed_up": "2026-01-14"
      }
    ]
  }
}
GET/v1/files/{key}/raw

Download raw

Serve a stored object (local-dev stand-in for a presigned URL).

Parameters

NameInDescription
keyreq path · string
Request
curl -X GET https://validrow.inboxrow.com/v1/files/{key}/raw \
  -H "X-API-Key: $VALIDROW_KEY"
import os
import requests

KEY = os.environ["VALIDROW_KEY"]

r = requests.get(
    "https://validrow.inboxrow.com/v1/files/{key}/raw",
    headers={"X-API-Key": KEY},
)
r.raise_for_status()
print(r.json())
const key = process.env.VALIDROW_KEY

const res = await fetch("https://validrow.inboxrow.com/v1/files/{key}/raw", {
  method: "GET",
  headers: {
    "X-API-Key": key,
  },
})

const data = await res.json()
Response200

A streamed body, not JSON. The request above writes it to a file.

03jobs

Running and collecting

A job is created, worked through in the background, and downloaded as three CSV segments. Poll the job or give it a webhook.

GET/v1/jobs

List jobs

Every run this workspace has done, newest first.

Response · 200 · a list of these

FieldTypeDescription
idreq string The job id, used on every other job route.
seqopt integer This workspace's own run number. Defaults to 0.
filenamereq string The file the run was started from.
statusreq string queued, running, done or failed.
list_typeopt string The list this run belongs to. Defaults to "Imports".
countsreq object of integer Rows settled, keyed by verdict.
erroropt string Why the run failed, when it did.
outputsreq string[] The segments ready to download: cleaned, valid, removed.
mappingopt object The column mapping the run was started with.
phaseopt string Which stage of the run is executing. Defaults to "queued".
processedopt integer Rows settled so far. Defaults to 0.
totalopt integer Rows in the file. Defaults to 0.
domains_totalopt integer Distinct domains in the file. Defaults to 0.
progressopt number Fraction complete, 0 to 1. Defaults to 0.0.
created_atopt number Unix time the job was accepted. Defaults to 0.0.
started_atopt number Unix time work began.
finished_atopt number Unix time work ended.
durationopt number Seconds the run took.
Request
curl -X GET https://validrow.inboxrow.com/v1/jobs \
  -H "X-API-Key: $VALIDROW_KEY"
import os
import requests

KEY = os.environ["VALIDROW_KEY"]

r = requests.get(
    "https://validrow.inboxrow.com/v1/jobs",
    headers={"X-API-Key": KEY},
)
r.raise_for_status()
print(r.json())
const key = process.env.VALIDROW_KEY

const res = await fetch("https://validrow.inboxrow.com/v1/jobs", {
  method: "GET",
  headers: {
    "X-API-Key": key,
  },
})

const data = await res.json()
Response200
[
  {
    "id": "j_4c19be",
    "seq": 12,
    "filename": "list.csv",
    "status": "running",
    "list_type": "Cold outreach",
    "counts": {
      "deliverable": 1840,
      "risky": 402,
      "undeliverable": 297,
      "unknown": 311
    },
    "outputs": [],
    "mapping": {
      "email": "email"
    },
    "phase": "smtp",
    "processed": 2850,
    "total": 4812,
    "domains_total": 731,
    "progress": 0.59,
    "created_at": 1788000000.0,
    "started_at": 1788000004.0
  }
]
POST/v1/jobs

Create job

Start a run against an uploaded file. Answers immediately with a queued job rather than holding the connection open for the length of the run: a million rows is not a request. Poll the job, or give it a webhook and be told once. Returns 404 if the file_id is not in this workspace, and 422 if list_type is not one this engine knows.

Request body · application/json

FieldTypeDescription
file_idreq string A file_id returned by POST /v1/files.
mappingreq ColumnMappingIn Which column holds the address.
mapping.emailreq string The column holding the address. The only mapping the engine needs; every other column is carried through untouched.
mapping.first_nameopt string Optional first-name column.
mapping.last_nameopt string Optional last-name column.
webhook_urlopt string Called once when the run finishes. Signed with HMAC-SHA256 when a webhook secret is configured.
filenameopt string The name to show in History. Defaults to the storage key.
list_typeopt string The list this run belongs to, for slicing the workspace.

Response · 200

FieldTypeDescription
idreq string The job id, used on every other job route.
seqopt integer This workspace's own run number. Defaults to 0.
filenamereq string The file the run was started from.
statusreq string queued, running, done or failed.
list_typeopt string The list this run belongs to. Defaults to "Imports".
countsreq object of integer Rows settled, keyed by verdict.
erroropt string Why the run failed, when it did.
outputsreq string[] The segments ready to download: cleaned, valid, removed.
mappingopt object The column mapping the run was started with.
phaseopt string Which stage of the run is executing. Defaults to "queued".
processedopt integer Rows settled so far. Defaults to 0.
totalopt integer Rows in the file. Defaults to 0.
domains_totalopt integer Distinct domains in the file. Defaults to 0.
progressopt number Fraction complete, 0 to 1. Defaults to 0.0.
created_atopt number Unix time the job was accepted. Defaults to 0.0.
started_atopt number Unix time work began.
finished_atopt number Unix time work ended.
durationopt number Seconds the run took.
Request
curl -X POST https://validrow.inboxrow.com/v1/jobs \
  -H "X-API-Key: $VALIDROW_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "file_id": "f_8s21kd_list.csv",
    "mapping": {
      "email": "email"
    },
    "filename": "list.csv"
  }'
import os
import requests

KEY = os.environ["VALIDROW_KEY"]

r = requests.post(
    "https://validrow.inboxrow.com/v1/jobs",
    headers={"X-API-Key": KEY},
    json={
        "file_id": "f_8s21kd_list.csv",
        "mapping": {
            "email": "email",
        },
        "filename": "list.csv",
    },
)
r.raise_for_status()
print(r.json())
const key = process.env.VALIDROW_KEY

const res = await fetch("https://validrow.inboxrow.com/v1/jobs", {
  method: "POST",
  headers: {
    "X-API-Key": key,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "file_id": "f_8s21kd_list.csv",
    "mapping": {
      "email": "email"
    },
    "filename": "list.csv"
  }),
})

const data = await res.json()
Response200
{
  "id": "j_4c19be",
  "seq": 12,
  "filename": "list.csv",
  "status": "running",
  "list_type": "Cold outreach",
  "counts": {
    "deliverable": 1840,
    "risky": 402,
    "undeliverable": 297,
    "unknown": 311
  },
  "outputs": [],
  "mapping": {
    "email": "email"
  },
  "phase": "smtp",
  "processed": 2850,
  "total": 4812,
  "domains_total": 731,
  "progress": 0.59,
  "created_at": 1788000000.0,
  "started_at": 1788000004.0
}
GET/v1/jobs/{job_id}

Get job

One run, with its live progress. Cheap enough to poll: `processed`, `total` and `phase` come from the job record rather than from the rows, so a progress bar drawn from them is truthful without costing a scan.

Parameters

NameInDescription
job_idreq path · string

Response · 200

FieldTypeDescription
idreq string The job id, used on every other job route.
seqopt integer This workspace's own run number. Defaults to 0.
filenamereq string The file the run was started from.
statusreq string queued, running, done or failed.
list_typeopt string The list this run belongs to. Defaults to "Imports".
countsreq object of integer Rows settled, keyed by verdict.
erroropt string Why the run failed, when it did.
outputsreq string[] The segments ready to download: cleaned, valid, removed.
mappingopt object The column mapping the run was started with.
phaseopt string Which stage of the run is executing. Defaults to "queued".
processedopt integer Rows settled so far. Defaults to 0.
totalopt integer Rows in the file. Defaults to 0.
domains_totalopt integer Distinct domains in the file. Defaults to 0.
progressopt number Fraction complete, 0 to 1. Defaults to 0.0.
created_atopt number Unix time the job was accepted. Defaults to 0.0.
started_atopt number Unix time work began.
finished_atopt number Unix time work ended.
durationopt number Seconds the run took.
Request
curl -X GET https://validrow.inboxrow.com/v1/jobs/{job_id} \
  -H "X-API-Key: $VALIDROW_KEY"
import os
import requests

KEY = os.environ["VALIDROW_KEY"]

r = requests.get(
    "https://validrow.inboxrow.com/v1/jobs/{job_id}",
    headers={"X-API-Key": KEY},
)
r.raise_for_status()
print(r.json())
const key = process.env.VALIDROW_KEY

const res = await fetch("https://validrow.inboxrow.com/v1/jobs/{job_id}", {
  method: "GET",
  headers: {
    "X-API-Key": key,
  },
})

const data = await res.json()
Response200
{
  "id": "j_4c19be",
  "seq": 12,
  "filename": "list.csv",
  "status": "running",
  "list_type": "Cold outreach",
  "counts": {
    "deliverable": 1840,
    "risky": 402,
    "undeliverable": 297,
    "unknown": 311
  },
  "outputs": [],
  "mapping": {
    "email": "email"
  },
  "phase": "smtp",
  "processed": 2850,
  "total": 4812,
  "domains_total": 731,
  "progress": 0.59,
  "created_at": 1788000000.0,
  "started_at": 1788000004.0
}
DELETE/v1/jobs/{job_id}

Delete job

Delete a run and its cached outputs. The validated addresses stay in the workspace by default — they are facts about mailboxes, not artefacts of the run that discovered them. Pass ``keep_addresses=false`` to drop those too.

Parameters

NameInDescription
job_idreq path · string
keep_addressesopt query · boolean Defaults to true.

Response · 204

Successful Response

Request
curl -X DELETE https://validrow.inboxrow.com/v1/jobs/{job_id} \
  -H "X-API-Key: $VALIDROW_KEY"
import os
import requests

KEY = os.environ["VALIDROW_KEY"]

r = requests.delete(
    "https://validrow.inboxrow.com/v1/jobs/{job_id}",
    headers={"X-API-Key": KEY},
)
r.raise_for_status()
print(r.status_code)
const key = process.env.VALIDROW_KEY

const res = await fetch("https://validrow.inboxrow.com/v1/jobs/{job_id}", {
  method: "DELETE",
  headers: {
    "X-API-Key": key,
  },
})

console.log(res.status)
Response204

A streamed body, not JSON. The request above writes it to a file.

GET/v1/jobs/{job_id}/download

Download job

Stream one of the three segments a finished run produces, as CSV. `cleaned` is your file back: every row, every column, with the verdict appended. `valid` is the rows worth sending to. `removed` is what came out, with the layer and the reason each row came out. Returns 409 while the run is still working, because a segment that is not written yet is not an empty one.

Parameters

NameInDescription
job_idreq path · string
segmentopt query · string Defaults to "cleaned".
Request
curl -X GET https://validrow.inboxrow.com/v1/jobs/{job_id}/download \
  -H "X-API-Key: $VALIDROW_KEY"
import os
import requests

KEY = os.environ["VALIDROW_KEY"]

r = requests.get(
    "https://validrow.inboxrow.com/v1/jobs/{job_id}/download",
    headers={"X-API-Key": KEY},
)
r.raise_for_status()
print(r.json())
const key = process.env.VALIDROW_KEY

const res = await fetch("https://validrow.inboxrow.com/v1/jobs/{job_id}/download", {
  method: "GET",
  headers: {
    "X-API-Key": key,
  },
})

const data = await res.json()
Response200

A streamed body, not JSON. The request above writes it to a file.

04workspace

The workspace read-model

Every address this workspace has ever validated, de-duplicated across runs. These endpoints answer questions that span jobs, which is why they read the workspace rather than a run's output file.

GET/v1/addresses

List addresses

Addresses across every run in this workspace, de-duplicated. One row per mailbox rather than one per appearance, so an address that arrived in three lists is counted once and carries the most recent verdict it was given.

Parameters

NameInDescription
verdictopt query · string[]
qopt query · string
list_typeopt query · string
sortopt query · string Defaults to "recent".
pageopt query · integer Defaults to 1.
sizeopt query · integer Defaults to 50.

Response · 200

FieldTypeDescription
rowsreq AddressOut[] This page of addresses.
totalreq integer Addresses matching the filter, all pages.
pagereq integer The 1-based page returned.
sizereq integer Rows per page.
Request
curl -X GET https://validrow.inboxrow.com/v1/addresses \
  -H "X-API-Key: $VALIDROW_KEY"
import os
import requests

KEY = os.environ["VALIDROW_KEY"]

r = requests.get(
    "https://validrow.inboxrow.com/v1/addresses",
    headers={"X-API-Key": KEY},
)
r.raise_for_status()
print(r.json())
const key = process.env.VALIDROW_KEY

const res = await fetch("https://validrow.inboxrow.com/v1/addresses", {
  method: "GET",
  headers: {
    "X-API-Key": key,
  },
})

const data = await res.json()
Response200
{
  "rows": [
    {
      "checked_at": 1788000412.0,
      "domain": "acme.io",
      "email": "jane.doe@acme.io",
      "is_catch_all": false,
      "is_disposable": false,
      "is_free": false,
      "is_role": false,
      "job_filename": "list.csv",
      "job_id": "j_4c19be",
      "list_type": "Cold outreach",
      "mx_found": true,
      "score": 96,
      "settled_at": 6,
      "status": "valid",
      "sub_status": "mailbox_confirmed",
      "verdict": "deliverable"
    }
  ],
  "total": 4812,
  "page": 1,
  "size": 50
}
GET/v1/analytics

Analytics

Everything the Analytics screen reports, in one round-trip.

Request
curl -X GET https://validrow.inboxrow.com/v1/analytics \
  -H "X-API-Key: $VALIDROW_KEY"
import os
import requests

KEY = os.environ["VALIDROW_KEY"]

r = requests.get(
    "https://validrow.inboxrow.com/v1/analytics",
    headers={"X-API-Key": KEY},
)
r.raise_for_status()
print(r.json())
const key = process.env.VALIDROW_KEY

const res = await fetch("https://validrow.inboxrow.com/v1/analytics", {
  method: "GET",
  headers: {
    "X-API-Key": key,
  },
})

const data = await res.json()
Response200
{}
POST/v1/exports

Export slice

Stream a filtered slice of the workspace as CSV.

Request body · application/json

FieldTypeDescription
verdictsopt string[] Any of the four primary verdicts. Empty means all of them.
searchopt string Substring match on the address or its domain.
list_typeopt string Restrict to one list.
presetopt string A slice defined by a sub-reason rather than a verdict: "catchall" or "disposable".
emailsopt string[] Only these addresses, for exporting a hand-picked selection.
columnsopt string "full" carries the verdict, sub-reason, score, MX and settling layer; "email" is one column. Defaults to "full".
require_mxopt boolean Drop rows whose domain has no MX. Defaults to false.
exclude_disposableopt boolean Drop disposable domains. Defaults to false.
Request
curl -X POST https://validrow.inboxrow.com/v1/exports \
  -H "X-API-Key: $VALIDROW_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "verdicts": [
      "undeliverable"
    ],
    "columns": "email",
    "exclude_disposable": true
  }'
import os
import requests

KEY = os.environ["VALIDROW_KEY"]

r = requests.post(
    "https://validrow.inboxrow.com/v1/exports",
    headers={"X-API-Key": KEY},
    json={
        "verdicts": ["undeliverable"],
        "columns": "email",
        "exclude_disposable": True,
    },
)
r.raise_for_status()
print(r.json())
const key = process.env.VALIDROW_KEY

const res = await fetch("https://validrow.inboxrow.com/v1/exports", {
  method: "POST",
  headers: {
    "X-API-Key": key,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "verdicts": [
      "undeliverable"
    ],
    "columns": "email",
    "exclude_disposable": true
  }),
})

const data = await res.json()
Response200

A streamed body, not JSON. The request above writes it to a file.

05meta

Operations

What a load balancer and a status page need. Reachable without credentials, always.

GET/health

Health

Whether this engine is serving, and which layers it has switched on. Reachable without credentials, because a load balancer cannot log in. The two flags matter to a caller: with DNS off nothing past layer 3 can run, and with the probe off a deliverable-looking address still comes back Unknown.

Response · 200

FieldTypeDescription
statusreq string "ok" while the process is serving.
versionreq string The engine version answering.
smtp_enabledreq boolean Whether the mailbox probe is running on this engine.
dns_enabledreq boolean Whether DNS and MX resolution is running on this engine.
Request
curl -X GET https://validrow.inboxrow.com/health \
  -H "X-API-Key: $VALIDROW_KEY"
import os
import requests

KEY = os.environ["VALIDROW_KEY"]

r = requests.get(
    "https://validrow.inboxrow.com/health",
    headers={"X-API-Key": KEY},
)
r.raise_for_status()
print(r.json())
const key = process.env.VALIDROW_KEY

const res = await fetch("https://validrow.inboxrow.com/health", {
  method: "GET",
  headers: {
    "X-API-Key": key,
  },
})

const data = await res.json()
Response200
{
  "status": "ok",
  "version": "0.1.0",
  "smtp_enabled": true,
  "dns_enabled": true
}

06Errors

Every failure names itself.

A failed call returns the status below and a JSON body with a detail field saying what went wrong. A 422 also names the field that failed and why, so a client can report it rather than retry it.

StatusWhat it means here
400 The request was malformed.
401 No credential, or one this engine does not recognise. Only returned when the engine requires auth.
404 No such file, job or address in this workspace.
409 The job exists but the segment you asked for is not written yet.
413 The upload is over this engine's size cap.
422 The body parsed but failed validation. The response names the field and what was wrong with it.
429 Over the rate limit.