{"service":"liberty-agent-settlement","kind":"liberty-agent-settlement-errors","version":"0","mode":"demo","money":false,"persistence":false,"title":"Settlement error catalog","description":"Error codes the live Settlement API actually returns. Client-held demo protocol. Liberty does not persist jobs, take custody, or move real money. Demo API keys are optional — there is no auth failure code.","path":"/api/errors.json","human":"/#integrate","origin":"https://liberty-amber.vercel.app","note":"Derived from the quote / validate / transition / simulate / verify engine and HTTP wrappers. Codes are the `error` field on `{ ok: false, mode: demo, money: false }`. POST /api/v0/validate also adds `kind` (schema on 400, state on 409). GET /api/schemas/receipt.json for the receipt object shape verify accepts. Receipts are not proof of payment. Do not invent codes. money is always false.","honesty":{"mode":"demo","money":false,"persistence":false,"custody":false,"auth_required":false,"auth_error":false,"note":"Client-held demo. Liberty does not move real money. Missing demo keys still work (key_optional). There is no auth error code."},"kinds":["schema","state","http"],"errors":[{"id":"invalid_json","code":"invalid_json","kind":"schema","status":400,"message":"Body must be a JSON object.","when":"The POST body is missing, not an object, an array, or not parseable JSON.","fields":[],"routes":["validate","quote","transition","simulate","verify"]},{"id":"invalid_action","code":"invalid_action","kind":"schema","status":400,"message":"action must be create, fund, submit, release, or dispute.","when":"action is missing or not one of the route’s allowed actions. Verify only accepts release or dispute when an action is sent.","fields":["action"],"extra":["actions"],"routes":["validate","quote","transition","verify"]},{"id":"missing_field","code":"missing_field","kind":"schema","status":400,"message":"{field} is required.","when":"A required string or integer is omitted or blank, the current job object is missing on a non-create action, a submitted verify job has no action, or a receipt is missing claimed fee fields.","fields":["title","amount","criteria","job","payer_credits","proof_url","action","receipt","fee","agent_payout","returned_to_payer"],"routes":["validate","quote","transition","simulate","verify"]},{"id":"invalid_field","code":"invalid_field","kind":"schema","status":400,"message":"{field} must be a string / integer / https URL / ISO-8601 UTC datetime.","when":"A present field has the wrong type, is empty when it must not be, exceeds a max length, is sent on the wrong action, or hold-expiry fields conflict.","fields":["amount","payer_credits","ttl_seconds","expires_at","job.expiresAt","idempotency_key","client_ref","callback_url","proof_note","release_note","dispute_reason","proof_url","terminal","receipt","receipt.status","job.id","job.title","job.amount","job.criteria","job.status","job.createdAt","job.proofUrl"],"cases":[{"when":"Fund (or simulate fund) sends both expires_at and ttl_seconds.","message":"Send expires_at or ttl_seconds, not both.","fields":["expires_at","ttl_seconds"]},{"when":"expires_at is not an ISO-8601 UTC datetime, or is not in the future.","message":"expires_at must be an ISO-8601 UTC datetime. / expires_at must be in the future.","fields":["expires_at"]},{"when":"ttl_seconds is not an integer >= 1.","message":"ttl_seconds must be an integer >= 1.","fields":["ttl_seconds"]},{"when":"expires_at or ttl_seconds is sent on an action other than fund.","message":"expires_at is only accepted on fund. / ttl_seconds is only accepted on fund.","fields":["expires_at","ttl_seconds"]},{"when":"simulate terminal is not release or dispute.","message":"terminal must be release or dispute.","fields":["terminal"]}],"routes":["validate","quote","transition","simulate","verify"]},{"id":"illegal_transition","code":"illegal_transition","kind":"state","status":409,"message":"Cannot {action} a job in status {from}. {action} requires status {expected}.","when":"The client-held job is not in the status that action requires (fund needs open, submit needs funded, release/dispute need submitted). Verify also rejects a terminal job whose status does not match the requested action, or a non-submitted / non-terminal job.","fields":[],"extra":["action","from","expected"],"routes":["validate","quote","transition","verify"]},{"id":"insufficient_credits","code":"insufficient_credits","kind":"state","status":409,"message":"Need {needed} credits to fund. payer_credits is {payer_credits}.","when":"Fund (or the fund step inside simulate) is sent with payer_credits less than job.amount.","fields":["payer_credits"],"extra":["action","needed","payer_credits"],"routes":["validate","quote","transition","simulate"]},{"id":"hold_expired","code":"hold_expired","kind":"state","status":409,"message":"Cannot release after expiresAt. The hold ended at {expiresAt}. Dispute remains allowed.","when":"Release (quote, validate, transition, or the release terminal of simulate) is attempted after the funded job’s expiresAt. Dispute still refunds.","fields":["expiresAt"],"extra":["expiresAt"],"routes":["validate","quote","transition","simulate"]},{"id":"method_not_allowed","code":"method_not_allowed","kind":"http","status":405,"message":"POST JSON to this path. GET the protocol at /api/settlement.json.","when":"A Settlement function is called with a verb other than the ones it serves (POST/OPTIONS/GET on the engines; GET/HEAD/OPTIONS on protocol documents).","fields":[],"routes":["validate","quote","transition","simulate","verify","protocol"]}]}