Basics
| Item | Value |
|---|---|
| Base URL | https://lvndr.toolfora.com/api/v1 |
| Auth | Authorization: Bearer lv_… (or x-api-key: lv_…) with a key from Settings > Agents & API, or an OAuth access token |
| Format | JSON in, JSON out. Every response has Cache-Control: no-store. |
| Contract | OpenAPI 3.1 at GET /api/v1/openapi.json, no auth needed |
| Plan | Included on every LVNDR plan and free on development stores. A store without an active plan gets 402. |
A key is shown once when created; only a hash is stored. A key that is unknown, revoked or expired gets 401. Uninstalling the app revokes every key.
Scopes
A new key gets read and undo. Rollback and export are opt-in when the key is made. An OAuth client that asks for no scope gets the same two.
| Scope | Allows |
|---|---|
| read | Every GET, including job progress; marking a restore point; starting and ending runs |
| undo | Undoing one change, a batch or a run; dismissing alerts; a run started with it captures every unattributed change |
| rollback | Rolling back to a restore point |
| export | Downloading the change log |
export LVNDR_API_KEY=lv_...
export LVNDR=https://lvndr.toolfora.com/api/v1Routes
A route needs the scope in the table. A key without it gets 403 insufficient_scope. GET routes count against the read limit, POST routes against the write limit. Every write to the store needs the planHash of a dry run or preview: dry-run first, show the plan, then send the hash back.
| Method and path | Scope | What it does |
|---|---|---|
| GET /api/v1/me | read | The key, its scopes and expiry, and the plan |
| GET /api/v1/status | read | Plan, tracked counts, pipeline health |
| GET /api/v1/changes | read | Changes, newest first, paged |
| GET /api/v1/changes/:id | read | One change with its diff |
| POST /api/v1/changes/:id/undo | undo | Preview (default) or run the undo of one change; the run needs the preview's planHash |
| GET /api/v1/records/:record/history | read | One record: latest state, versions, changes |
| GET /api/v1/batches/:id | read | Everything one actor did around a change |
| POST /api/v1/batches/:id/undo | undo | Preview (default), or queue the undo of a batch with the preview's planHash (202 with a job) |
| GET /api/v1/restore-points | read | The newest 50 restore points |
| POST /api/v1/restore-points | read | Mark a restore point now |
| GET /api/v1/restore-points/:id | read | One point and how many changes came after it |
| GET /api/v1/restore-points/:id/preview | read | Dry run of a rollback |
| POST /api/v1/restore-points/:id/rollback | rollback | Queue the undo of everything after the point (202 with a job); needs confirm: true and the preview's planHash |
| GET /api/v1/alerts | read | Anomaly alerts |
| POST /api/v1/alerts/:id/dismiss | undo | Dismiss an alert |
| POST /api/v1/runs | read | Start an agent run (with a restore point unless markRestorePoint is false) |
| GET /api/v1/runs | read | Agent runs, newest first |
| GET /api/v1/runs/:id | read | One run with its changes, attributedThrough and pendingDeliveries |
| POST /api/v1/runs/:id/end | read | End a run |
| POST /api/v1/runs/:id/undo | undo | Preview (default), or queue the undo of a whole run with the preview's planHash (202 with a job) |
| GET /api/v1/jobs/:id | read | One background undo job and its progress |
| GET /api/v1/export | export | Download the change log; audited |
| GET /api/v1/openapi.json | none | The OpenAPI document |
A path that exists with another method gets 405 and an Allow header. An unknown path gets 404 and does not count against the rate limit. HEAD works on every GET route. A body field a route does not take gets 400 unknown_field naming it, so a typo such as plan_hash cannot silently skip a check. Bodies over 64 KB get 413 payload_too_large.
Headers
| Header | Direction | Meaning |
|---|---|---|
| Authorization or x-api-key | request | The key |
| Idempotency-Key | request (POST) | Makes a retried write safe; see below. Up to 255 characters. |
| X-Lvndr-Agent | request | The agent's name, up to 120 characters. Stored on every write and used as the run's agent when POST /runs has none. |
| X-Lvndr-Run-Id | request | The run a write belongs to. Must name a run on this store, else 400 unknown_run. |
| X-RateLimit-Limit | response | Requests per minute for this key and kind (read or write). Follows the plan; during early access (before managed billing) every store gets the top rate, 300 reads and 60 writes |
| X-RateLimit-Remaining | response | Requests left before the limit |
| Retry-After | response (429) | Seconds to wait |
| Idempotency-Key | response | Echoed when the request sent one |
| X-Lvndr-Rows | response (export) | Rows in the file |
Rate limits
Each key has two token buckets, one for reads (GET) and one for writes (POST). They refill continuously. Over the limit, the answer is 429 with Retry-After. The size follows the store's plan:
| Plan | Reads per minute | Writes per minute |
|---|---|---|
| Starter | 60 | 10 |
| Growth | 120 | 20 |
| Scale | 300 | 60 |
| Development store | 120 | 20 |
Until managed billing is on, every store gets the Scale numbers. The server can override all of them with LVNDR_RATE_READ and LVNDR_RATE_WRITE. MCP tool calls share the same buckets. Requests with a missing or wrong key are limited per IP address (30 a minute, then 429).
The buckets live in each server process. With one server that is exact; with several, a key can get up to that many times the limit.
Idempotency
Send Idempotency-Key on a POST and retry with the same key after a timeout. The first answer is stored for 24 hours and replayed, so the write happens once. Keys are per store.
| Case | Answer |
|---|---|
| Same key, same request | The stored answer, status and body |
| Same key, different body, agent or run id | 409 idempotency_key_reused |
| Same key while the first request is still running | 409 idempotency_key_in_progress; retry shortly |
| The first request failed with a 5xx | Nothing stored; a retry runs again |
| Key longer than 255 characters | 400 invalid_idempotency_key |
curl -X POST -H "Authorization: Bearer $LVNDR_API_KEY" -H "Content-Type: application/json" -H "Idempotency-Key: 7f0c2a" \
-d '{"dryRun": false, "planHash": "q3Xl0c2V4Zk9b1Rm"}' $LVNDR/changes/cm3abc/undoPagination
Lists that page return nextCursor. Pass it back unchanged as cursor for the next page; it is null on the last page. A cursor that cannot be read gets 400 invalid_cursor. Pages apply to changes, a record's history and a run's changes.
Change object
Lists and single changes share one shape.
{
"id": "cm3...",
"resourceType": "PRODUCT",
"resourceId": "gid://shopify/Product/123",
"resourceTitle": "The Minimal Snowboard",
"action": "update", // create | update | delete
"occurredAt": "2026-11-10T14:03:12.000Z",
"fields": "price (variant 456)", // or "new record" / "record removed"
"summary": "The price of one variant went from 885.95 to 750.", // null when summaries are off
"runId": null, // the agent run it belongs to
"actor": {
"tier": "exact", // exact | channel | inferred | unknown (no actor known: common for field edits)
"kind": "staff", // staff | app | shopify | unknown | agent
"name": "Joe Pace",
"appTitle": "Shopify Web",
"note": "Named by Shopify's admin event",
"label": "Joe Pace"
}
}actor.tier is unknown for many field edits: Shopify records no actor for them, and LVNDR shows “Not recorded” until it can make a labelled guess (inferred). Report it as unknown, never as a person. LVNDR's own undos are always exact with name lvndr undo.
GET /api/v1/me
Which store and key this is. Use it to check a key before anything else.
curl -H "Authorization: Bearer $LVNDR_API_KEY" $LVNDR/me{
"shop": "example.myshopify.com",
"key": { "id": "cm9k...", "label": "Claude Code", "scopes": ["read", "undo"], "expiresAt": "2027-02-11T09:00:00.000Z", "clientName": null },
"plan": { "handle": "scale", "label": "Scale" },
"limits": { "products": 20000, "retentionDays": 365, "alerts": true, "api": true, "apiRate": { "read": 300, "write": 60 }, "multiStore": true }
}Until managed billing is on, every store reports the Scale limits, labelled “Early access (free)”.
GET /api/v1/status
Plan, tracked counts and pipeline health.
curl -H "Authorization: Bearer $LVNDR_API_KEY" $LVNDR/status{
"shop": "example.myshopify.com",
"plan": { "handle": "scale", "products": 20000, "retentionDays": 365, "alerts": true, "api": true, "label": "Scale" },
"initialSyncAt": "2026-11-10T09:00:00.000Z",
"lastPolledAt": "2026-11-10T14:05:00.000Z",
"tracked": { "PRODUCT": 412, "COLLECTION": 18, "PAGE": 6, "BLOG": 1, "ARTICLE": 14, "MENU": 3, "THEME": 2, "METAFIELD_DEFINITION": 9 },
"deliveries": { "pending": 0, "failed": 0 }
}plan.products is null when unlimited.
GET /api/v1/changes
Changes, newest first.
| Query parameter | Meaning |
|---|---|
| since, until | ISO timestamps (2026-11-10T00:00:00Z); changes at or after, at or before |
| type | PRODUCT, COLLECTION, PAGE, BLOG, ARTICLE, MENU, THEME or METAFIELD_DEFINITION |
| action | create, update or delete |
| resourceId | One record: its Shopify gid (gid://shopify/Product/123) or the short form Product-123. |
| actor | Case-insensitive part of the staff, app or agent name |
| q | Case-insensitive part of the record title |
| hideUndos | 1 or true: leave out LVNDR's own undos |
| runId | Only changes tagged with this agent run |
| limit | 1 to 100, default 50 |
| cursor | nextCursor from the previous page |
curl -H "Authorization: Bearer $LVNDR_API_KEY" \
"$LVNDR/changes?since=2026-11-10T00:00:00Z&type=PRODUCT&limit=20"{ "changes": [ { ...change }, ... ], "nextCursor": "eyJ0Ijo...", "limit": 20 }GET /api/v1/changes/:id
One change with its full diff.
curl -H "Authorization: Bearer $LVNDR_API_KEY" $LVNDR/changes/cm3abc{
"change": {
...change,
"diff": [ { "path": "variants[ProductVariant/456].price", "before": "885.95", "after": "750.00" } ],
"beforeKnown": true
}
}POST /api/v1/changes/:id/undo
Preview or run the undo of one change. The default is a preview; nothing is written unless dryRun is false, and then only with the preview's planHash. When it runs, the record is snapshotted first, so the undo can itself be undone.
| Body field | Default | Meaning |
|---|---|---|
| dryRun | true | false writes to the store |
| includeConflicts | false | true also overwrites fields changed again since |
| planHash | none | Required when dryRun is false: the planHash the dry run returned. Missing is 400 plan_required; the write is refused with 409 plan_changed if the plan is no longer the same (the record changed since). |
| reason | none | Why, up to 500 characters. Stored with the undo and in the audit log. |
# preview
curl -X POST -H "Authorization: Bearer $LVNDR_API_KEY" -H "Content-Type: application/json" \
-d '{"dryRun": true}' $LVNDR/changes/cm3abc/undo
# run exactly what the preview showed
curl -X POST -H "Authorization: Bearer $LVNDR_API_KEY" -H "Content-Type: application/json" \
-d '{"dryRun": false, "planHash": "q3Xl0c2V4Zk9b1Rm", "reason": "price import went wrong"}' $LVNDR/changes/cm3abc/undo{
"plan": {
"mode": "fields", // fields | delete | recreate
"counts": { "ready": 1, "conflict": 0, "noop": 0, "unsupported": 0 },
"items": [
{ "path": "variants[ProductVariant/456].price", "status": "ready", "reason": null, "current": "750.00", "target": "885.95" }
]
},
"planHash": "q3Xl0c2V4Zk9b1Rm", // send back with the real run
"run": null // on a real run: { "id", "status": "done" | "partial" | "failed", "ops": [ { "op", "ok", "errors" } ] }
}A run is recorded in the change log as “LVNDR undo”, requested by api-key:<key id>, with the agent and run id from the headers.
GET /api/v1/records/:record/history
One record: its latest stored state, up to 50 versions and its changes, newest first. :record is Product-123 or a URL-encoded gid. Pages with cursor.
curl -H "Authorization: Bearer $LVNDR_API_KEY" $LVNDR/records/Product-123/history{
"record": { "resourceId": "gid://shopify/Product/123", "resourceType": "PRODUCT", "title": "The Minimal Snowboard", "deleted": false,
"latest": { "version": 7, "capturedAt": "...", "source": "sweep", "deleted": false, "fields": [ { "label": "Title", "value": "The Minimal Snowboard" }, ... ] } },
"versions": [ { "id": "...", "version": 7, "capturedAt": "...", "source": "sweep", "sourceUpdatedAt": "..." } ],
"changes": [ { ...change } ],
"nextCursor": null
}GET /api/v1/batches/:id
Everything the same actor did around a change with no gap over ten minutes, newest first. :id is any change in the batch.
curl -H "Authorization: Bearer $LVNDR_API_KEY" $LVNDR/batches/cm3abc{ "anchorId": "cm3abc", "actorLabel": "Joe Pace", "changes": [ { ...change }, ... ] }POST /api/v1/batches/:id/undo
Preview (the default) or undo the whole batch, newest first. Body: dryRun, planHash (required with dryRun: false), reason. A batch holds up to 200 changes. LVNDR's own undos in the batch are skipped.
The dry run plans the newest 50 changes and returns total, more (changes the undo covers that the preview did not plan) and planHash. With dryRun: false the undo is queued as a background job: the answer is 202 with the job (see GET /api/v1/jobs/:id below), or 409 plan_changed when the planHash sent no longer matches the batch.
curl -X POST -H "Authorization: Bearer $LVNDR_API_KEY" -H "Content-Type: application/json" -d '{"dryRun": true}' $LVNDR/batches/cm3abc/undo{
"anchorId": "cm3abc", "dryRun": true, "actorLabel": "price-bot",
"counts": { "planned": 12, "done": 0, "partial": 0, "failed": 0, "skipped": 1 },
"results": [ { "changeId": "...", "resourceTitle": "...", "action": "update", "status": "planned", "detail": "...", "undoRunId": null } ],
"total": 13, "more": 0, "remaining": 0, "planHash": "Zk9b1RmN8pA7wYsE"
}curl -X POST -H "Authorization: Bearer $LVNDR_API_KEY" -H "Content-Type: application/json" -d '{"dryRun": false, "planHash": "Zk9b1RmN8pA7wYsE"}' $LVNDR/batches/cm3abc/undo
# 202
{ "anchorId": "cm3abc", "actorLabel": "price-bot", "dryRun": false, "job": { "id": "cm9job...", "status": "queued", ... } }GET /api/v1/restore-points
The 50 most recent restore points.
curl -H "Authorization: Bearer $LVNDR_API_KEY" $LVNDR/restore-points{ "points": [ { "id": "cm3p1", "kind": "manual", "label": "before the import", "at": "2026-11-10T13:00:00.000Z", "createdBy": "api-key:cm9k...", "runId": null } ] }kind is manual, burst or sweep.
POST /api/v1/restore-points
Mark a restore point now. Needs only the read scope: marking never writes to the store. The label is optional and cut at 120 characters; a reason is stored in the audit log.
curl -X POST -H "Authorization: Bearer $LVNDR_API_KEY" -H "Content-Type: application/json" \
-d '{"label": "before the import"}' $LVNDR/restore-points{ "point": { "id": "cm3p2", "kind": "manual", "label": "before the import", "at": "2026-11-10T14:10:00.000Z", "createdBy": "api-key:cm9k...", "runId": null } }GET /api/v1/restore-points/:id
One point, with changesSince: how many changes came after it.
curl -H "Authorization: Bearer $LVNDR_API_KEY" $LVNDR/restore-points/cm3p2GET /api/v1/restore-points/:id/preview
What rolling back would do to each change after the point, for the first 50, without writing. total and remaining say how many there are beyond those. planHash identifies the set of changes; send it with the rollback.
curl -H "Authorization: Bearer $LVNDR_API_KEY" $LVNDR/restore-points/cm3p2/preview{ "preview": { "pointId": "cm3p2", "changes": [ ... ], "totals": { ... }, "total": 14, "previewed": 14, "remaining": 0, "limit": 50 },
"planHash": "N8pA7wYsE5uJhTgD" }POST /api/v1/restore-points/:id/rollback
Undo every change after the point, newest first, as a background job. Refused with 400 confirm_required unless the body has "confirm": true, and with 400 plan_required without the preview's planHash. This also reverts changes other people made after the point. It is refused with 409 plan_changed if changes arrived since the preview. One job covers up to 500 changes; if the finished job's remaining is above 0, preview and roll back again.
curl -X POST -H "Authorization: Bearer $LVNDR_API_KEY" -H "Content-Type: application/json" \
-d '{"confirm": true, "planHash": "N8pA7wYsE5uJhTgD", "reason": "bad import"}' $LVNDR/restore-points/cm3p2/rollback# 202
{ "pointId": "cm3p2", "job": { "id": "cm9job...", "kind": "rollback", "status": "queued", "total": 14, ... } }GET /api/v1/alerts
Anomaly alerts, newest first. status is open (default), dismissed or all; limit 1 to 100, default 50. An open alert becomes resolved when a batch, run or rollback undo that covers its burst finishes; resolved alerts are listed under all.
curl -H "Authorization: Bearer $LVNDR_API_KEY" "$LVNDR/alerts?status=all"{ "alerts": [ { "id": "cm9al...", "kind": "burst", "status": "open", "actorLabel": "price-bot", "count": 42,
"windowStart": "...", "windowEnd": "...", "anchorChangeId": "cm9ch...", "resourceTypes": ["PRODUCT"], "createdAt": "..." } ] }POST /api/v1/alerts/:id/dismiss
Mark an alert as seen. Needs the undo scope, so a read-only key cannot silence the alert its own burst raised. dismissed is false when it was not open (already dismissed or resolved).
curl -X POST -H "Authorization: Bearer $LVNDR_API_KEY" $LVNDR/alerts/cm9al/dismiss{ "alert": { ... }, "dismissed": true }POST /api/v1/runs
Start an agent run. Changes made while it is open are tagged with its id; see Running agents safely for the rules.
| Body field | Meaning |
|---|---|
| agent | Up to 120 characters. Defaults to X-Lvndr-Agent; one of the two is required. |
| task | What the run is for, up to 500 characters |
| clientId | Used only when it is the key's own OAuth client id; otherwise ignored, and captureNote says so |
| markRestorePoint | Default true: marks a restore point one second before the run. false skips it. |
Needs only the read scope. The answer says what the run will capture: all-unattributed when the key has the undo scope (every unknown or inferred change while the run is open, staff edits included), client for an OAuth token without undo (only its own client's changes), none for a Settings key without undo.
curl -X POST -H "Authorization: Bearer $LVNDR_API_KEY" -H "Content-Type: application/json" -H "X-Lvndr-Agent: Claude Code" \
-d '{"task": "Raise winter prices 10%"}' $LVNDR/runs{ "run": { "id": "cm9run...", "agent": "Claude Code", "task": "Raise winter prices 10%", "clientId": null,
"restorePointId": "cm9pt...", "startedAt": "...", "endedAt": null, "status": "open", "changeCount": 0 },
"capture": "all-unattributed",
"captureNote": "This run records every change Shopify left unattributed or LVNDR inferred while it is open (up to 24 h), staff edits included." }GET /api/v1/runs
Runs, newest first. open=1 for open runs only; limit 1 to 100, default 20.
curl -H "Authorization: Bearer $LVNDR_API_KEY" "$LVNDR/runs?open=1"{ "runs": [ { ...run } ] }GET /api/v1/runs/:id
One run with its restore point and its changes, newest first. limit 1 to 200 (default 50) and cursor page through them. attributedThrough is the time through which LVNDR's last completed attribution pass covered the store (null before the first), and pendingDeliveries counts Shopify deliveries not yet processed.
Changes are tagged within about 4 minutes; collection rules and SEO, menus, themes and metafield definitions come from a 10-minute check. After the last write, poll this route about every 20 seconds until attributedThrough is after that write and pendingDeliveries is 0, then review the changes.
curl -H "Authorization: Bearer $LVNDR_API_KEY" $LVNDR/runs/cm9run{ "run": { ...run, "restorePoint": { ...point } }, "changes": [ { ...change } ], "nextCursor": null,
"attributedThrough": "2026-11-13T10:06:00.000Z", "pendingDeliveries": 0 }POST /api/v1/runs/:id/end
Close a run. Later changes do not join it. Ending an ended run returns it unchanged.
curl -X POST -H "Authorization: Bearer $LVNDR_API_KEY" $LVNDR/runs/cm9run/end{ "run": { ...run, "status": "ended" } }POST /api/v1/runs/:id/undo
Preview (the default) or undo every change tagged with the run, newest first. Body: dryRun, planHash (required with dryRun: false), reason. The dry run has the same fields as a batch undo's, with runId. With dryRun: false the answer is 202 with a job that covers up to 500 changes; remaining counts the rest.
# preview
curl -X POST -H "Authorization: Bearer $LVNDR_API_KEY" -H "Content-Type: application/json" -d '{"dryRun": true}' $LVNDR/runs/cm9run/undo
# run (202 with a job)
curl -X POST -H "Authorization: Bearer $LVNDR_API_KEY" -H "Content-Type: application/json" -d '{"dryRun": false, "planHash": "yWsE5uJhTgDq3Xl0", "reason": "wrong collection"}' $LVNDR/runs/cm9run/undoGET /api/v1/jobs/:id
A run undo, batch undo or rollback is a background job. The write answers 202 at once with the job; nothing has been written yet. Poll this route every few seconds until status is done, partial or failed. It needs only the read scope.
curl -H "Authorization: Bearer $LVNDR_API_KEY" $LVNDR/jobs/cm9job{ "job": {
"id": "cm9job...", "kind": "run", "targetId": "cm9run...",
"status": "running", // queued | running | done | partial | failed
"total": 40, "done": 12, "failed": 0, "skipped": 1,
"remaining": 0, // changes beyond this job; undo again afterwards
"error": null, // why the whole job failed; starts with plan_changed when the set moved
"createdAt": "...", "startedAt": "...", "finishedAt": null,
"results": [ { "changeId": "...", "resourceTitle": "...", "action": "update", "status": "done", "detail": "...", "undoRunId": "..." } ]
} }partial means some changes failed and others were undone; failed means none were. A request for a run, batch or point whose job is still queued or running returns that job instead of starting another. The job checks the planHash again before it writes and fails with plan_changed if the set of changes moved. The CLI polls for you; MCP clients use lvndr_get_job.
GET /api/v1/export
Download the change log as a file. Every export is written to the store's audit log with the key that asked.
| Query parameter | Meaning |
|---|---|
| format | csv (default) or json |
| since | ISO timestamp; changes at or after it |
| until | ISO timestamp; changes at or before it |
curl -H "Authorization: Bearer $LVNDR_API_KEY" -o changes.csv \
"$LVNDR/export?format=csv&since=2026-01-01T00:00:00Z"The response is an attachment named lvndr-<store>-changes-<date>.csv (or .json). The X-Lvndr-Rows header carries the row count. Large exports stream.
Columns: id, occurredAt, resourceType, resourceId, resourceTitle, action, actorTier, actorKind, actorName, actorAppTitle, summary, diff (JSON).
GET /api/v1/openapi.json
The full contract: every route, parameter, body and response schema. No key needed; cached for five minutes.
curl https://lvndr.toolfora.com/api/v1/openapi.jsonErrors
Every error has one shape:
{ "error": { "code": "insufficient_scope", "message": "This key lacks the undo scope", "status": 403 } }| Status | code | When |
|---|---|---|
| 400 | invalid_parameter | A bad parameter: since/until not ISO timestamps, an unknown type or action, a malformed id, a body field that should be true or false |
| 400 | invalid_json | The body is not a JSON object |
| 400 | invalid_cursor | A cursor that was not passed back unchanged |
| 400 | confirm_required | A rollback without confirm: true |
| 400 | plan_required | A write (dryRun false, or a rollback) without the planHash of its preview; dry-run first |
| 400 | unknown_field | A body field the route does not take, named in the message |
| 400 | unknown_run | X-Lvndr-Run-Id names no run on this store |
| 400 | invalid_idempotency_key | Idempotency-Key longer than 255 characters |
| 401 | unauthorized | Missing, malformed, revoked or expired key |
| 402 | subscription_required | The store has no active LVNDR plan (managed billing only) |
| 403 | insufficient_scope | The key lacks the route's scope |
| 403 | not_installed | The app is not installed on this store any more |
| 404 | not_found | Unknown route, change, record, batch, restore point, alert, run or job |
| 405 | method_not_allowed | The path exists with another method |
| 413 | payload_too_large | A body over 64 KB |
| 409 | idempotency_key_reused, idempotency_key_in_progress | See Idempotency |
| 409 | plan_changed | The planHash sent with an undo or rollback no longer matches; preview again |
| 409 | conflict | An undo of this change is already running, or the deleted record was already rebuilt |
| 429 | rate_limited | Over the read or write limit, or too many failed key lookups from one address; wait Retry-After seconds |
| 500 | internal_error | Something failed on the server; retry, then contact support |