API Reference · Applications
Complete Step
Complete a wizard step and move on
/v1/applications/{application_id}/steps/{step}/completecomplete_stepOnly the user (or their agent) moves the wizard forward; background work never does. Works for the current step once every required item in its requirements is met, and for an earlier step marked attention once it's fixed (that step's checks are re-run live). Paid steps need an account. 409 step_not_ready lists what's missing; 409 step_locked when an earlier step comes first. Completing an already completed step returns the application unchanged.
cURL example
curl -X POST "https://api.verifiedinbox.ai/v1/applications/0192a5e0-1234-7000-8000-000000000001/steps/domain/complete" \
-H "VI-Guest-Token: vi_guest_YOUR_TOKEN"Parameters
| Parameter | Type | Description |
|---|---|---|
application_idpathrequired | string (uuid) | Application id. |
steppathrequired | string | Wizard step, e.g. `domain`, `email-security`, `dns`. |
VI-Environmentheader | string | `live` (default) or `test`. Used for anonymous callers and OAuth access tokens; API keys and web sessions carry their own environment. |
Response
| Field | Type | Description |
|---|---|---|
backgroundrequired | BackgroundWork[] | Active long-running work plus anything finished in the last 10 minutes. Nested fields (6)
|
brand_namerequired | string | Display-name guess (website title or domain label). |
contact_emailrequired | string | null | — |
created_atrequired | string (date-time) | — |
current_steprequired | string | Where to work now: the first step needing attention, else the first step the user hasn't completed. Allowed: |
domainrequired | string | Normalized ASCII (punycode) domain. |
domain_displayrequired | string | Unicode form of the domain. |
domain_statusrequired | string | Whether the domain is registered and can have its own logo (`unknown` while checking). Allowed: |
email_usagerequired | string | null | How email is used on the domain, as told by the customer (null until answered). Allowed: |
environmentrequired | string | — Allowed: |
idrequired | string (uuid) | — |
next_actionsrequired | NextAction[] | What to do next (for people and agents). Nested fields (9)
|
organizational_domainrequired | string | Registrable domain (e.g. `acme.com` for `news.acme.com`). |
outcomesrequired | Outcomes | Separate outcomes — never collapsed into one "verified" flag. Nested fields (10)
|
ownerrequired | ApplicationOwner | — |
productrequired | string | null | Chosen product, else the recommended one. Allowed: |
product_selectedrequired | string | null | Product explicitly chosen by the customer. Allowed: |
recommended_productrequired | string | null | From eligibility; null until assessed. Allowed: |
stepsrequired | Step[] | The 11 wizard steps, in order. Nested fields (8)
|
updated_atrequired | string (date-time) | — |
versionrequired | integer | Optimistic-concurrency version; send as `If-Match`. |
web_urlrequired | string | Deep link to the current step in the web app. |
{
"background": [
{
"kind": "domain_scan",
"message": "Everything checks out.",
"next_run_at": "2026-10-31T12:00:00Z",
"state": "string",
"status": "pending",
"updated_at": "2026-10-31T12:00:00Z"
}
],
"brand_name": "string",
"contact_email": "string",
"created_at": "2026-10-31T12:00:00Z",
"current_step": "domain",
"domain": "acme.com",
"domain_display": "string",
"domain_status": "unknown",
"email_usage": "none",
"environment": "live",
"id": "0192a5e0-1234-7000-8000-000000000001",
"next_actions": [
{
"api": {
"method": "string",
"path": "string"
},
"description": "string",
"kind": "string",
"mcp_tool": "string",
"requires_auth": true,
"requires_payment": true,
"step": "domain",
"title": "string",
"url": "https://verifiedinbox.ai/verify/0192a5e0-1234-7000-8000-000000000001/domain"
}
],
"organizational_domain": "string",
"outcomes": {
"bimi": "not_published",
"business": "not_started",
"certificate": "not_ordered",
"dmarc_rollout": "missing",
"eligibility": "unknown",
"inbox_display": "not_observed",
"logo": "missing",
"ownership": "pending",
"payment": "unpaid",
"trademark": "not_started"
},
"owner": {
"type": "guest"
},
"product": "vmc",
"product_selected": "vmc",
"recommended_product": "vmc",
"steps": [
{
"completed_at": "2026-10-31T12:00:00Z",
"paid": true,
"phase": "check",
"requirements": [],
"slug": "domain",
"status": "locked",
"summary": "string",
"title": "string"
}
],
"updated_at": "2026-10-31T12:00:00Z",
"version": 1,
"web_url": "https://verifiedinbox.ai/verify/0192a5e0-1234-7000-8000-000000000001/domain"
}Other responses & possible errors
Expand a status code below to see the error code, description, and example error payload.
400 (invalid_request)`invalid_request` — the request is malformed.
`invalid_request` — the request is malformed.
{
"error": {
"code": "invalid_request",
"message": "Please provide a valid domain name."
}
}401 (unauthenticated)`unauthenticated` — sign in / send a valid credential. `next_action.kind = sign_in`.
`unauthenticated` — sign in / send a valid credential. `next_action.kind = sign_in`.
{
"error": {
"code": "unauthenticated",
"message": "Sign in or provide an API key to continue.",
"next_action": {
"kind": "sign_in",
"title": "Sign in or create an account",
"url": "/login"
}
}
}404 (not_found)`not_found` — doesn't exist or isn't accessible to you (never 403).
`not_found` — doesn't exist or isn't accessible to you (never 403).
{
"error": {
"code": "not_found",
"message": "We couldn't find that resource."
}
}409 (version_conflict)Not ready (`step_not_ready`, `details.missing`) or not available yet (`step_locked`).
Not ready (`step_not_ready`, `details.missing`) or not available yet (`step_locked`).
{
"error": {
"code": "version_conflict",
"message": "This application was updated elsewhere. Refresh and try again."
}
}422 (unprocessable)`unprocessable` / `blocked_provider` — understood but can't be done (plain-English reason).
`unprocessable` / `blocked_provider` — understood but can't be done (plain-English reason).
{
"error": {
"code": "unprocessable",
"message": "Shared mailbox providers like gmail.com cannot be verified."
}
}429 (rate_limited)`rate_limited` — retry after `Retry-After` seconds (`details.retry_after_seconds`). `limit_reached` — a quota is used up; `details.limit` names it and `next_action` offers support.
`rate_limited` — retry after `Retry-After` seconds (`details.retry_after_seconds`). `limit_reached` — a quota is used up; `details.limit` names it and `next_action` offers support.
{
"error": {
"code": "rate_limited",
"message": "Too many requests. Please wait a moment and try again."
}
}