{"openapi":"3.1.0","info":{"title":"LVNDR API","version":"1.0.0","summary":"What changed in a Shopify store, who made it as far as Shopify says, and the undo.","description":"Bearer-authenticated with an API key from LVNDR > Settings > Agents & API. Keys carry scopes: read, undo, rollback, export. Writes default to dry runs, and a real write must send back the planHash of the dry run or preview it is bound to. Rate limits are per key and follow the shop's plan (Starter 60 reads / 10 writes a minute, Growth 120 / 20, Scale 300 / 60; development stores 120 / 20 once billing is on). During early access (billing not switched on) every shop, development stores included, gets the top rate, 300 / 60. Every response has X-RateLimit-Limit and X-RateLimit-Remaining; a 429 adds Retry-After. Errors are { error: { code, message, status } }; body fields a route does not document are refused with 400 unknown_field."},"servers":[{"url":"http://lvndr.toolfora.com/api/v1"}],"security":[{"bearer":[]}],"tags":[{"name":"Account"},{"name":"Changes"},{"name":"Records"},{"name":"Batches"},{"name":"Restore points"},{"name":"Alerts"},{"name":"Runs"},{"name":"Jobs"},{"name":"Export"}],"paths":{"/me":{"get":{"operationId":"getMe","summary":"The key, its scopes and the shop's plan","tags":["Account"],"x-lvndr-scope":"read","responses":{"200":{"description":"OK","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Me"}}}},"400":{"description":"Malformed request: bad JSON, a non-boolean dryRun/confirm, a bad parameter, unknown_field (a body field the route does not take), confirm_required, plan_required (a write without the planHash of its dry run or preview), invalid_cursor, unknown_run (X-Lvndr-Run-Id names no run on this shop), invalid_idempotency_key, plan_unknown (a planHash no preview returned) or include_conflicts_mismatch (includeConflicts differs from the dry run)","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unknown key (unauthorized), or a real key that expired (key_expired) or was revoked (key_revoked); the message says when","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"subscription_required: the shop's LVNDR plan does not include the API","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this route needs, or the app is not installed","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found for this shop","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per key and plan, or too many failed key lookups from one address); see Retry-After","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/status":{"get":{"operationId":"getStatus","summary":"Plan, tracked record counts and pipeline health","tags":["Account"],"x-lvndr-scope":"read","responses":{"200":{"description":"OK","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Status"}}}},"400":{"description":"Malformed request: bad JSON, a non-boolean dryRun/confirm, a bad parameter, unknown_field (a body field the route does not take), confirm_required, plan_required (a write without the planHash of its dry run or preview), invalid_cursor, unknown_run (X-Lvndr-Run-Id names no run on this shop), invalid_idempotency_key, plan_unknown (a planHash no preview returned) or include_conflicts_mismatch (includeConflicts differs from the dry run)","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unknown key (unauthorized), or a real key that expired (key_expired) or was revoked (key_revoked); the message says when","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"subscription_required: the shop's LVNDR plan does not include the API","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this route needs, or the app is not installed","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found for this shop","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per key and plan, or too many failed key lookups from one address); see Retry-After","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/changes":{"get":{"operationId":"listChanges","summary":"Changes, newest first, keyset-paginated","tags":["Changes"],"x-lvndr-scope":"read","parameters":[{"name":"since","in":"query","required":false,"description":"Changes at or after it: an ISO timestamp, or how long ago (30m, 24h, 7d, 2w)","schema":{"type":"string"},"example":"2026-11-10T00:00:00Z"},{"name":"until","in":"query","required":false,"description":"Changes at or before it: an ISO timestamp, or how long ago","schema":{"type":"string"}},{"name":"type","in":"query","required":false,"description":"Resource type, any case: PRODUCT, COLLECTION, PAGE, BLOG, ARTICLE, MENU, THEME, METAFIELD_DEFINITION","schema":{"type":"string"}},{"name":"action","in":"query","required":false,"description":"create, update or delete","schema":{"type":"string","enum":["create","update","delete"]}},{"name":"resourceId","in":"query","required":false,"description":"One record: its gid or the short form Product-123","schema":{"type":"string"},"example":"Product-123"},{"name":"actor","in":"query","required":false,"description":"Case-insensitive substring of the staff or app name","schema":{"type":"string"}},{"name":"q","in":"query","required":false,"description":"Case-insensitive substring of the record title","schema":{"type":"string"}},{"name":"hideUndos","in":"query","required":false,"description":"1/true: leave out the changes LVNDR's own undos made","schema":{"type":"boolean"}},{"name":"runId","in":"query","required":false,"description":"Only changes tagged with this agent run","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Page size, 1 to 100 (default 50)","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"Opaque; the nextCursor of the previous page","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeList"}}}},"400":{"description":"Malformed request: bad JSON, a non-boolean dryRun/confirm, a bad parameter, unknown_field (a body field the route does not take), confirm_required, plan_required (a write without the planHash of its dry run or preview), invalid_cursor, unknown_run (X-Lvndr-Run-Id names no run on this shop), invalid_idempotency_key, plan_unknown (a planHash no preview returned) or include_conflicts_mismatch (includeConflicts differs from the dry run)","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unknown key (unauthorized), or a real key that expired (key_expired) or was revoked (key_revoked); the message says when","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"subscription_required: the shop's LVNDR plan does not include the API","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this route needs, or the app is not installed","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found for this shop","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per key and plan, or too many failed key lookups from one address); see Retry-After","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/changes/{id}":{"get":{"operationId":"getChange","summary":"One change with its full diff","tags":["Changes"],"x-lvndr-scope":"read","parameters":[{"name":"id","in":"path","required":true,"description":"Id","schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,64}$"}}],"responses":{"200":{"description":"OK","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"change":{"$ref":"#/components/schemas/ChangeDetail"}},"required":["change"]}}}},"400":{"description":"Malformed request: bad JSON, a non-boolean dryRun/confirm, a bad parameter, unknown_field (a body field the route does not take), confirm_required, plan_required (a write without the planHash of its dry run or preview), invalid_cursor, unknown_run (X-Lvndr-Run-Id names no run on this shop), invalid_idempotency_key, plan_unknown (a planHash no preview returned) or include_conflicts_mismatch (includeConflicts differs from the dry run)","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unknown key (unauthorized), or a real key that expired (key_expired) or was revoked (key_revoked); the message says when","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"subscription_required: the shop's LVNDR plan does not include the API","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this route needs, or the app is not installed","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found for this shop","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per key and plan, or too many failed key lookups from one address); see Retry-After","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/changes/{id}/undo":{"post":{"operationId":"undoChange","summary":"Preview (default) or run the undo of one change","description":"With dryRun true (the default) nothing is written, `run` is null, `planHash` identifies the plan and `items` lists each field with the record, the field in merchant words and both values as text (`nothingToUndo` when none is ready). dryRun false needs that planHash (400 plan_required without it): the record is snapshotted first, then the ready fields are written back; conflicts only with includeConflicts. The answer names the undo record (`undoRunId`; `run` is the same, kept for older clients) and, once Shopify has reported it, `resultChangeId`, the change the undo's write produced. The write is refused with 409 plan_changed if the store moved since the dry run, 409 already_undone if the change was already undone, 400 include_conflicts_mismatch if includeConflicts differs from the dry run and 400 plan_unknown for a planHash no dry run returns.","tags":["Changes"],"x-lvndr-scope":"undo","parameters":[{"name":"id","in":"path","required":true,"description":"Id","schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,64}$"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Retry-safe writes: the first response is replayed for 24 h","schema":{"type":"string","maxLength":255}},{"name":"X-Lvndr-Agent","in":"header","required":false,"description":"Name of the agent making the request; stored on the write","schema":{"type":"string","maxLength":120}},{"name":"X-Lvndr-Run-Id","in":"header","required":false,"description":"Agent run the write belongs to (from POST /runs)","schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"dryRun":{"type":"boolean","default":true,"description":"true (the default) previews without writing"},"includeConflicts":{"type":"boolean","default":false,"description":"Also overwrite fields changed again since"},"planHash":{"type":"string","maxLength":64,"description":"The planHash the dry run or preview returned. Required when writing (400 plan_required without it). The write is refused with 409 plan_changed if what it would undo moved since, 409 already_undone if it was already undone (the message names the undo or job), and 400 plan_unknown for a value no preview returns."},"reason":{"type":"string","maxLength":500,"description":"Why; stored on the undo and in the audit log"}},"additionalProperties":false},"example":{"dryRun":false,"planHash":"q3Xl0c2V4Zk9b1RmN8pA7wYsE5uJhTgD","reason":"price import went wrong"}}}},"responses":{"200":{"description":"OK","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UndoResponse"},"example":{"plan":{"mode":"fields","counts":{"ready":1,"conflict":0,"noop":0,"unsupported":0},"items":[{"path":"title","status":"ready","reason":null,"current":"New","target":"Old"}]},"planHash":"q3Xl0c2V4Zk9b1RmN8pA7wYsE5uJhTgD","run":null}}}},"400":{"description":"Malformed request: bad JSON, a non-boolean dryRun/confirm, a bad parameter, unknown_field (a body field the route does not take), confirm_required, plan_required (a write without the planHash of its dry run or preview), invalid_cursor, unknown_run (X-Lvndr-Run-Id names no run on this shop), invalid_idempotency_key, plan_unknown (a planHash no preview returned) or include_conflicts_mismatch (includeConflicts differs from the dry run)","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unknown key (unauthorized), or a real key that expired (key_expired) or was revoked (key_revoked); the message says when","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"subscription_required: the shop's LVNDR plan does not include the API","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this route needs, or the app is not installed","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found for this shop","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Idempotency-Key reused with a different request, or still running; plan_changed: what the write would undo moved since its preview; already_undone: it was already undone (the message names the undo or job); or conflict: an undo of this change is already running or the deleted record was already rebuilt","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large: the body is over 64 KB","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per key and plan, or too many failed key lookups from one address); see Retry-After","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/records/{record}/history":{"get":{"operationId":"getRecordHistory","summary":"One record: latest state, stored versions and its changes","tags":["Records"],"x-lvndr-scope":"read","parameters":[{"name":"record","in":"path","required":true,"description":"Type-digits (Product-123) or a URL-encoded gid","schema":{"type":"string"},"example":"Product-123"},{"name":"cursor","in":"query","required":false,"description":"Opaque; the nextCursor of the previous page","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordHistory"}}}},"400":{"description":"Malformed request: bad JSON, a non-boolean dryRun/confirm, a bad parameter, unknown_field (a body field the route does not take), confirm_required, plan_required (a write without the planHash of its dry run or preview), invalid_cursor, unknown_run (X-Lvndr-Run-Id names no run on this shop), invalid_idempotency_key, plan_unknown (a planHash no preview returned) or include_conflicts_mismatch (includeConflicts differs from the dry run)","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unknown key (unauthorized), or a real key that expired (key_expired) or was revoked (key_revoked); the message says when","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"subscription_required: the shop's LVNDR plan does not include the API","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this route needs, or the app is not installed","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found for this shop","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per key and plan, or too many failed key lookups from one address); see Retry-After","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/batches/{id}":{"get":{"operationId":"getBatch","summary":"Everything the same actor did around a change","tags":["Batches"],"x-lvndr-scope":"read","parameters":[{"name":"id","in":"path","required":true,"description":"Any change id in the batch","schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,64}$"}}],"responses":{"200":{"description":"OK","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Batch"}}}},"400":{"description":"Malformed request: bad JSON, a non-boolean dryRun/confirm, a bad parameter, unknown_field (a body field the route does not take), confirm_required, plan_required (a write without the planHash of its dry run or preview), invalid_cursor, unknown_run (X-Lvndr-Run-Id names no run on this shop), invalid_idempotency_key, plan_unknown (a planHash no preview returned) or include_conflicts_mismatch (includeConflicts differs from the dry run)","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unknown key (unauthorized), or a real key that expired (key_expired) or was revoked (key_revoked); the message says when","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"subscription_required: the shop's LVNDR plan does not include the API","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this route needs, or the app is not installed","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found for this shop","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per key and plan, or too many failed key lookups from one address); see Retry-After","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/batches/{id}/undo":{"post":{"operationId":"undoBatch","summary":"Preview (default) or queue the undo of a whole batch, newest first","description":"dryRun true (the default) plans the newest 50 changes without writing and returns `items` (each field the undo would write, with the record, the field in merchant words and both values as text), `more` (changes not planned), `remaining` (beyond one job), `nothingToUndo` and `planHash`. dryRun false needs that planHash (400 plan_required without it), queues a background job, starts it at once and answers 202 { job }; poll GET /jobs/{id} after job.pollAfterMs. The job is refused with 409 plan_changed if the set of changes moved since the preview, or 409 already_undone if an earlier job already undid that set.","tags":["Batches"],"x-lvndr-scope":"undo","parameters":[{"name":"id","in":"path","required":true,"description":"Any change id in the batch","schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,64}$"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Retry-safe writes: the first response is replayed for 24 h","schema":{"type":"string","maxLength":255}},{"name":"X-Lvndr-Agent","in":"header","required":false,"description":"Name of the agent making the request; stored on the write","schema":{"type":"string","maxLength":120}},{"name":"X-Lvndr-Run-Id","in":"header","required":false,"description":"Agent run the write belongs to (from POST /runs)","schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"dryRun":{"type":"boolean","default":true,"description":"true (the default) previews without writing"},"planHash":{"type":"string","maxLength":64,"description":"The planHash the dry run or preview returned. Required when writing (400 plan_required without it). The write is refused with 409 plan_changed if what it would undo moved since, 409 already_undone if it was already undone (the message names the undo or job), and 400 plan_unknown for a value no preview returns."},"reason":{"type":"string","maxLength":500,"description":"Why; stored on the undo and in the audit log"}},"additionalProperties":false},"example":{"dryRun":true}}}},"responses":{"200":{"description":"OK (dry run or preview)","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchUndo"}}}},"202":{"description":"Queued as a background job; poll GET /jobs/{id}","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"anchorId":{"type":"string"},"dryRun":{"type":"boolean","const":false},"job":{"type":"object","description":"A multi-change undo running in the background. Poll GET /jobs/{id} (or lvndr_get_job) until status is done, partial or failed.","properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["run","batch","rollback","record","selection"]},"targetId":{"type":"string","description":"Run id, batch anchor change id, or restore point id"},"status":{"type":"string","enum":["queued","running","done","partial","failed"]},"total":{"type":"integer","description":"Changes the job covers"},"done":{"type":"integer"},"failed":{"type":"integer","description":"Failed or partly failed changes"},"skipped":{"type":"integer"},"remaining":{"type":"integer","description":"Changes beyond what one job covers; start another after this one"},"error":{"type":["string","null"],"description":"Why the job failed as a whole; starts with plan_changed when the change set moved since the preview"},"createdAt":{"type":"string","format":"date-time"},"startedAt":{"type":["string","null"],"format":"date-time"},"finishedAt":{"type":["string","null"],"format":"date-time"},"pollAfterMs":{"type":["integer","null"],"description":"While queued or running: poll again after this many milliseconds. null once the job is final."},"results":{"type":"array","description":"One entry per change handled so far, newest change first","items":{"type":"object","properties":{"changeId":{"type":"string"},"resourceTitle":{"type":["string","null"]},"action":{"type":"string"},"status":{"type":"string","enum":["done","partial","failed","skipped"]},"detail":{"type":"string"},"undoRunId":{"type":["string","null"]}},"required":["changeId","status","detail"]}}},"required":["id","kind","targetId","status","total","done","failed","skipped","createdAt","results"]}},"required":["job"]}}}},"400":{"description":"Malformed request: bad JSON, a non-boolean dryRun/confirm, a bad parameter, unknown_field (a body field the route does not take), confirm_required, plan_required (a write without the planHash of its dry run or preview), invalid_cursor, unknown_run (X-Lvndr-Run-Id names no run on this shop), invalid_idempotency_key, plan_unknown (a planHash no preview returned) or include_conflicts_mismatch (includeConflicts differs from the dry run)","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unknown key (unauthorized), or a real key that expired (key_expired) or was revoked (key_revoked); the message says when","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"subscription_required: the shop's LVNDR plan does not include the API","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this route needs, or the app is not installed","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found for this shop","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Idempotency-Key reused with a different request, or still running; plan_changed: what the write would undo moved since its preview; already_undone: it was already undone (the message names the undo or job); or conflict: an undo of this change is already running or the deleted record was already rebuilt","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large: the body is over 64 KB","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per key and plan, or too many failed key lookups from one address); see Retry-After","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/restore-points":{"get":{"operationId":"listRestorePoints","summary":"Restore points, newest first, paged","description":"The daily check's points (kind sweep) are left out unless kind is sweep or all.","tags":["Restore points"],"x-lvndr-scope":"read","parameters":[{"name":"kind","in":"query","required":false,"description":"manual, burst, app_install, sweep, or all (default: every kind but sweep)","schema":{"type":"string","enum":["manual","burst","app_install","sweep","all"]}},{"name":"limit","in":"query","required":false,"description":"1 to 100 (default 50)","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"Opaque; the nextCursor of the previous page","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"points":{"type":"array","items":{"$ref":"#/components/schemas/RestorePoint"}},"nextCursor":{"type":["string","null"],"description":"Pass as ?cursor= for the next page; null on the last page"}},"required":["points","nextCursor"]}}}},"400":{"description":"Malformed request: bad JSON, a non-boolean dryRun/confirm, a bad parameter, unknown_field (a body field the route does not take), confirm_required, plan_required (a write without the planHash of its dry run or preview), invalid_cursor, unknown_run (X-Lvndr-Run-Id names no run on this shop), invalid_idempotency_key, plan_unknown (a planHash no preview returned) or include_conflicts_mismatch (includeConflicts differs from the dry run)","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unknown key (unauthorized), or a real key that expired (key_expired) or was revoked (key_revoked); the message says when","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"subscription_required: the shop's LVNDR plan does not include the API","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this route needs, or the app is not installed","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found for this shop","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per key and plan, or too many failed key lookups from one address); see Retry-After","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"markRestorePoint","summary":"Mark a restore point now, e.g. before a bulk job","tags":["Restore points"],"x-lvndr-scope":"read","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Retry-safe writes: the first response is replayed for 24 h","schema":{"type":"string","maxLength":255}},{"name":"X-Lvndr-Agent","in":"header","required":false,"description":"Name of the agent making the request; stored on the write","schema":{"type":"string","maxLength":120}},{"name":"X-Lvndr-Run-Id","in":"header","required":false,"description":"Agent run the write belongs to (from POST /runs)","schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"label":{"type":"string","maxLength":120},"reason":{"type":"string","maxLength":500,"description":"Why; stored on the undo and in the audit log"}},"additionalProperties":false},"example":{"label":"before the import"}}}},"responses":{"200":{"description":"OK","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"point":{"$ref":"#/components/schemas/RestorePoint"}},"required":["point"]}}}},"400":{"description":"Malformed request: bad JSON, a non-boolean dryRun/confirm, a bad parameter, unknown_field (a body field the route does not take), confirm_required, plan_required (a write without the planHash of its dry run or preview), invalid_cursor, unknown_run (X-Lvndr-Run-Id names no run on this shop), invalid_idempotency_key, plan_unknown (a planHash no preview returned) or include_conflicts_mismatch (includeConflicts differs from the dry run)","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unknown key (unauthorized), or a real key that expired (key_expired) or was revoked (key_revoked); the message says when","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"subscription_required: the shop's LVNDR plan does not include the API","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this route needs, or the app is not installed","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found for this shop","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Idempotency-Key reused with a different request, or still running; plan_changed: what the write would undo moved since its preview; already_undone: it was already undone (the message names the undo or job); or conflict: an undo of this change is already running or the deleted record was already rebuilt","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large: the body is over 64 KB","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per key and plan, or too many failed key lookups from one address); see Retry-After","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/restore-points/{id}":{"get":{"operationId":"getRestorePoint","summary":"One restore point and how many changes came after it","tags":["Restore points"],"x-lvndr-scope":"read","parameters":[{"name":"id","in":"path","required":true,"description":"Id","schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,64}$"}}],"responses":{"200":{"description":"OK","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"point":{"$ref":"#/components/schemas/RestorePoint"}},"required":["point"]}}}},"400":{"description":"Malformed request: bad JSON, a non-boolean dryRun/confirm, a bad parameter, unknown_field (a body field the route does not take), confirm_required, plan_required (a write without the planHash of its dry run or preview), invalid_cursor, unknown_run (X-Lvndr-Run-Id names no run on this shop), invalid_idempotency_key, plan_unknown (a planHash no preview returned) or include_conflicts_mismatch (includeConflicts differs from the dry run)","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unknown key (unauthorized), or a real key that expired (key_expired) or was revoked (key_revoked); the message says when","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"subscription_required: the shop's LVNDR plan does not include the API","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this route needs, or the app is not installed","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found for this shop","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per key and plan, or too many failed key lookups from one address); see Retry-After","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/restore-points/{id}/preview":{"get":{"operationId":"previewRollback","summary":"Dry run of a rollback: what would be restored, skipped or left alone","tags":["Restore points"],"x-lvndr-scope":"read","parameters":[{"name":"id","in":"path","required":true,"description":"Id","schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,64}$"}}],"responses":{"200":{"description":"OK","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RollbackPreview"}}}},"400":{"description":"Malformed request: bad JSON, a non-boolean dryRun/confirm, a bad parameter, unknown_field (a body field the route does not take), confirm_required, plan_required (a write without the planHash of its dry run or preview), invalid_cursor, unknown_run (X-Lvndr-Run-Id names no run on this shop), invalid_idempotency_key, plan_unknown (a planHash no preview returned) or include_conflicts_mismatch (includeConflicts differs from the dry run)","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unknown key (unauthorized), or a real key that expired (key_expired) or was revoked (key_revoked); the message says when","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"subscription_required: the shop's LVNDR plan does not include the API","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this route needs, or the app is not installed","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found for this shop","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per key and plan, or too many failed key lookups from one address); see Retry-After","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/restore-points/{id}/rollback":{"post":{"operationId":"rollbackToRestorePoint","summary":"Queue the undo of every change after the point, newest first","description":"Refused with 400 confirm_required unless the body has confirm: true, and with 400 plan_required without the planHash from GET /restore-points/{id}/preview. The rollback runs as a background job (202 { job }, poll GET /jobs/{id}) and is refused with 409 plan_changed if changes arrived since the preview.","tags":["Restore points"],"x-lvndr-scope":"rollback","parameters":[{"name":"id","in":"path","required":true,"description":"Id","schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,64}$"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Retry-safe writes: the first response is replayed for 24 h","schema":{"type":"string","maxLength":255}},{"name":"X-Lvndr-Agent","in":"header","required":false,"description":"Name of the agent making the request; stored on the write","schema":{"type":"string","maxLength":120}},{"name":"X-Lvndr-Run-Id","in":"header","required":false,"description":"Agent run the write belongs to (from POST /runs)","schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"confirm":{"type":"boolean","const":true},"planHash":{"type":"string","maxLength":64,"description":"The planHash the dry run or preview returned. Required when writing (400 plan_required without it). The write is refused with 409 plan_changed if what it would undo moved since, 409 already_undone if it was already undone (the message names the undo or job), and 400 plan_unknown for a value no preview returns."},"reason":{"type":"string","maxLength":500,"description":"Why; stored on the undo and in the audit log"}},"required":["confirm","planHash"],"additionalProperties":false},"example":{"confirm":true,"planHash":"q3Xl0c2V4Zk9b1RmN8pA7wYsE5uJhTgD","reason":"bad import"}}}},"responses":{"200":{"description":"OK (dry run or preview)","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"pointId":{"type":"string"},"dryRun":{"type":"boolean","const":false},"job":{"type":"object","description":"A multi-change undo running in the background. Poll GET /jobs/{id} (or lvndr_get_job) until status is done, partial or failed.","properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["run","batch","rollback","record","selection"]},"targetId":{"type":"string","description":"Run id, batch anchor change id, or restore point id"},"status":{"type":"string","enum":["queued","running","done","partial","failed"]},"total":{"type":"integer","description":"Changes the job covers"},"done":{"type":"integer"},"failed":{"type":"integer","description":"Failed or partly failed changes"},"skipped":{"type":"integer"},"remaining":{"type":"integer","description":"Changes beyond what one job covers; start another after this one"},"error":{"type":["string","null"],"description":"Why the job failed as a whole; starts with plan_changed when the change set moved since the preview"},"createdAt":{"type":"string","format":"date-time"},"startedAt":{"type":["string","null"],"format":"date-time"},"finishedAt":{"type":["string","null"],"format":"date-time"},"pollAfterMs":{"type":["integer","null"],"description":"While queued or running: poll again after this many milliseconds. null once the job is final."},"results":{"type":"array","description":"One entry per change handled so far, newest change first","items":{"type":"object","properties":{"changeId":{"type":"string"},"resourceTitle":{"type":["string","null"]},"action":{"type":"string"},"status":{"type":"string","enum":["done","partial","failed","skipped"]},"detail":{"type":"string"},"undoRunId":{"type":["string","null"]}},"required":["changeId","status","detail"]}}},"required":["id","kind","targetId","status","total","done","failed","skipped","createdAt","results"]}},"required":["job"]}}}},"202":{"description":"Queued as a background job; poll GET /jobs/{id}","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"pointId":{"type":"string"},"dryRun":{"type":"boolean","const":false},"job":{"type":"object","description":"A multi-change undo running in the background. Poll GET /jobs/{id} (or lvndr_get_job) until status is done, partial or failed.","properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["run","batch","rollback","record","selection"]},"targetId":{"type":"string","description":"Run id, batch anchor change id, or restore point id"},"status":{"type":"string","enum":["queued","running","done","partial","failed"]},"total":{"type":"integer","description":"Changes the job covers"},"done":{"type":"integer"},"failed":{"type":"integer","description":"Failed or partly failed changes"},"skipped":{"type":"integer"},"remaining":{"type":"integer","description":"Changes beyond what one job covers; start another after this one"},"error":{"type":["string","null"],"description":"Why the job failed as a whole; starts with plan_changed when the change set moved since the preview"},"createdAt":{"type":"string","format":"date-time"},"startedAt":{"type":["string","null"],"format":"date-time"},"finishedAt":{"type":["string","null"],"format":"date-time"},"pollAfterMs":{"type":["integer","null"],"description":"While queued or running: poll again after this many milliseconds. null once the job is final."},"results":{"type":"array","description":"One entry per change handled so far, newest change first","items":{"type":"object","properties":{"changeId":{"type":"string"},"resourceTitle":{"type":["string","null"]},"action":{"type":"string"},"status":{"type":"string","enum":["done","partial","failed","skipped"]},"detail":{"type":"string"},"undoRunId":{"type":["string","null"]}},"required":["changeId","status","detail"]}}},"required":["id","kind","targetId","status","total","done","failed","skipped","createdAt","results"]}},"required":["job"]}}}},"400":{"description":"Malformed request: bad JSON, a non-boolean dryRun/confirm, a bad parameter, unknown_field (a body field the route does not take), confirm_required, plan_required (a write without the planHash of its dry run or preview), invalid_cursor, unknown_run (X-Lvndr-Run-Id names no run on this shop), invalid_idempotency_key, plan_unknown (a planHash no preview returned) or include_conflicts_mismatch (includeConflicts differs from the dry run)","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unknown key (unauthorized), or a real key that expired (key_expired) or was revoked (key_revoked); the message says when","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"subscription_required: the shop's LVNDR plan does not include the API","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this route needs, or the app is not installed","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found for this shop","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Idempotency-Key reused with a different request, or still running; plan_changed: what the write would undo moved since its preview; already_undone: it was already undone (the message names the undo or job); or conflict: an undo of this change is already running or the deleted record was already rebuilt","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large: the body is over 64 KB","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per key and plan, or too many failed key lookups from one address); see Retry-After","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/alerts":{"get":{"operationId":"listAlerts","summary":"Burst alerts, newest first","tags":["Alerts"],"x-lvndr-scope":"read","parameters":[{"name":"status","in":"query","required":false,"description":"open (default), dismissed, resolved (closed by an undo) or all","schema":{"type":"string","enum":["open","dismissed","resolved","all"],"default":"open"}},{"name":"limit","in":"query","required":false,"description":"1 to 100 (default 50)","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}],"responses":{"200":{"description":"OK","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"alerts":{"type":"array","items":{"$ref":"#/components/schemas/Alert"}}},"required":["alerts"]}}}},"400":{"description":"Malformed request: bad JSON, a non-boolean dryRun/confirm, a bad parameter, unknown_field (a body field the route does not take), confirm_required, plan_required (a write without the planHash of its dry run or preview), invalid_cursor, unknown_run (X-Lvndr-Run-Id names no run on this shop), invalid_idempotency_key, plan_unknown (a planHash no preview returned) or include_conflicts_mismatch (includeConflicts differs from the dry run)","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unknown key (unauthorized), or a real key that expired (key_expired) or was revoked (key_revoked); the message says when","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"subscription_required: the shop's LVNDR plan does not include the API","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this route needs, or the app is not installed","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found for this shop","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per key and plan, or too many failed key lookups from one address); see Retry-After","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/alerts/{id}/dismiss":{"post":{"operationId":"dismissAlert","summary":"Dismiss an alert","description":"Needs the undo scope: a read-only key cannot silence the alert its own burst raised.","tags":["Alerts"],"x-lvndr-scope":"undo","parameters":[{"name":"id","in":"path","required":true,"description":"Id","schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,64}$"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Retry-safe writes: the first response is replayed for 24 h","schema":{"type":"string","maxLength":255}},{"name":"X-Lvndr-Agent","in":"header","required":false,"description":"Name of the agent making the request; stored on the write","schema":{"type":"string","maxLength":120}},{"name":"X-Lvndr-Run-Id","in":"header","required":false,"description":"Agent run the write belongs to (from POST /runs)","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"alert":{"$ref":"#/components/schemas/Alert"},"dismissed":{"type":"boolean","description":"false when it was not open (already dismissed or resolved)"}},"required":["alert","dismissed"]}}}},"400":{"description":"Malformed request: bad JSON, a non-boolean dryRun/confirm, a bad parameter, unknown_field (a body field the route does not take), confirm_required, plan_required (a write without the planHash of its dry run or preview), invalid_cursor, unknown_run (X-Lvndr-Run-Id names no run on this shop), invalid_idempotency_key, plan_unknown (a planHash no preview returned) or include_conflicts_mismatch (includeConflicts differs from the dry run)","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unknown key (unauthorized), or a real key that expired (key_expired) or was revoked (key_revoked); the message says when","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"subscription_required: the shop's LVNDR plan does not include the API","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this route needs, or the app is not installed","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found for this shop","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Idempotency-Key reused with a different request, or still running; plan_changed: what the write would undo moved since its preview; already_undone: it was already undone (the message names the undo or job); or conflict: an undo of this change is already running or the deleted record was already rebuilt","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large: the body is over 64 KB","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per key and plan, or too many failed key lookups from one address); see Retry-After","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/runs":{"post":{"operationId":"startRun","summary":"Announce an agent run; changes made during it are tagged with its id","description":"Needs only the read scope: it writes to LVNDR, never to the store. agent is required (in the body or the X-Lvndr-Agent header); task is optional but shown to the merchant. markRestorePoint (default true) also marks a restore point just before the run. What the run collects depends on the key (`capture` in the response): a key with the undo scope opens a catch-all run that tags every unattributed or inferred change while it is open (up to 24 h); any other key's run tags only changes made by its own OAuth client, or none, and then `warning` says so. A clientId is used only when it is the key's own OAuth client id. Poll GET /runs/{id} until attributedThrough is after your last write and pendingDeliveries is 0 before reviewing.","tags":["Runs"],"x-lvndr-scope":"read","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Retry-safe writes: the first response is replayed for 24 h","schema":{"type":"string","maxLength":255}},{"name":"X-Lvndr-Agent","in":"header","required":false,"description":"Name of the agent making the request; stored on the write","schema":{"type":"string","maxLength":120}},{"name":"X-Lvndr-Run-Id","in":"header","required":false,"description":"Agent run the write belongs to (from POST /runs)","schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"agent":{"type":"string","maxLength":120,"description":"Defaults to the X-Lvndr-Agent header"},"task":{"type":"string","maxLength":500},"clientId":{"type":"string","maxLength":64,"description":"Used only when it is this key's own OAuth client id; otherwise ignored (captureNote says so)"},"markRestorePoint":{"type":"boolean","default":true}},"additionalProperties":false},"example":{"agent":"Claude Code","task":"Raise winter prices 10%","markRestorePoint":true}}}},"responses":{"200":{"description":"OK","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunStart"}}}},"400":{"description":"Malformed request: bad JSON, a non-boolean dryRun/confirm, a bad parameter, unknown_field (a body field the route does not take), confirm_required, plan_required (a write without the planHash of its dry run or preview), invalid_cursor, unknown_run (X-Lvndr-Run-Id names no run on this shop), invalid_idempotency_key, plan_unknown (a planHash no preview returned) or include_conflicts_mismatch (includeConflicts differs from the dry run)","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unknown key (unauthorized), or a real key that expired (key_expired) or was revoked (key_revoked); the message says when","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"subscription_required: the shop's LVNDR plan does not include the API","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this route needs, or the app is not installed","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found for this shop","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Idempotency-Key reused with a different request, or still running; plan_changed: what the write would undo moved since its preview; already_undone: it was already undone (the message names the undo or job); or conflict: an undo of this change is already running or the deleted record was already rebuilt","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large: the body is over 64 KB","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per key and plan, or too many failed key lookups from one address); see Retry-After","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"operationId":"listRuns","summary":"Agent runs, newest first","tags":["Runs"],"x-lvndr-scope":"read","parameters":[{"name":"open","in":"query","required":false,"description":"1/true: open runs only","schema":{"type":"boolean"}},{"name":"limit","in":"query","required":false,"description":"1 to 100","schema":{"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"OK","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"runs":{"type":"array","items":{"$ref":"#/components/schemas/AgentRun"}}},"required":["runs"]}}}},"400":{"description":"Malformed request: bad JSON, a non-boolean dryRun/confirm, a bad parameter, unknown_field (a body field the route does not take), confirm_required, plan_required (a write without the planHash of its dry run or preview), invalid_cursor, unknown_run (X-Lvndr-Run-Id names no run on this shop), invalid_idempotency_key, plan_unknown (a planHash no preview returned) or include_conflicts_mismatch (includeConflicts differs from the dry run)","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unknown key (unauthorized), or a real key that expired (key_expired) or was revoked (key_revoked); the message says when","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"subscription_required: the shop's LVNDR plan does not include the API","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this route needs, or the app is not installed","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found for this shop","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per key and plan, or too many failed key lookups from one address); see Retry-After","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/runs/{id}":{"get":{"operationId":"getRun","summary":"One run with its changes and how fresh the tagging is","description":"Changes are tagged within a few minutes (collection rules and SEO, menus, themes and metafield definitions up to 10). Poll about every 20 s until attributedThrough is after your last write and pendingDeliveries is 0, then review.","tags":["Runs"],"x-lvndr-scope":"read","parameters":[{"name":"id","in":"path","required":true,"description":"Id","schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,64}$"}},{"name":"cursor","in":"query","required":false,"description":"Opaque; the nextCursor of the previous page","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Changes per page, 1 to 200","schema":{"type":"integer"}}],"responses":{"200":{"description":"OK","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunDetail"}}}},"400":{"description":"Malformed request: bad JSON, a non-boolean dryRun/confirm, a bad parameter, unknown_field (a body field the route does not take), confirm_required, plan_required (a write without the planHash of its dry run or preview), invalid_cursor, unknown_run (X-Lvndr-Run-Id names no run on this shop), invalid_idempotency_key, plan_unknown (a planHash no preview returned) or include_conflicts_mismatch (includeConflicts differs from the dry run)","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unknown key (unauthorized), or a real key that expired (key_expired) or was revoked (key_revoked); the message says when","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"subscription_required: the shop's LVNDR plan does not include the API","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this route needs, or the app is not installed","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found for this shop","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per key and plan, or too many failed key lookups from one address); see Retry-After","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/runs/{id}/end":{"post":{"operationId":"endRun","summary":"Close a run (idempotent; alreadyEnded is true on a second call)","tags":["Runs"],"x-lvndr-scope":"read","parameters":[{"name":"id","in":"path","required":true,"description":"Id","schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,64}$"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Retry-safe writes: the first response is replayed for 24 h","schema":{"type":"string","maxLength":255}},{"name":"X-Lvndr-Agent","in":"header","required":false,"description":"Name of the agent making the request; stored on the write","schema":{"type":"string","maxLength":120}},{"name":"X-Lvndr-Run-Id","in":"header","required":false,"description":"Agent run the write belongs to (from POST /runs)","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"run":{"$ref":"#/components/schemas/AgentRun"},"alreadyEnded":{"type":"boolean","description":"true when the run had already ended; nothing changed"}},"required":["run"]}}}},"400":{"description":"Malformed request: bad JSON, a non-boolean dryRun/confirm, a bad parameter, unknown_field (a body field the route does not take), confirm_required, plan_required (a write without the planHash of its dry run or preview), invalid_cursor, unknown_run (X-Lvndr-Run-Id names no run on this shop), invalid_idempotency_key, plan_unknown (a planHash no preview returned) or include_conflicts_mismatch (includeConflicts differs from the dry run)","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unknown key (unauthorized), or a real key that expired (key_expired) or was revoked (key_revoked); the message says when","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"subscription_required: the shop's LVNDR plan does not include the API","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this route needs, or the app is not installed","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found for this shop","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Idempotency-Key reused with a different request, or still running; plan_changed: what the write would undo moved since its preview; already_undone: it was already undone (the message names the undo or job); or conflict: an undo of this change is already running or the deleted record was already rebuilt","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large: the body is over 64 KB","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per key and plan, or too many failed key lookups from one address); see Retry-After","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/runs/{id}/undo":{"post":{"operationId":"undoRun","summary":"Preview (default) or queue the undo of everything the run changed, newest first","description":"dryRun true (the default) plans the newest 50 changes without writing and returns `items` (each field the undo would write, with the record, the field in merchant words and both values as text), `more` (changes not planned), `remaining` (beyond one job), `nothingToUndo` and `planHash`. dryRun false needs that planHash (400 plan_required without it), queues a background job, starts it at once and answers 202 { job }; poll GET /jobs/{id} after job.pollAfterMs. The job is refused with 409 plan_changed if the set of changes moved since the preview, or 409 already_undone if an earlier job already undid that set.","tags":["Runs"],"x-lvndr-scope":"undo","parameters":[{"name":"id","in":"path","required":true,"description":"Id","schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,64}$"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Retry-safe writes: the first response is replayed for 24 h","schema":{"type":"string","maxLength":255}},{"name":"X-Lvndr-Agent","in":"header","required":false,"description":"Name of the agent making the request; stored on the write","schema":{"type":"string","maxLength":120}},{"name":"X-Lvndr-Run-Id","in":"header","required":false,"description":"Agent run the write belongs to (from POST /runs)","schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"dryRun":{"type":"boolean","default":true,"description":"true (the default) previews without writing"},"planHash":{"type":"string","maxLength":64,"description":"The planHash the dry run or preview returned. Required when writing (400 plan_required without it). The write is refused with 409 plan_changed if what it would undo moved since, 409 already_undone if it was already undone (the message names the undo or job), and 400 plan_unknown for a value no preview returns."},"reason":{"type":"string","maxLength":500,"description":"Why; stored on the undo and in the audit log"}},"additionalProperties":false},"example":{"dryRun":true}}}},"responses":{"200":{"description":"OK (dry run or preview)","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunUndo"}}}},"202":{"description":"Queued as a background job; poll GET /jobs/{id}","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"runId":{"type":"string"},"dryRun":{"type":"boolean","const":false},"job":{"type":"object","description":"A multi-change undo running in the background. Poll GET /jobs/{id} (or lvndr_get_job) until status is done, partial or failed.","properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["run","batch","rollback","record","selection"]},"targetId":{"type":"string","description":"Run id, batch anchor change id, or restore point id"},"status":{"type":"string","enum":["queued","running","done","partial","failed"]},"total":{"type":"integer","description":"Changes the job covers"},"done":{"type":"integer"},"failed":{"type":"integer","description":"Failed or partly failed changes"},"skipped":{"type":"integer"},"remaining":{"type":"integer","description":"Changes beyond what one job covers; start another after this one"},"error":{"type":["string","null"],"description":"Why the job failed as a whole; starts with plan_changed when the change set moved since the preview"},"createdAt":{"type":"string","format":"date-time"},"startedAt":{"type":["string","null"],"format":"date-time"},"finishedAt":{"type":["string","null"],"format":"date-time"},"pollAfterMs":{"type":["integer","null"],"description":"While queued or running: poll again after this many milliseconds. null once the job is final."},"results":{"type":"array","description":"One entry per change handled so far, newest change first","items":{"type":"object","properties":{"changeId":{"type":"string"},"resourceTitle":{"type":["string","null"]},"action":{"type":"string"},"status":{"type":"string","enum":["done","partial","failed","skipped"]},"detail":{"type":"string"},"undoRunId":{"type":["string","null"]}},"required":["changeId","status","detail"]}}},"required":["id","kind","targetId","status","total","done","failed","skipped","createdAt","results"]}},"required":["job"]}}}},"400":{"description":"Malformed request: bad JSON, a non-boolean dryRun/confirm, a bad parameter, unknown_field (a body field the route does not take), confirm_required, plan_required (a write without the planHash of its dry run or preview), invalid_cursor, unknown_run (X-Lvndr-Run-Id names no run on this shop), invalid_idempotency_key, plan_unknown (a planHash no preview returned) or include_conflicts_mismatch (includeConflicts differs from the dry run)","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unknown key (unauthorized), or a real key that expired (key_expired) or was revoked (key_revoked); the message says when","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"subscription_required: the shop's LVNDR plan does not include the API","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this route needs, or the app is not installed","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found for this shop","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Idempotency-Key reused with a different request, or still running; plan_changed: what the write would undo moved since its preview; already_undone: it was already undone (the message names the undo or job); or conflict: an undo of this change is already running or the deleted record was already rebuilt","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large: the body is over 64 KB","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per key and plan, or too many failed key lookups from one address); see Retry-After","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/jobs/{id}":{"get":{"operationId":"getJob","summary":"One background undo job (run, batch or rollback) and its progress","tags":["Jobs"],"x-lvndr-scope":"read","parameters":[{"name":"id","in":"path","required":true,"description":"Id","schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,64}$"}}],"responses":{"200":{"description":"OK","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"job":{"type":"object","description":"A multi-change undo running in the background. Poll GET /jobs/{id} (or lvndr_get_job) until status is done, partial or failed.","properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["run","batch","rollback","record","selection"]},"targetId":{"type":"string","description":"Run id, batch anchor change id, or restore point id"},"status":{"type":"string","enum":["queued","running","done","partial","failed"]},"total":{"type":"integer","description":"Changes the job covers"},"done":{"type":"integer"},"failed":{"type":"integer","description":"Failed or partly failed changes"},"skipped":{"type":"integer"},"remaining":{"type":"integer","description":"Changes beyond what one job covers; start another after this one"},"error":{"type":["string","null"],"description":"Why the job failed as a whole; starts with plan_changed when the change set moved since the preview"},"createdAt":{"type":"string","format":"date-time"},"startedAt":{"type":["string","null"],"format":"date-time"},"finishedAt":{"type":["string","null"],"format":"date-time"},"pollAfterMs":{"type":["integer","null"],"description":"While queued or running: poll again after this many milliseconds. null once the job is final."},"results":{"type":"array","description":"One entry per change handled so far, newest change first","items":{"type":"object","properties":{"changeId":{"type":"string"},"resourceTitle":{"type":["string","null"]},"action":{"type":"string"},"status":{"type":"string","enum":["done","partial","failed","skipped"]},"detail":{"type":"string"},"undoRunId":{"type":["string","null"]}},"required":["changeId","status","detail"]}}},"required":["id","kind","targetId","status","total","done","failed","skipped","createdAt","results"]}},"required":["job"]}}}},"400":{"description":"Malformed request: bad JSON, a non-boolean dryRun/confirm, a bad parameter, unknown_field (a body field the route does not take), confirm_required, plan_required (a write without the planHash of its dry run or preview), invalid_cursor, unknown_run (X-Lvndr-Run-Id names no run on this shop), invalid_idempotency_key, plan_unknown (a planHash no preview returned) or include_conflicts_mismatch (includeConflicts differs from the dry run)","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unknown key (unauthorized), or a real key that expired (key_expired) or was revoked (key_revoked); the message says when","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"subscription_required: the shop's LVNDR plan does not include the API","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this route needs, or the app is not installed","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found for this shop","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per key and plan, or too many failed key lookups from one address); see Retry-After","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/export":{"get":{"operationId":"exportChanges","summary":"Download the change log (CSV or JSON); every export is audited","tags":["Export"],"x-lvndr-scope":"export","parameters":[{"name":"format","in":"query","required":false,"description":"csv (default) or json","schema":{"type":"string","enum":["csv","json"]}},{"name":"since","in":"query","required":false,"description":"ISO timestamp","schema":{"type":"string","format":"date-time"}},{"name":"until","in":"query","required":false,"description":"ISO timestamp","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"OK","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"text/csv":{"schema":{"type":"string"}},"application/json":{"schema":{"type":"array","items":{"type":"object"}}}}},"400":{"description":"Malformed request: bad JSON, a non-boolean dryRun/confirm, a bad parameter, unknown_field (a body field the route does not take), confirm_required, plan_required (a write without the planHash of its dry run or preview), invalid_cursor, unknown_run (X-Lvndr-Run-Id names no run on this shop), invalid_idempotency_key, plan_unknown (a planHash no preview returned) or include_conflicts_mismatch (includeConflicts differs from the dry run)","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unknown key (unauthorized), or a real key that expired (key_expired) or was revoked (key_revoked); the message says when","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"subscription_required: the shop's LVNDR plan does not include the API","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this route needs, or the app is not installed","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found for this shop","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per key and plan, or too many failed key lookups from one address); see Retry-After","headers":{"X-RateLimit-Limit":{"description":"Requests per minute for this key and kind (read or write); set by the shop's plan","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/openapi.json":{"get":{"operationId":"getOpenApi","summary":"This document (no auth)","tags":["Account"],"security":[],"responses":{"200":{"description":"OpenAPI 3.1 document","content":{"application/json":{"schema":{"type":"object"}}}}}}}},"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"lv_…","description":"An API key from Settings > Agents & API, or an OAuth access token"}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable machine code, e.g. insufficient_scope, rate_limited, confirm_required, not_found"},"message":{"type":"string","description":"Human-readable explanation"},"status":{"type":"integer","description":"The HTTP status, repeated"}},"required":["code","message","status"]}},"required":["error"],"description":"Every non-2xx response."},"Actor":{"type":"object","properties":{"tier":{"type":"string","enum":["exact","channel","inferred","unknown"],"description":"How sure the attribution is"},"kind":{"type":"string","enum":["staff","app","shopify","unknown","agent"]},"name":{"type":["string","null"]},"appTitle":{"type":["string","null"]},"note":{"type":["string","null"]},"label":{"type":"string","description":"What the app shows as the actor"}},"required":["tier","kind","name","appTitle","note","label"]},"Change":{"type":"object","properties":{"id":{"type":"string"},"resourceType":{"type":"string","enum":["PRODUCT","COLLECTION","PAGE","BLOG","ARTICLE","MENU","THEME","METAFIELD_DEFINITION"]},"resourceId":{"type":"string","description":"Shopify gid"},"resourceTitle":{"type":["string","null"]},"action":{"type":"string","enum":["create","update","delete"]},"occurredAt":{"type":"string","format":"date-time"},"fields":{"type":"string","description":"Short list of the fields that moved, or 'new record' / 'record removed'"},"summary":{"type":["string","null"],"description":"One plain sentence, when summaries are on"},"runId":{"type":["string","null"],"description":"Agent run the change was tagged with"},"actor":{"type":"object","properties":{"tier":{"type":"string","enum":["exact","channel","inferred","unknown"],"description":"How sure the attribution is"},"kind":{"type":"string","enum":["staff","app","shopify","unknown","agent"]},"name":{"type":["string","null"]},"appTitle":{"type":["string","null"]},"note":{"type":["string","null"]},"label":{"type":"string","description":"What the app shows as the actor"}},"required":["tier","kind","name","appTitle","note","label"]}},"required":["id","resourceType","resourceId","resourceTitle","action","occurredAt","fields","summary","runId","actor"],"description":"One change to one record."},"ChangeDetail":{"type":"object","properties":{"id":{"type":"string"},"resourceType":{"type":"string","enum":["PRODUCT","COLLECTION","PAGE","BLOG","ARTICLE","MENU","THEME","METAFIELD_DEFINITION"]},"resourceId":{"type":"string","description":"Shopify gid"},"resourceTitle":{"type":["string","null"]},"action":{"type":"string","enum":["create","update","delete"]},"occurredAt":{"type":"string","format":"date-time"},"fields":{"type":"string","description":"Short list of the fields that moved, or 'new record' / 'record removed'"},"summary":{"type":["string","null"],"description":"One plain sentence, when summaries are on"},"runId":{"type":["string","null"],"description":"Agent run the change was tagged with"},"actor":{"type":"object","properties":{"tier":{"type":"string","enum":["exact","channel","inferred","unknown"],"description":"How sure the attribution is"},"kind":{"type":"string","enum":["staff","app","shopify","unknown","agent"]},"name":{"type":["string","null"]},"appTitle":{"type":["string","null"]},"note":{"type":["string","null"]},"label":{"type":"string","description":"What the app shows as the actor"}},"required":["tier","kind","name","appTitle","note","label"]},"diff":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"before":{},"after":{},"field":{"type":"string","description":"The field in merchant words (change detail only)"},"beforeText":{"type":"string","description":"The value before, as text: \"(empty)\", names instead of ids, an excerpt of long text"},"afterText":{"type":"string","description":"The value after, as text"}},"required":["path"]}},"beforeKnown":{"type":"boolean"}},"required":["id","resourceType","resourceId","resourceTitle","action","occurredAt","fields","summary","runId","actor","diff","beforeKnown"],"description":"A change with its full field diff."},"ChangeList":{"type":"object","properties":{"changes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"resourceType":{"type":"string","enum":["PRODUCT","COLLECTION","PAGE","BLOG","ARTICLE","MENU","THEME","METAFIELD_DEFINITION"]},"resourceId":{"type":"string","description":"Shopify gid"},"resourceTitle":{"type":["string","null"]},"action":{"type":"string","enum":["create","update","delete"]},"occurredAt":{"type":"string","format":"date-time"},"fields":{"type":"string","description":"Short list of the fields that moved, or 'new record' / 'record removed'"},"summary":{"type":["string","null"],"description":"One plain sentence, when summaries are on"},"runId":{"type":["string","null"],"description":"Agent run the change was tagged with"},"actor":{"type":"object","properties":{"tier":{"type":"string","enum":["exact","channel","inferred","unknown"],"description":"How sure the attribution is"},"kind":{"type":"string","enum":["staff","app","shopify","unknown","agent"]},"name":{"type":["string","null"]},"appTitle":{"type":["string","null"]},"note":{"type":["string","null"]},"label":{"type":"string","description":"What the app shows as the actor"}},"required":["tier","kind","name","appTitle","note","label"]}},"required":["id","resourceType","resourceId","resourceTitle","action","occurredAt","fields","summary","runId","actor"],"description":"One change to one record."}},"nextCursor":{"type":["string","null"],"description":"Pass as ?cursor= for the next page; null on the last page"},"limit":{"type":"integer"}},"required":["changes","nextCursor","limit"]},"PlanItem":{"type":"object","properties":{"path":{"type":"string","description":"Field path, e.g. title or variants[id=...].price"},"status":{"type":"string","enum":["ready","conflict","noop","unsupported"],"description":"ready: will be written back; conflict: changed again since; noop: already back; unsupported: LVNDR cannot write it"},"reason":{"type":["string","null"]},"current":{"description":"Live value now"},"target":{"description":"Value the undo writes"}},"required":["path","status","reason"],"description":"One field of an undo plan."},"UndoPlan":{"type":"object","properties":{"mode":{"type":"string","enum":["fields","delete","recreate"]},"counts":{"type":"object","properties":{"ready":{"type":"integer","minimum":0},"conflict":{"type":"integer","minimum":0},"noop":{"type":"integer","minimum":0},"unsupported":{"type":"integer","minimum":0}},"required":["ready","conflict","noop","unsupported"]},"items":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string","description":"Field path, e.g. title or variants[id=...].price"},"status":{"type":"string","enum":["ready","conflict","noop","unsupported"],"description":"ready: will be written back; conflict: changed again since; noop: already back; unsupported: LVNDR cannot write it"},"reason":{"type":["string","null"]},"current":{"description":"Live value now"},"target":{"description":"Value the undo writes"}},"required":["path","status","reason"],"description":"One field of an undo plan."}}},"required":["mode","counts","items"]},"UndoRun":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["done","partial","failed","pending"]},"ops":{"type":"array","items":{"type":"object","properties":{"op":{"type":"string"},"ok":{"type":"boolean"},"errors":{"type":"array","items":{"type":"string"}}},"required":["op","ok","errors"]}}},"required":["id","status","ops"],"description":"What an undo wrote: one entry per mutation."},"UndoResponse":{"type":"object","properties":{"plan":{"type":"object","properties":{"mode":{"type":"string","enum":["fields","delete","recreate"]},"counts":{"type":"object","properties":{"ready":{"type":"integer","minimum":0},"conflict":{"type":"integer","minimum":0},"noop":{"type":"integer","minimum":0},"unsupported":{"type":"integer","minimum":0}},"required":["ready","conflict","noop","unsupported"]},"items":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string","description":"Field path, e.g. title or variants[id=...].price"},"status":{"type":"string","enum":["ready","conflict","noop","unsupported"],"description":"ready: will be written back; conflict: changed again since; noop: already back; unsupported: LVNDR cannot write it"},"reason":{"type":["string","null"]},"current":{"description":"Live value now"},"target":{"description":"Value the undo writes"}},"required":["path","status","reason"],"description":"One field of an undo plan."}}},"required":["mode","counts","items"]},"items":{"type":"array","items":{"type":"object","description":"One field one change's undo would write (or leave alone), in merchant words.","properties":{"changeId":{"type":"string"},"record":{"type":"object","properties":{"id":{"type":"string","description":"Shopify gid"},"type":{"type":"string"},"title":{"type":["string","null"]}},"required":["id","type","title"]},"path":{"type":"string","description":"Internal field path; show `field` instead"},"field":{"type":"string","description":"The field in merchant words"},"current":{"type":"string","description":"Value in the store now, as text; \"(empty)\" when empty"},"target":{"type":"string","description":"Value the undo would write, as text"},"status":{"type":"string","enum":["ready","conflict","noop","unsupported"],"description":"ready = will be written; conflict = changed again since, left alone unless forced; noop = already back"},"reason":{"type":["string","null"]}},"required":["changeId","record","path","field","current","target","status","reason"]},"description":"What the undo would write, one entry per field per change, with the record, the field in merchant words and both values as text"},"planHash":{"type":"string","description":"Identifies what this dry run would undo. Send it back with the real run; the write is refused with 409 plan_changed if the store moved since."},"run":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["done","partial","failed","pending"]},"ops":{"type":"array","items":{"type":"object","properties":{"op":{"type":"string"},"ok":{"type":"boolean"},"errors":{"type":"array","items":{"type":"string"}}},"required":["op","ok","errors"]}}},"required":["id","status","ops"],"description":"What an undo wrote: one entry per mutation."},{"type":"null"}],"description":"null on a dry run. The undo record (UndoRun); kept for compatibility, see undoRunId"},"undoRunId":{"type":["string","null"],"description":"The undo record written (null on a dry run). Not an agent run id"},"resultChangeId":{"type":["string","null"],"description":"The change the undo's own write produced in the log, once Shopify has reported it (usually within a minute); null until then and on a dry run. Find it later with GET /changes?resourceId="},"nothingToUndo":{"type":"boolean","description":"true when the plan has nothing to write"}},"required":["plan","run"]},"Job":{"type":"object","description":"A multi-change undo running in the background. Poll GET /jobs/{id} (or lvndr_get_job) until status is done, partial or failed.","properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["run","batch","rollback","record","selection"]},"targetId":{"type":"string","description":"Run id, batch anchor change id, or restore point id"},"status":{"type":"string","enum":["queued","running","done","partial","failed"]},"total":{"type":"integer","description":"Changes the job covers"},"done":{"type":"integer"},"failed":{"type":"integer","description":"Failed or partly failed changes"},"skipped":{"type":"integer"},"remaining":{"type":"integer","description":"Changes beyond what one job covers; start another after this one"},"error":{"type":["string","null"],"description":"Why the job failed as a whole; starts with plan_changed when the change set moved since the preview"},"createdAt":{"type":"string","format":"date-time"},"startedAt":{"type":["string","null"],"format":"date-time"},"finishedAt":{"type":["string","null"],"format":"date-time"},"pollAfterMs":{"type":["integer","null"],"description":"While queued or running: poll again after this many milliseconds. null once the job is final."},"results":{"type":"array","description":"One entry per change handled so far, newest change first","items":{"type":"object","properties":{"changeId":{"type":"string"},"resourceTitle":{"type":["string","null"]},"action":{"type":"string"},"status":{"type":"string","enum":["done","partial","failed","skipped"]},"detail":{"type":"string"},"undoRunId":{"type":["string","null"]}},"required":["changeId","status","detail"]}}},"required":["id","kind","targetId","status","total","done","failed","skipped","createdAt","results"]},"UndoManyItem":{"type":"object","properties":{"changeId":{"type":"string"},"resourceTitle":{"type":["string","null"]},"action":{"type":"string"},"status":{"type":"string","enum":["planned","done","partial","failed","skipped"],"description":"planned only on a dry run"},"detail":{"type":"string"},"undoRunId":{"type":["string","null"]}},"required":["changeId","resourceTitle","action","status","detail","undoRunId"]},"PreviewItem":{"type":"object","description":"One field one change's undo would write (or leave alone), in merchant words.","properties":{"changeId":{"type":"string"},"record":{"type":"object","properties":{"id":{"type":"string","description":"Shopify gid"},"type":{"type":"string"},"title":{"type":["string","null"]}},"required":["id","type","title"]},"path":{"type":"string","description":"Internal field path; show `field` instead"},"field":{"type":"string","description":"The field in merchant words"},"current":{"type":"string","description":"Value in the store now, as text; \"(empty)\" when empty"},"target":{"type":"string","description":"Value the undo would write, as text"},"status":{"type":"string","enum":["ready","conflict","noop","unsupported"],"description":"ready = will be written; conflict = changed again since, left alone unless forced; noop = already back"},"reason":{"type":["string","null"]}},"required":["changeId","record","path","field","current","target","status","reason"]},"Batch":{"type":"object","properties":{"anchorId":{"type":"string"},"actorLabel":{"type":"string"},"changes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"resourceType":{"type":"string","enum":["PRODUCT","COLLECTION","PAGE","BLOG","ARTICLE","MENU","THEME","METAFIELD_DEFINITION"]},"resourceId":{"type":"string","description":"Shopify gid"},"resourceTitle":{"type":["string","null"]},"action":{"type":"string","enum":["create","update","delete"]},"occurredAt":{"type":"string","format":"date-time"},"fields":{"type":"string","description":"Short list of the fields that moved, or 'new record' / 'record removed'"},"summary":{"type":["string","null"],"description":"One plain sentence, when summaries are on"},"runId":{"type":["string","null"],"description":"Agent run the change was tagged with"},"actor":{"type":"object","properties":{"tier":{"type":"string","enum":["exact","channel","inferred","unknown"],"description":"How sure the attribution is"},"kind":{"type":"string","enum":["staff","app","shopify","unknown","agent"]},"name":{"type":["string","null"]},"appTitle":{"type":["string","null"]},"note":{"type":["string","null"]},"label":{"type":"string","description":"What the app shows as the actor"}},"required":["tier","kind","name","appTitle","note","label"]}},"required":["id","resourceType","resourceId","resourceTitle","action","occurredAt","fields","summary","runId","actor"],"description":"One change to one record."}}},"required":["anchorId","actorLabel","changes"],"description":"Everything one actor did with no gap over ten minutes around the anchor change."},"BatchUndo":{"type":"object","properties":{"anchorId":{"type":"string"},"actorLabel":{"type":"string"},"dryRun":{"type":"boolean"},"counts":{"type":"object","properties":{"planned":{"type":"integer","minimum":0},"done":{"type":"integer","minimum":0},"partial":{"type":"integer","minimum":0},"failed":{"type":"integer","minimum":0},"skipped":{"type":"integer","minimum":0}},"required":["planned","done","partial","failed","skipped"]},"results":{"type":"array","items":{"type":"object","properties":{"changeId":{"type":"string"},"resourceTitle":{"type":["string","null"]},"action":{"type":"string"},"status":{"type":"string","enum":["planned","done","partial","failed","skipped"],"description":"planned only on a dry run"},"detail":{"type":"string"},"undoRunId":{"type":["string","null"]}},"required":["changeId","resourceTitle","action","status","detail","undoRunId"]},"description":"Newest change first; a dry run plans the newest 50"},"total":{"type":"integer","description":"Changes the undo covers"},"more":{"type":"integer","description":"Changes the undo covers that the dry run did not plan"},"remaining":{"type":"integer","description":"Changes beyond what one undo job covers; undo again after it"},"planHash":{"type":"string","description":"Identifies what this dry run would undo. Send it back with the real run; the write is refused with 409 plan_changed if the store moved since."},"items":{"type":"array","items":{"type":"object","description":"One field one change's undo would write (or leave alone), in merchant words.","properties":{"changeId":{"type":"string"},"record":{"type":"object","properties":{"id":{"type":"string","description":"Shopify gid"},"type":{"type":"string"},"title":{"type":["string","null"]}},"required":["id","type","title"]},"path":{"type":"string","description":"Internal field path; show `field` instead"},"field":{"type":"string","description":"The field in merchant words"},"current":{"type":"string","description":"Value in the store now, as text; \"(empty)\" when empty"},"target":{"type":"string","description":"Value the undo would write, as text"},"status":{"type":"string","enum":["ready","conflict","noop","unsupported"],"description":"ready = will be written; conflict = changed again since, left alone unless forced; noop = already back"},"reason":{"type":["string","null"]}},"required":["changeId","record","path","field","current","target","status","reason"]},"description":"What the undo would write, one entry per field per change, with the record, the field in merchant words and both values as text"},"nothingToUndo":{"type":"boolean","description":"true when nothing in the preview would be written"}},"required":["anchorId","actorLabel","dryRun","counts","results"],"description":"A batch undo dry run. The real run answers 202 { job } instead."},"RunStart":{"type":"object","properties":{"run":{"type":"object","properties":{"id":{"type":"string"},"agent":{"type":"string"},"task":{"type":["string","null"]},"clientId":{"type":["string","null"]},"restorePointId":{"type":["string","null"]},"startedAt":{"type":"string","format":"date-time"},"endedAt":{"type":["string","null"],"format":"date-time"},"status":{"type":"string","enum":["open","ended"]},"changeCount":{"type":"integer"},"capture":{"type":"string","enum":["all-unattributed","client","none"],"description":"What the run collects: every unattributed or inferred change (keys with undo), only its OAuth client's changes, or nothing"}},"required":["id","agent","task","clientId","restorePointId","startedAt","endedAt","status","changeCount","capture"],"description":"An agent's announced unit of work. Changes made inside it are tagged with its id."},"capture":{"type":"string","enum":["all-unattributed","client","none"]},"captureNote":{"type":"string","description":"One line on what this run will collect, and why"},"warning":{"type":["string","null"],"description":"Set when the run will collect nothing (capture none): show it, the run cannot be undone as one"}},"required":["run","capture","captureNote"]},"RestorePoint":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["manual","burst","app_install","sweep"]},"label":{"type":"string"},"at":{"type":"string","format":"date-time"},"createdBy":{"type":["string","null"]},"runId":{"type":["string","null"]},"changesSince":{"type":"integer","description":"Changes after the point (single-point reads only)"}},"required":["id","kind","label","at","createdBy","runId"],"description":"A moment the store can be rolled back to."},"RollbackPreview":{"type":"object","properties":{"preview":{"type":"object","properties":{"pointId":{"type":"string"},"changes":{"type":"array","items":{"type":"object","properties":{"changeId":{"type":"string"},"resourceType":{"type":"string"},"resourceId":{"type":"string"},"resourceTitle":{"type":["string","null"]},"action":{"type":"string"},"occurredAt":{"type":"string","format":"date-time"},"mode":{"type":["string","null"]},"outcome":{"type":"string","enum":["restore","already-back","conflict","unsupported","error"]},"detail":{"type":"string"},"counts":{"type":"object","properties":{"ready":{"type":"integer","minimum":0},"conflict":{"type":"integer","minimum":0},"noop":{"type":"integer","minimum":0},"unsupported":{"type":"integer","minimum":0}},"required":["ready","conflict","noop","unsupported"]},"items":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"label":{"type":"string","description":"The field in plain words, e.g. 'Price · variant Blue / M'"},"status":{"type":"string","enum":["ready","conflict","noop","unsupported"]},"reason":{"type":["string","null"]}},"required":["path","label","status","reason"]}}},"required":["changeId","outcome","detail"]}},"totals":{"type":"object","properties":{"ready":{"type":"integer","minimum":0},"conflict":{"type":"integer","minimum":0},"noop":{"type":"integer","minimum":0},"unsupported":{"type":"integer","minimum":0}},"required":["ready","conflict","noop","unsupported"]},"outcomes":{"type":"object","properties":{"restore":{"type":"integer","minimum":0},"already-back":{"type":"integer","minimum":0},"conflict":{"type":"integer","minimum":0},"unsupported":{"type":"integer","minimum":0},"error":{"type":"integer","minimum":0}},"required":["restore","already-back","conflict","unsupported","error"]},"total":{"type":"integer"},"previewed":{"type":"integer"},"remaining":{"type":"integer"},"limit":{"type":"integer"},"items":{"type":"array","items":{"type":"object","description":"One field one change's undo would write (or leave alone), in merchant words.","properties":{"changeId":{"type":"string"},"record":{"type":"object","properties":{"id":{"type":"string","description":"Shopify gid"},"type":{"type":"string"},"title":{"type":["string","null"]}},"required":["id","type","title"]},"path":{"type":"string","description":"Internal field path; show `field` instead"},"field":{"type":"string","description":"The field in merchant words"},"current":{"type":"string","description":"Value in the store now, as text; \"(empty)\" when empty"},"target":{"type":"string","description":"Value the undo would write, as text"},"status":{"type":"string","enum":["ready","conflict","noop","unsupported"],"description":"ready = will be written; conflict = changed again since, left alone unless forced; noop = already back"},"reason":{"type":["string","null"]}},"required":["changeId","record","path","field","current","target","status","reason"]},"description":"What the undo would write, one entry per field per change, with the record, the field in merchant words and both values as text"}},"required":["pointId","changes","totals","outcomes","total","previewed","remaining","limit"]},"planHash":{"type":"string","description":"Identifies what this dry run would undo. Send it back with the real run; the write is refused with 409 plan_changed if the store moved since."},"nothingToUndo":{"type":"boolean","description":"true when nothing after the point would be written"}},"required":["preview"]},"RollbackResult":{"type":"object","properties":{"pointId":{"type":"string"},"counts":{"type":"object","properties":{"done":{"type":"integer","minimum":0},"partial":{"type":"integer","minimum":0},"failed":{"type":"integer","minimum":0},"skipped":{"type":"integer","minimum":0}},"required":["done","partial","failed","skipped"]},"remaining":{"type":"integer","description":"Changes one pass did not reach; run the rollback again"},"results":{"type":"array","items":{"type":"object","properties":{"changeId":{"type":"string"},"resourceTitle":{"type":["string","null"]},"action":{"type":"string"},"status":{"type":"string"},"detail":{"type":"string"}},"required":["changeId","resourceTitle","action","status","detail"]}}},"required":["pointId","counts","remaining","results"]},"Alert":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string"},"status":{"type":"string","enum":["open","dismissed","resolved"],"description":"resolved: a batch, run or rollback undo covering the burst finished"},"actorLabel":{"type":"string"},"count":{"type":"integer"},"windowStart":{"type":"string","format":"date-time"},"windowEnd":{"type":"string","format":"date-time"},"anchorChangeId":{"type":"string","description":"GET /batches/{id} with this for the burst"},"resourceTypes":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string","format":"date-time"}},"required":["id","kind","status","actorLabel","count","windowStart","windowEnd","anchorChangeId","resourceTypes","createdAt"],"description":"A burst: one actor changed many records in a short window."},"AgentRun":{"type":"object","properties":{"id":{"type":"string"},"agent":{"type":"string"},"task":{"type":["string","null"]},"clientId":{"type":["string","null"]},"restorePointId":{"type":["string","null"]},"startedAt":{"type":"string","format":"date-time"},"endedAt":{"type":["string","null"],"format":"date-time"},"status":{"type":"string","enum":["open","ended"]},"changeCount":{"type":"integer"},"capture":{"type":"string","enum":["all-unattributed","client","none"],"description":"What the run collects: every unattributed or inferred change (keys with undo), only its OAuth client's changes, or nothing"}},"required":["id","agent","task","clientId","restorePointId","startedAt","endedAt","status","changeCount","capture"],"description":"An agent's announced unit of work. Changes made inside it are tagged with its id."},"RunDetail":{"type":"object","properties":{"run":{"type":"object","properties":{"id":{"type":"string"},"agent":{"type":"string"},"task":{"type":["string","null"]},"clientId":{"type":["string","null"]},"restorePointId":{"type":["string","null"]},"startedAt":{"type":"string","format":"date-time"},"endedAt":{"type":["string","null"],"format":"date-time"},"status":{"type":"string","enum":["open","ended"]},"changeCount":{"type":"integer"},"capture":{"type":"string","enum":["all-unattributed","client","none"],"description":"What the run collects: every unattributed or inferred change (keys with undo), only its OAuth client's changes, or nothing"},"restorePoint":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["manual","burst","app_install","sweep"]},"label":{"type":"string"},"at":{"type":"string","format":"date-time"},"createdBy":{"type":["string","null"]},"runId":{"type":["string","null"]},"changesSince":{"type":"integer","description":"Changes after the point (single-point reads only)"}},"required":["id","kind","label","at","createdBy","runId"],"description":"A moment the store can be rolled back to."},{"type":"null"}]}},"required":["id","agent","task","clientId","restorePointId","startedAt","endedAt","status","changeCount","capture"],"description":"An agent's announced unit of work. Changes made inside it are tagged with its id."},"changes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"resourceType":{"type":"string","enum":["PRODUCT","COLLECTION","PAGE","BLOG","ARTICLE","MENU","THEME","METAFIELD_DEFINITION"]},"resourceId":{"type":"string","description":"Shopify gid"},"resourceTitle":{"type":["string","null"]},"action":{"type":"string","enum":["create","update","delete"]},"occurredAt":{"type":"string","format":"date-time"},"fields":{"type":"string","description":"Short list of the fields that moved, or 'new record' / 'record removed'"},"summary":{"type":["string","null"],"description":"One plain sentence, when summaries are on"},"runId":{"type":["string","null"],"description":"Agent run the change was tagged with"},"actor":{"type":"object","properties":{"tier":{"type":"string","enum":["exact","channel","inferred","unknown"],"description":"How sure the attribution is"},"kind":{"type":"string","enum":["staff","app","shopify","unknown","agent"]},"name":{"type":["string","null"]},"appTitle":{"type":["string","null"]},"note":{"type":["string","null"]},"label":{"type":"string","description":"What the app shows as the actor"}},"required":["tier","kind","name","appTitle","note","label"]}},"required":["id","resourceType","resourceId","resourceTitle","action","occurredAt","fields","summary","runId","actor"],"description":"One change to one record."}},"nextCursor":{"type":["string","null"]},"attributedThrough":{"type":["string","null"],"format":"date-time","description":"Changes that occurred before this time have been attributed and tagged with runs. Review the run once this is after your last write and pendingDeliveries is 0."},"pendingDeliveries":{"type":"integer","minimum":0,"description":"Shopify change deliveries for this store not processed yet"}},"required":["run","changes","nextCursor","attributedThrough","pendingDeliveries"]},"RunUndo":{"type":"object","properties":{"runId":{"type":"string"},"dryRun":{"type":"boolean"},"counts":{"type":"object","properties":{"planned":{"type":"integer","minimum":0},"done":{"type":"integer","minimum":0},"partial":{"type":"integer","minimum":0},"failed":{"type":"integer","minimum":0},"skipped":{"type":"integer","minimum":0}},"required":["planned","done","partial","failed","skipped"]},"results":{"type":"array","items":{"type":"object","properties":{"changeId":{"type":"string"},"resourceTitle":{"type":["string","null"]},"action":{"type":"string"},"status":{"type":"string","enum":["planned","done","partial","failed","skipped"],"description":"planned only on a dry run"},"detail":{"type":"string"},"undoRunId":{"type":["string","null"]}},"required":["changeId","resourceTitle","action","status","detail","undoRunId"]},"description":"Newest change first; a dry run plans the newest 50"},"total":{"type":"integer","description":"Changes the undo covers"},"more":{"type":"integer","description":"Changes the undo covers that the dry run did not plan"},"remaining":{"type":"integer","description":"Changes beyond what one undo job covers; undo again after it"},"planHash":{"type":"string","description":"Identifies what this dry run would undo. Send it back with the real run; the write is refused with 409 plan_changed if the store moved since."},"items":{"type":"array","items":{"type":"object","description":"One field one change's undo would write (or leave alone), in merchant words.","properties":{"changeId":{"type":"string"},"record":{"type":"object","properties":{"id":{"type":"string","description":"Shopify gid"},"type":{"type":"string"},"title":{"type":["string","null"]}},"required":["id","type","title"]},"path":{"type":"string","description":"Internal field path; show `field` instead"},"field":{"type":"string","description":"The field in merchant words"},"current":{"type":"string","description":"Value in the store now, as text; \"(empty)\" when empty"},"target":{"type":"string","description":"Value the undo would write, as text"},"status":{"type":"string","enum":["ready","conflict","noop","unsupported"],"description":"ready = will be written; conflict = changed again since, left alone unless forced; noop = already back"},"reason":{"type":["string","null"]}},"required":["changeId","record","path","field","current","target","status","reason"]},"description":"What the undo would write, one entry per field per change, with the record, the field in merchant words and both values as text"},"nothingToUndo":{"type":"boolean","description":"true when nothing in the preview would be written"}},"required":["runId","dryRun","counts","results"],"description":"A run undo dry run. The real run answers 202 { job } instead."},"Me":{"type":"object","properties":{"shop":{"type":"string"},"key":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string"},"scopes":{"type":"array","items":{"type":"string","enum":["read","undo","rollback","export"]}},"expiresAt":{"type":["string","null"],"format":"date-time"},"clientName":{"type":["string","null"]}},"required":["id","label","scopes","expiresAt","clientName"]},"plan":{"type":"object","properties":{"handle":{"type":"string"},"label":{"type":"string"}},"required":["handle","label"]},"limits":{"type":"object","additionalProperties":true}},"required":["shop","key","plan","limits"]},"Status":{"type":"object","properties":{"shop":{"type":"string"},"plan":{"type":"object","properties":{"handle":{"type":"string"},"label":{"type":"string"},"products":{"type":["integer","null"],"description":"null when unlimited"},"retentionDays":{"type":"integer"},"alerts":{"type":"boolean"},"api":{"type":"boolean"}},"required":["handle"]},"initialSyncAt":{"type":["string","null"],"format":"date-time"},"lastPolledAt":{"type":["string","null"],"format":"date-time"},"tracked":{"type":"object","additionalProperties":{"type":"integer"},"description":"Records tracked per resource type"},"deliveries":{"type":"object","additionalProperties":true}},"required":["shop","plan","initialSyncAt","lastPolledAt","tracked","deliveries"]},"RecordHistory":{"type":"object","properties":{"record":{"type":"object","properties":{"resourceId":{"type":"string"},"resourceType":{"type":["string","null"]},"title":{"type":["string","null"]},"deleted":{"type":"boolean"},"latest":{"anyOf":[{"type":"object","properties":{"version":{"type":"integer"},"capturedAt":{"type":"string","format":"date-time"},"source":{"type":"string"},"fields":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"value":{"type":"string"}},"required":["label","value"]}}},"required":["version","capturedAt","source","fields"]},{"type":"null"}]}},"required":["resourceId","resourceType","title","deleted","latest"]},"versions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"version":{"type":"integer"},"capturedAt":{"type":"string","format":"date-time"},"source":{"type":"string"},"sourceUpdatedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","version","capturedAt","source","sourceUpdatedAt"]},"description":"Newest 50"},"changes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"resourceType":{"type":"string","enum":["PRODUCT","COLLECTION","PAGE","BLOG","ARTICLE","MENU","THEME","METAFIELD_DEFINITION"]},"resourceId":{"type":"string","description":"Shopify gid"},"resourceTitle":{"type":["string","null"]},"action":{"type":"string","enum":["create","update","delete"]},"occurredAt":{"type":"string","format":"date-time"},"fields":{"type":"string","description":"Short list of the fields that moved, or 'new record' / 'record removed'"},"summary":{"type":["string","null"],"description":"One plain sentence, when summaries are on"},"runId":{"type":["string","null"],"description":"Agent run the change was tagged with"},"actor":{"type":"object","properties":{"tier":{"type":"string","enum":["exact","channel","inferred","unknown"],"description":"How sure the attribution is"},"kind":{"type":"string","enum":["staff","app","shopify","unknown","agent"]},"name":{"type":["string","null"]},"appTitle":{"type":["string","null"]},"note":{"type":["string","null"]},"label":{"type":"string","description":"What the app shows as the actor"}},"required":["tier","kind","name","appTitle","note","label"]}},"required":["id","resourceType","resourceId","resourceTitle","action","occurredAt","fields","summary","runId","actor"],"description":"One change to one record."}},"nextCursor":{"type":["string","null"]}},"required":["record","versions","changes","nextCursor"]}}}}