{"openapi":"3.1.0","info":{"title":"Orizon Agents API","description":"The orchestration layer for autonomous digital labor: goal decomposition across a priced agent network, Soroban-settled payments and reputation on Stellar, and PDAX fiat on/off-ramping. Errors use a unified envelope — the legacy \"detail\" key plus an \"error\" object with a stable code, message, and request id.","contact":{"name":"Orizon Agents","url":"https://orizons.xyz/"},"version":"0.1.0"},"servers":[{"url":"https://orizon-agents-be-stellar.onrender.com","description":"production"}],"paths":{"/api/agents":{"get":{"tags":["agents"],"summary":"List registered agents","operationId":"list_agents_api_agents_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/Agent"},"type":"array","title":"Response List Agents Api Agents Get"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/agents/{agent_id}":{"get":{"tags":["agents"],"summary":"Get one agent by id","operationId":"get_agent_api_agents__agent_id__get","parameters":[{"name":"agent_id","in":"path","required":true,"schema":{"type":"string","title":"Agent Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Agent"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/agents/bind/endpoint-check":{"get":{"tags":["binding"],"summary":"Preflight an endpoint URL","description":"Advisory: would this URL be accepted? Pure — no DNS, no outbound request.\n\nExists so the form can show an inline field error with the reason instead\nof a bare 422, the same trade `agent_id_available` makes for agent ids.","operationId":"endpoint_check_api_agents_bind_endpoint_check_get","parameters":[{"name":"url","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":2048,"title":"Url"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndpointCheckResponse"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/agents/{agent_id}/unbind/challenge":{"post":{"tags":["binding"],"summary":"Mint an unbind challenge to sign","description":"Issue the nonce and the exact message the agent's owner must sign to\nrevoke the binding.\n\nNo request body: an unbind names no endpoint (see\n`external_binding.unbinding_message`), so there is nothing to supply.\n\nThe chain read comes first for `bind_challenge`'s reason — the bounded\nchallenge table may only ever hold real agent ids — and it has a second\nconsequence here worth stating: an agent the registry cannot name an owner\nfor cannot be unbound, because there is nobody to prove the revocation\nagainst. The deployed AgentRegistry has no way to remove an agent, so a\nbinding cannot be orphaned this way today; if one ever gains it, the removal\nentrypoint has to revoke the binding as part of the same change rather than\nleave an endpoint nobody can detach.","operationId":"unbind_challenge_api_agents__agent_id__unbind_challenge_post","parameters":[{"name":"agent_id","in":"path","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9_]{1,32}$","title":"Agent Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnbindChallengeResponse"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/agents/{agent_id}/bind/challenge":{"post":{"tags":["binding"],"summary":"Mint a binding challenge to sign","description":"Issue the nonce and the exact message the agent's owner must sign.","operationId":"bind_challenge_api_agents__agent_id__bind_challenge_post","parameters":[{"name":"agent_id","in":"path","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9_]{1,32}$","title":"Agent Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BindChallengeReq"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BindChallengeResponse"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/agents/{agent_id}/bind":{"post":{"tags":["binding"],"summary":"Bind an endpoint to an agent id","description":"Verify ownership and record the binding.\n\nThe order below IS acceptance criteria 2 and 4, not house style:\n\n1. **Endpoint policy first** — before any chain read, nonce lookup or\n   write, so a blocked URL provably never reaches the network and provably\n   stores nothing.\n2. **Signature shape** — a pure decode. Cheap, and it keeps a client bug\n   from costing an RPC round-trip.\n3. **Owner from the chain**, fail closed (see `_require_owner`).\n4. **Signature** — the nonce is consumed here and *only* on success, so an\n   RPC outage can never burn a pending operator's challenge. Note this is\n   also why owner resolution comes first: the nonce check happening before\n   any chain read would make this a free unauthenticated `owner_of`\n   amplifier, and consuming the nonce before the owner is known would let\n   an outage grief every pending bind.\n5. **Resolve-and-check DNS** — after authorization, so an anonymous caller\n   cannot use this as a free resolver.\n6. **Store.**","operationId":"bind_api_agents__agent_id__bind_post","parameters":[{"name":"agent_id","in":"path","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9_]{1,32}$","title":"Agent Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BindReq"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BindingResponse"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"delete":{"tags":["binding"],"summary":"Revoke an agent's endpoint binding","description":"Verify ownership and stop dispatching to the bound endpoint.\n\nThis is the operator's kill switch, and until it existed there was none. An\noperator whose host was compromised or decommissioned could not stop signed\ndispatch envelopes — carrying the buyer's intent, rationale and accumulated\ncontext — being delivered to it: `set_active(id, false)` only flips the\nmirrored marketplace status, the failure tracker only logs, and rebinding to\nsome other host merely redirected the traffic while every step failed\nagainst the operator's own reputation.\n\n`bind`'s ordering, minus the two endpoint-shaped steps (there is no URL to\npolicy-check and none to resolve):\n\n1. **Signature shape** — a pure decode, before any chain read.\n2. **Owner from the chain**, fail closed (`_require_owner`). Resolved LIVE,\n   never from `state.agents` or the record's own stored `owner`: an agent\n   that has changed hands must be revocable by whoever owns it NOW, and a\n   cached owner is the one thing an attacker who can wait could outlast.\n3. **Signature** — the nonce is consumed here and only on success, so an RPC\n   outage cannot burn a pending operator's challenge.\n4. **Tombstone the store, then forget the id.**\n\nStatus codes match `bind` exactly, including the deliberately\nnon-discriminating 401: one `not_agent_owner` covers \"no live challenge\",\n\"already used\", \"expired\" and \"signature does not verify\", so the route\ncannot be used to probe which agents exist or who owns them.\n\nREVOKING AN AGENT THAT IS NOT BOUND IS A 200, not a 404. The caller is\nasking for an end state — \"nothing is dispatched to this agent\" — and that\nend state holds, so the request succeeded. A 404 would report failure for a\nrequest that achieved exactly what it asked, and would push a client that\ncannot tell a lost response from a lost binding into retrying a revocation\nthat already worked. `was_bound` reports which of the two happened, for an\noperator who does need to know. A 204 was the other candidate and loses to\nthe same argument: it carries no body, so it could not say.","operationId":"unbind_api_agents__agent_id__bind_delete","parameters":[{"name":"agent_id","in":"path","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9_]{1,32}$","title":"Agent Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnbindReq"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnbindResponse"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/agents/{agent_id}/binding":{"get":{"tags":["binding"],"summary":"Read an agent's binding","description":"The current binding. AC-6's \"replaces the old endpoint\" is only\nobservable through this route.\n\nAnonymous callers get the **host only**: the binding is arguably public\ninfrastructure, but publishing the full path invites traffic that bypasses\nthe orchestrator entirely. A caller holding the operator key gets the\nwhole URL.","operationId":"read_binding_api_agents__agent_id__binding_get","parameters":[{"name":"agent_id","in":"path","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9_]{1,32}$","title":"Agent Id"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BindingResponse"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/agents/{agent_id}/readiness":{"get":{"tags":["binding"],"summary":"Operator readiness self-check: the next thing to fix","description":"Seven steps from registration to first settlement, each `done`, `todo`,\n`failed` or `unknown`, with the next action for anything not done. See\n`app/services/operator_readiness.py` for each step's source.\n\nPublic, like every fact it reports. The one cost it carries — a GET of the\nagent's bound endpoint — is paid at most once per agent per 30 s: the whole\nanswer is cached and single-flight. Nothing in the request reaches the\nprobe; it only ever fetches the URL already in the binding store, through\nthe dispatch path's SSRF guard, and neither the URL nor its host is\nreturned. An unknown agent id is a 200 whose `registered` step is `todo`.","operationId":"readiness_api_agents__agent_id__readiness_get","parameters":[{"name":"agent_id","in":"path","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9_]{1,32}$","title":"Agent Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__routers__binding__ReadinessResponse"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/orchestrator/decompose":{"post":{"tags":["orchestrator"],"summary":"Decompose an intent into a plan","operationId":"orchestrator_decompose_api_orchestrator_decompose_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecomposeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecomposeResponse"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/orchestrator/execute":{"post":{"tags":["orchestrator"],"summary":"Execute a stored plan","operationId":"orchestrator_execute_api_orchestrator_execute_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecuteRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecuteResponse"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/tasks":{"get":{"tags":["tasks"],"summary":"List recent tasks","operationId":"list_tasks_api_tasks_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TaskSummary"},"title":"Response List Tasks Api Tasks Get"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/tasks/{task_id}":{"get":{"tags":["tasks"],"summary":"Get a task's status","operationId":"get_task_api_tasks__task_id__get","parameters":[{"name":"task_id","in":"path","required":true,"schema":{"type":"string","title":"Task Id"}},{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Token"}},{"name":"X-Task-Token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Task-Token"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Task"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/tasks/{task_id}/artifact":{"get":{"tags":["tasks"],"summary":"Get a task's produced artifact","description":"Returns the code artifact produced by the workflow, if any.","operationId":"get_artifact_api_tasks__task_id__artifact_get","parameters":[{"name":"task_id","in":"path","required":true,"schema":{"type":"string","title":"Task Id"}},{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Token"}},{"name":"X-Task-Token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Task-Token"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArtifactResponse"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/disputes/challenge":{"post":{"tags":["disputes"],"summary":"Mint a dispute challenge to sign","description":"Issue the nonce and the exact string the payer's wallet must sign.\n\nThe handler itself decides nothing: it validates the two fields, calls the\nservice once, and renders the message the service defines. In particular it\ndoes NOT look up the settlement to decide whether a mint is allowed — the\nservice does that, for `bind_challenge`'s reason (a bounded challenge table\nkeyed on caller-supplied values may only ever hold pairs that could really\nbe disputed, or anyone can evict the challenges honest buyers are mid-way\nthrough signing). A second opinion here would be a rule with two homes.\n\nSo an unknown or unsettled job is refused at the mint, with the service's\nown code and status rather than a 500 — which is what `_refuse` is for, and\nwhy this cheap public route still has a `try`.\n\nThe expiry it answers with is deliberately COARSE (`_coarse_expiry`): the\nmint is idempotent inside the window, so an exact one would tell any\nanonymous caller how long ago somebody started disputing a step they can\nname. The idempotency stays — it is what keeps a flood from cancelling the\nnonce a buyer is mid-way through signing — and only the clock is blurred.\n\nOne client may mint `DISPUTE_CHALLENGE_RATE_LIMIT_PER_MINUTE` a minute\n(`_challenge_limiter`); past it, 429 `dispute_challenge_rate_limited` with\nRetry-After, before the settlement is read.","operationId":"dispute_challenge_api_disputes_challenge_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisputeChallengeReq"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisputeChallengeResponse"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/disputes/read-challenge":{"post":{"tags":["disputes"],"summary":"Mint a challenge the payer signs to read their disputes' free text","description":"The first half of D-067's fix: a nonce for the payer to sign.\n\nPublic, like `/disputes/challenge`, and safe for the same reasons: it mints\nonly for a task that has a settlement AND at least one dispute, into the\n`dispute_read` budget, and\na live challenge comes back as is, so a flood cannot cancel the one the\npayer is signing. The service decides; this renders.","operationId":"dispute_read_challenge_api_disputes_read_challenge_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisputeReadChallengeReq"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisputeReadChallengeResponse"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"`unknown_task`, or `no_settlement` — the task never settled, so there is no payer to prove; or `no_disputes` — it settled, but nothing was disputed, so there is nothing to read.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"`challenge_capacity_dispute_read` — every read-challenge slot is live. Ask again shortly.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/disputes/read-grant":{"post":{"tags":["disputes"],"summary":"Exchange the payer's read signature for a read grant","description":"The second half: verify the payer's signature and hand back a grant.\n\nThe grant goes back as `X-Dispute-Read-Grant` on `GET /tasks/{id}/disputes`\nand `GET /disputes/{id}`, and buys exactly the two free-text fields there.\nIt is not a task token and nothing treats it as one: no artifact, no trace,\nno stream. None of the opening rules are asked — the window may be long\nclosed — because reading what was said is not making a new claim.\n\nThe grant is never logged: it is a credential for its hour.","operationId":"dispute_read_grant_api_disputes_read_grant_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisputeReadGrantReq"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisputeReadGrantResponse"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"`not_the_payer` — the signature is not the settlement's payer's over this read challenge.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"`unknown_task` or `no_settlement`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"`challenge_unknown` — not this task's read challenge, or already used; `challenge_expired` — its five minutes are up. Either way, ask for a new one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/disputes":{"post":{"tags":["disputes"],"summary":"Open a dispute on a settled step","description":"Verify the payer's signature and record the dispute.\n\nEvery check — the challenge is live, the signature is the payer's, the\npayer is the wallet that actually paid this job, the step settled and was\ncharged, the window is still open — belongs to `dispute_svc.open_dispute`\nand is made there in one place, against one settlement record. Splitting\nany of it out to here would mean a rule with two homes and one of them\nunguarded: 4.03's resolution path calls the service, not this route.\n\n200, never 201, and never a second record: a repeat of a dispute already\nraised is answered with the first one (see `_duplicate_envelope`), so a\nbuyer who double-submits or refreshes sees what they filed rather than an\nerror they cannot act on.","operationId":"open_dispute_api_disputes_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenDisputeReq"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisputeResponse"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"This step is already disputed — the body carries the original dispute unchanged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DuplicateDisputeResponse"}}}}}}},"/api/disputes/{dispute_id}":{"get":{"tags":["disputes"],"summary":"Read one dispute","description":"The dispute, by the id `POST /disputes` returned.\n\nUnauthenticated by design: `dispute_store.new_dispute_id` mints an\nunguessable id, so the id IS the capability — the same trade the per-task\nread token makes, without a token to lose. A buyer with no account can\nstill come back to their dispute from a link.\n\nThat trade only ever held while the ids stayed unguessable, and they do\nnot: `GET /api/tasks/{id}/disputes` PUBLISHES them, and it is open while\nTASK_AUTH_REQUIRED is off, which is how production runs. So the id buys\nthe money facts — status, amounts, the refund hash — and the free text is\nbought separately, with the same proof that route asks for: a task token\nfor the task this dispute belongs to, the operator key, or a dispute read\ngrant the dispute's own payer earned by signature (D-067). The dispute\nnames its own task, so the caller supplies a credential and never a\nsecond id.\n\nThe id's exact format is deliberately not pinned in the path pattern. The\nstore mints it and 4.03 may lengthen it; a pattern here would make that a\ntwo-module change, and would answer a mistyped id with a 422 that says\n\"wrong shape\" where 404 says all a caller is entitled to know.","operationId":"get_dispute_api_disputes__dispute_id__get","parameters":[{"name":"dispute_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":64,"title":"Dispute Id"}},{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Token"}},{"name":"X-Task-Token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Task-Token"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}},{"name":"X-Dispute-Read-Grant","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Dispute-Read-Grant"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisputeResponse"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/tasks/{task_id}/disputes":{"get":{"tags":["disputes"],"summary":"A task's dispute window and the disputes raised on it","description":"The settlement, the window and what has been raised, in one read.\n\nLives here rather than in `routers/tasks.py` so the dispute surface is one\nmodule: `tasks.py` owns the in-memory task state and knows nothing about\nsettlements, and a route split across the two would have to be found twice.\n\nAn unsettled or unknown task is **not** a 404 — it is a null settlement, a\nnull window and an empty list, with `now` still set. The console polls this\nwhile a workflow runs, and the honest answer to \"can this be disputed yet?\"\nbefore settlement is \"no, and here is nothing\", not an error the UI has to\nspecial-case into the same view.\n\nTHE TASK ID IS NOT A CAPABILITY, and this route is built on the assumption\nthat it is not. While TASK_AUTH_REQUIRED is off — the shipped default, and\nhow production runs — it is open like every other `/tasks/{task_id}/...`\nread, and `GET /api/tasks?limit=200` hands out two hundred task ids for the\nasking. So in production this read is open, and what it may carry is\ndecided on that basis rather than on the gate.\n\nWith TASK_AUTH_REQUIRED ON it is gated, but NOT by `require_task_read`\n(D-067). That dependency admits a task token or the operator key and\nnothing else, and it ran before the handler — so a payer holding a dispute\nread grant, whose token died with the tab or the process, was answered 404\n`unknown_task` before the grant was ever looked at, from the one route that\nfeeds their receipt. It is gated here instead, on exactly what buys the\nfree text: `proof.proves_free_text` — the token or the key, which\n`require_task_read` would take, or a live grant for this task and its\nsettlement's payer. Nothing wider: a grant for another task, another payer\nor no settlement at all still reads as `unknown_task`. See\n`_require_listing_read`.\n\nWhat it carries openly is held to what is already public. The settlement's\njob id and payer are on-chain (see `SettlementView`), each output summary\nis the line the world-readable trace already showed, and every dispute's\namounts, statuses, timestamps and transaction hashes are facts about money\nthat moved or is owed. Nothing belongs on either shape that the chain or\nthe trace does not already publish.\n\nThe two fields that do not meet that standard are the HUMAN-WRITTEN ones —\neach dispute's `reason` and, on a rejection, `rejection_reason` — and they\nare withheld from a caller who has not proved they may read this task,\nwith the proof `require_task_read` would demand if it were switched on — a\ntask token, or the operator key — or with a dispute read grant, which the\ntask's payer earns by signing and which buys this free text and nothing\nthat `require_task_read` guards. See `DisputeResponse.of`. This route\nstays open to a shared trace link, which is the point of not simply\nturning the switch on; a shared link just does not come with the buyer's\nwords attached.","operationId":"list_task_disputes_api_tasks__task_id__disputes_get","parameters":[{"name":"task_id","in":"path","required":true,"schema":{"type":"string","title":"Task Id"}},{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Token"}},{"name":"X-Task-Token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Task-Token"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}},{"name":"X-Dispute-Read-Grant","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Dispute-Read-Grant"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskDisputesResponse"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/disputes/{dispute_id}/uphold":{"post":{"tags":["disputes"],"summary":"Uphold a dispute and credit the buyer","description":"Find for the buyer: credit the step back out of the settler's balance.\n\nThe guard is spelled on the decorator rather than hoisted onto a secured\nsub-router, `list_task_disputes`-style and for the same reason — with the\ndependency on the route, what admits a caller is readable at the route,\nand `tests/test_money_route_auth.py` pins both of this pair so a third\nadjudication route added without one fails there rather than in\nproduction.\n\nThis handler decides nothing about the money, exactly as `open_dispute`\ndecides nothing about the window. Whether the dispute may be upheld at\nall, how much is creditable once the step price and the settled total are\ntaken into account, and — the part that must never be duplicated — whether\na transfer has already been claimed for this dispute, all belong to\n`dispute_svc.uphold`. A second opinion here would be a second place that\ncould decide to sign.\n\nSo a REPEAT uphold is the service's answer, passed through unchanged: the\nsame terminal record, carrying the same `refund_tx`. Not an error, and\nemphatically not a second payout — an adjudicator who double-clicks, or a\nconsole that retries a dropped response, must be able to see what already\nhappened rather than be told something went wrong.","operationId":"uphold_dispute_api_disputes__dispute_id__uphold_post","security":[{"OperatorApiKey":[]}],"parameters":[{"name":"dispute_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":64,"title":"Dispute Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisputeResponse"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"`invalid_api_key` — no X-API-Key, or not the operator's. The two are one answer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"`unknown_dispute` — no dispute with that id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"The dispute cannot take this verdict: `dispute_not_open`, `dispute_rejected`, `refund_in_flight`, `settlement_missing`, `nothing_to_credit` or `refund_above_cap`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"`adjudication_not_configured` — no API_KEY is configured, so nobody can adjudicate; or, once the key has matched, `dispute_refunds_disabled` — the refund switch is off. Both are the operator's, never the caller's.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"502":{"description":"`refund_failed` — the ledger rejected the credit, so NOTHING moved and the dispute stays upheld.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"`refund_unconfirmed` — the credit was submitted and its outcome is unknown. It may still land, so it must be reconciled by hand and NEVER retried.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/disputes/{dispute_id}/reject":{"post":{"tags":["disputes"],"summary":"Reject a dispute, with a reason the buyer is shown","description":"Find for the platform: close the dispute without crediting anything.\n\nBehind `require_adjudicator` alongside `uphold_dispute`, although nothing\nhere signs. Rejecting is the other half of one decision, and the half that\nis CHEAP to make is exactly the half an attacker would reach for: a\nrejection is terminal, so an open reject route would let anyone close\nevery dispute raised against the platform before an adjudicator ever saw\none. The refund switch gates it too, for the same reason — a deployment\nthat cannot pay a dispute out must not be able to dispose of one either —\nbut only once the key has matched, so the switch's state is the\noperator's to read and nobody else's (D-052).\n\nThe note is REQUIRED and it is the buyer's to read — it comes back as the\ndispute's `rejection_reason`. The body is required with it, so no body, no\nnote, a null note and an empty one are all the same field-level 422, and\nthe service is never called. The note is then passed through rather than\ninterpreted: whether what is left of it after cleaning still says anything\nis the service's call, because only the service cleans it, and its\n`rejection_reason_required` reaches the adjudicator through `_refuse`\nlike every other code — 422, verbatim, with no mapping to add here.\n\nONE ANSWER HERE PRECEDES THE GUARD, deliberately. FastAPI decodes the body\nbefore it solves dependencies, so a body that is not JSON at all — `{not\njson` — is a 422 rather than the 401 this pair otherwise gives an\nanonymous caller (503 `adjudication_not_configured` on a keyless one). It\nwas worth checking what that discloses, and the answer is nothing:\n\n  * the ROUTE'S EXISTENCE is already disclosed by the guarded answer. A\n    well-formed anonymous POST here gets 401 `invalid_api_key`, where a\n    path that does not exist gets 404. Whoever the 422 would tell has\n    already been told;\n  * the SHAPE is not disclosed at all. A well-formed body with no `note`\n    is 401 too — the model is validated after the dependency like\n    everything else, and only an undecodable body is answered earlier. So\n    the 422 says \"this endpoint parses JSON\" and no more;\n  * NOTHING RUNS. No store read, no signature, no money — the request dies\n    in the body decode.\n\nTaking the body as a raw `Request` and parsing it by hand after the guard\nwould close it, at the cost of the declared model that makes every promise\nin the paragraph above, and of the request schema in the published spec.\nThat is a worse route in exchange for an answer nobody learns anything\nfrom. `tests/test_money_route_auth.py` pins the case so the next reader\nfinds a decision here rather than an oversight.","operationId":"reject_dispute_api_disputes__dispute_id__reject_post","security":[{"OperatorApiKey":[]}],"parameters":[{"name":"dispute_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":64,"title":"Dispute Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RejectDisputeReq"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisputeResponse"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"`invalid_api_key` — no X-API-Key, or not the operator's. The two are one answer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"`unknown_dispute` — no dispute with that id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"The dispute cannot take this verdict: `dispute_not_open`, `dispute_rejected`, `refund_in_flight`, `settlement_missing`, `nothing_to_credit` or `refund_above_cap`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"`adjudication_not_configured` — no API_KEY is configured, so nobody can adjudicate; or, once the key has matched, `dispute_refunds_disabled` — the refund switch is off. Both are the operator's, never the caller's.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/trace/{task_id}":{"get":{"tags":["trace"],"summary":"Get a task's recorded trace","operationId":"get_trace_api_trace__task_id__get","parameters":[{"name":"task_id","in":"path","required":true,"schema":{"type":"string","title":"Task Id"}},{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Token"}},{"name":"X-Task-Token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Task-Token"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TraceLine"},"title":"Response Get Trace Api Trace  Task Id  Get"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/trace/{task_id}/stream":{"get":{"tags":["trace"],"summary":"Stream a task's trace as SSE","description":"Server-Sent Events — replays the existing trace then streams live lines.\n\nThe task-auth guard accepts the read token as a `?token=` query parameter\nhere because EventSource cannot set request headers.\n\nClient disconnects are handled by sse-starlette cancelling the generator\n(the finally block unsubscribes); polling request.is_disconnected() here\nwould race sse-starlette's own listener for the one ASGI receive channel.","operationId":"stream_trace_api_trace__task_id__stream_get","parameters":[{"name":"task_id","in":"path","required":true,"schema":{"type":"string","title":"Task Id"}},{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Token"}},{"name":"X-Task-Token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Task-Token"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/metrics/overview":{"get":{"tags":["metrics"],"summary":"Dashboard overview metrics","description":"Blended dashboard metrics: live counters (agents online, completion,\ntrust) layered onto demo presentation baselines.","operationId":"overview_api_metrics_overview_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OverviewMetrics"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/flow/default":{"get":{"tags":["flow"],"summary":"Default agent-graph flow layout","operationId":"default_flow_api_flow_default_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Flow"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/payments/x402":{"post":{"tags":["payments"],"summary":"X402","description":"Simulated HTTP 402 flow.\n\nFirst call (no payment header): respond 402 with a challenge.\nSecond call with any non-empty X-Orizon-Payment header: respond 200 + receipt.","operationId":"x402_api_payments_x402_post","parameters":[{"name":"x-orizon-payment","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Orizon-Payment"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/X402Request"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/X402Response"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/stellar/network":{"get":{"tags":["stellar"],"summary":"Network","operationId":"network_api_stellar_network_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NetworkInfo"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/stellar/agent/{agent_id}":{"get":{"tags":["stellar"],"summary":"Read Agent","description":"Read an Agent from AgentRegistry.get(id).","operationId":"read_agent_api_stellar_agent__agent_id__get","parameters":[{"name":"agent_id","in":"path","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9_]{1,32}$","title":"Agent Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRead"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/stellar/agents/sync":{"post":{"tags":["stellar"],"summary":"Trigger Registry Sync","description":"Run one registry-sync pass now — the FE's post-registration fast path.\n\nAdvisory and idempotent (single-flight inside the service); the periodic\nloop remains the source of truth. Failure is a real answer here — the\ncaller falls back to polling /api/agents until the next interval lands.","operationId":"trigger_registry_sync_api_stellar_agents_sync_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncResponse"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/stellar/agent-id-available/{agent_id}":{"get":{"tags":["stellar"],"summary":"Agent Id Available","description":"Advisory pre-signature check for the registration form (id blur).\n\nDeliberately loose on the path param so a malformed id gets a friendly\n200 + reason instead of a bare 422 — the form shows the message inline.\nThe check is advisory only: the contract's AlreadyExists is the final\nanswer, and a race between this and submit is accepted (story 1.03).","operationId":"agent_id_available_api_stellar_agent_id_available__agent_id__get","parameters":[{"name":"agent_id","in":"path","required":true,"schema":{"type":"string","maxLength":64,"title":"Agent Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentIdAvailability"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/stellar/reputation":{"get":{"tags":["stellar"],"summary":"Read Reputations","description":"Smoothed reputation for every registered agent, plus the routing\nfloor and prior. Never fails: agents without on-chain evidence (or with\nthe chain unreachable) come back as the prior, marked source=\"prior\".","operationId":"read_reputations_api_stellar_reputation_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReputationBatch"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/stellar/reputation/params":{"get":{"tags":["stellar"],"summary":"Reputation Params","description":"The reputation system's parameter set — pure config, no RPC call.","operationId":"reputation_params_api_stellar_reputation_params_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReputationParams"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/stellar/reputation/{agent_id}":{"get":{"tags":["stellar"],"summary":"Read Reputation","description":"Smoothed reputation for one REGISTERED agent — cached\nReputationLedger.rep_state read with Bayesian prior smoothing; stale or\nprior fallback on a failed read.\n\n404 `unknown_agent` for an id the registry does not hold, answered before\nany RPC. The route used to read the chain for any id matching the\npattern: every unregistered id was a cache miss, so each one cost a\nSoroban round trip, and a stream of them queued enough reads to push the\nreal registry batch past its deadline (120 unknown ids degraded all 23\nagents) — an unauthenticated way to switch the routing floor off for\neveryone. 404 rather than the prior with no RPC: the prior would tell the\ncaller an id nobody registered is a routable newcomer, which is a claim,\nnot an absence; the frontend already treats 404 on this route as \"no such\nagent\". An agent registered on-chain but not yet indexed by the registry\nsync reads 404 until the next pass — it has no ratings to show yet anyway.","operationId":"read_reputation_api_stellar_reputation__agent_id__get","parameters":[{"name":"agent_id","in":"path","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9_]{1,32}$","title":"Agent Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReputationInfo"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/stellar/reputation/{agent_id}/invalidate":{"post":{"tags":["stellar"],"summary":"Drop one agent's cached reputation (operator only)","description":"Forget this process's cached rep_state for one agent, so its next read\n— a plan's routing, its stamp, this router's GET — comes from the ledger.\n\nFor a rating that landed from OUTSIDE this process: the uphold script\nrates in its own process, and `reputation_svc.invalidate_rep` there drops\nonly that process's cache, so without this the server kept serving the\npre-dispute score for up to `reputation_read_ttl_seconds` (D-066). The\nadjudication route needs none of this — it invalidates in-process.\n\nPer PROCESS, by construction: the cache is a module dict. The deployment\nruns one uvicorn worker (render.yaml `--workers 1`), so this process is the\nwhole service. A multi-worker deployment would reach one worker per call\nand must replace this with a shared invalidation (a shared cache, or a\nbroadcast) before it scales out.","operationId":"invalidate_reputation_api_stellar_reputation__agent_id__invalidate_post","security":[{"OperatorApiKey":[]}],"parameters":[{"name":"agent_id","in":"path","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9_]{1,32}$","title":"Agent Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvalidatedReputation"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/stellar/attestation/{job_id_hex}":{"get":{"tags":["stellar"],"summary":"Read Attestation","description":"Read an on-chain Attestation by hex-encoded 16-byte job_id.","operationId":"read_attestation_api_stellar_attestation__job_id_hex__get","parameters":[{"name":"job_id_hex","in":"path","required":true,"schema":{"type":"string","pattern":"^[0-9a-fA-F]{32}$","title":"Job Id Hex"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttestationRead"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/stellar/settlement/{agent_id}":{"get":{"tags":["stellar"],"summary":"Read Settlement","description":"On-chain settlement evidence for one agent: every `charged` event Soroban\nRPC still holds for it, with the platform's own payments separated out.\n\nDeliberately never 5xx, unlike the reads above. A scan that could not run\nanswers 200 with `unavailable` set and no entries, because the dashboard\nhas to be able to say WHY it is showing nothing — a 404 or a 503 here would\nleave it with an empty state indistinguishable from \"this agent has never\nbeen paid\". For the same reason an empty `entries` with `unavailable` null\nmeans \"nothing inside `window_days`\", and `total_stroops` counts only\ncharges proven to have come from someone other than us.","operationId":"read_settlement_api_stellar_settlement__agent_id__get","parameters":[{"name":"agent_id","in":"path","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9_]{1,32}$","title":"Agent Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettlementEvidence"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/stellar/build/register-agent":{"post":{"tags":["stellar"],"summary":"Build Register Agent","description":"Build unsigned XDR for AgentRegistry.register. Owner signs via Freighter.","operationId":"build_register_agent_api_stellar_build_register_agent_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterAgentReq"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/XdrResponse"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/stellar/build/update-price":{"post":{"tags":["stellar"],"summary":"Build Update Price","description":"Build unsigned XDR for AgentRegistry.update_price. Owner signs via Freighter.\n\nThe contract gates the write with agent.owner.require_auth(), so ownership is\nnot re-checked here — the FE only offers the action to the owner, and a\nnon-owner's signed tx fails on-chain. An unregistered id is refused as a\nplain 404 rather than surfacing as an opaque build failure after simulate.","operationId":"build_update_price_api_stellar_build_update_price_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePriceReq"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/XdrResponse"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/stellar/build/set-active":{"post":{"tags":["stellar"],"summary":"Build Set Active","description":"Build unsigned XDR for AgentRegistry.set_active (delist / relist). Owner signs.\n\nDelisting is reversible — set_active(id, true) relists — and never deletes:\nthe agent's on-chain record, history and reputation survive. Ownership is the\ncontract's require_auth; an unregistered id is refused as a plain 404.","operationId":"build_set_active_api_stellar_build_set_active_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetActiveReq"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/XdrResponse"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/stellar/build/authorize":{"post":{"tags":["stellar"],"summary":"Build Authorize","description":"Build unsigned XDR for PaymentEscrow.authorize (x402 pre-auth).\n\nThe signature is the same on both escrow versions, so this builder serves\nboth; what the payer's signature DOES differs (ADR 0010). On v1 it records\nan allowance that `charge` was meant to spend. On v2 it also moves\n`max_amount` into the escrow's custody in the same invocation — the payer's\none signature covers both — and that custody is paid out per delivered step\nby the settler's `settle`, the rest returned, or reclaimed by the payer\nonce `expires_at` has passed.\n\n`ttl_seconds` sets `expires_at`. On v2 it is when the payer may start\nreclaiming custody, not a deadline for the settler: `settle` still lands\nafter it until the payer reclaims, and whichever lands first wins (the\namended interface). `/execute` refuses an authorization whose remaining\nlife cannot cover a worst-case run of the plan\n(`execution_svc.worst_case_run_seconds`: the re-check's batch read, 125 s\nper step, 150 s for the settle — 902.5 s for the planner's six-step\nmaximum), so a run it starts is never racing a reclaim. The default of\n1800 s covers that with room for the wallet signature and the authorize to\nconfirm.","operationId":"build_authorize_api_stellar_build_authorize_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthorizeReq"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthorizeXdrResponse"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/stellar/build/reclaim":{"post":{"tags":["stellar"],"summary":"Build Reclaim","description":"Build unsigned XDR for PaymentEscrow v2 `reclaim(payer, auth_id)`. The payer signs.\n\nThe payer's way back to custody no settle ever spent: allowed once the\nauthorization has expired, and never after it was settled or reclaimed.\nEach of those is checked first with a read-only simulate and refused with\nits own 409 (`authorization_settled`, `authorization_revoked`,\n`authorization_locked`), so the wallet is never asked to sign a\ntransaction the contract will refuse. A v1 escrow holds no custody and\nanswers 409 `reclaim_unsupported`; an unreadable chain is 503\n`authorization_unverifiable` (ADR 0011).","operationId":"build_reclaim_api_stellar_build_reclaim_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReclaimReq"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/XdrResponse"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/stellar/submit":{"post":{"tags":["stellar"],"summary":"Submit Signed","description":"Submit a Freighter-signed transaction XDR.","operationId":"submit_signed_api_stellar_submit_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitReq"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Submit Signed Api Stellar Submit Post"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/stellar/server/charge":{"post":{"tags":["stellar"],"summary":"Server Charge","description":"Backend-signed PaymentEscrow.charge (the backend is the `settler` role). v1 only.\n\nPaymentEscrow v2 has no `charge`: a v2 run is paid by `settle`, per\ndelivered step, at the end of the run (ADR 0010). Against a v2 escrow this\nanswers 409 `charge_unsupported_on_v2` rather than a simulation failure\nthat reads like a transient fault.","operationId":"server_charge_api_stellar_server_charge_post","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChargeReq"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Server Charge Api Stellar Server Charge Post"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/stellar/server/seal":{"post":{"tags":["stellar"],"summary":"Server Seal","description":"Backend-signed AttestationRegistry.seal (backend is the `sealer` role).","operationId":"server_seal_api_stellar_server_seal_post","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SealReq"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Server Seal Api Stellar Server Seal Post"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/stellar/new-id":{"get":{"tags":["stellar"],"summary":"New Id","description":"Produce a random 16-byte id (hex) — useful for job_id / auth_id.","operationId":"new_id_api_stellar_new_id_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewIdResponse"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/ecosystem/adoption":{"get":{"tags":["ecosystem"],"summary":"External operator adoption against SOW §6.3, from on-chain facts","description":"Externally operated agents, their owners, and their verified settlements.\n\nEvery owner and every charge links to Stellar Expert. Agents owned by a\nteam wallet or a key this deployment holds are listed under `excluded`\nwith the reason, never counted. A read that failed sets `degraded` and\nnames the agent in `unreadable_agents`: the totals are then a floor, not\na zero. Settlements are read from Soroban RPC events, which the node keeps\nfor about seven days: `window_days` is the span the scans actually covered\n(the smallest, when agents' scans differ; 0 when none ran), and a\nsettlement older than that is not counted. Cached for about 30 s.\n\n503 only when no report could be produced at all — the per-read failures\nabove are answered in the report itself.","operationId":"adoption_api_ecosystem_adoption_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdoptionReport"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/pdax/environment":{"get":{"tags":["pdax"],"summary":"Environment","description":"Report the active PDAX environment + base URL (no secrets).","operationId":"environment_api_pdax_environment_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Environment Api Pdax Environment Get"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/pdax/health":{"get":{"tags":["pdax"],"summary":"Health","description":"Non-actuating liveness report, read straight from settings. This route\nis public, so it must never dial PDAX — anonymous callers could otherwise\ndrive repeated real logins (and lock the institutional account). The\nauthenticated /health/deep route performs the actual handshake probe.","operationId":"health_api_pdax_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Health Api Pdax Health Get"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/pdax/webhooks/receive":{"post":{"tags":["pdax"],"summary":"Webhook Receive","description":"Inbound endpoint PDAX POSTs crypto/fiat events to. Validates the\noptional HMAC signature, then parses the event into a typed model.","operationId":"webhook_receive_api_pdax_webhooks_receive_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Webhook Receive Api Pdax Webhooks Receive Post"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/pdax/reference":{"get":{"tags":["pdax"],"summary":"Reference","description":"All PDAX accepted-value tables the frontend forms need.","operationId":"reference_api_pdax_reference_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Reference Api Pdax Reference Get"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/pdax/reference/banks":{"get":{"tags":["pdax"],"summary":"Reference Banks","description":"Bank / e-wallet display name → PDAX bank code.","operationId":"reference_banks_api_pdax_reference_banks_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Reference Banks Api Pdax Reference Banks Get"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/pdax/reference/tokens":{"get":{"tags":["pdax"],"summary":"Reference Tokens","description":"Supported crypto token → network (Stellar tokens flagged).","operationId":"reference_tokens_api_pdax_reference_tokens_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Reference Tokens Api Pdax Reference Tokens Get"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/pdax/reference/countries":{"get":{"tags":["pdax"],"summary":"Reference Countries","description":"Accepted country list (case-sensitive).","operationId":"reference_countries_api_pdax_reference_countries_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Reference Countries Api Pdax Reference Countries Get"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/pdax/health/deep":{"get":{"tags":["pdax"],"summary":"Health Deep","description":"Actuating dependency check (API-key guarded): probes the PDAX auth\nhandshake and reports ok / degraded / unconfigured — never exposing\ncredentials. When API_KEY is unset the guard above is a no-op, so the\nprobe is skipped instead: an anonymous caller could otherwise drive\nrepeated real logins, exactly what /health refuses to allow.","operationId":"health_deep_api_pdax_health_deep_get","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Health Deep Api Pdax Health Deep Get"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/pdax/trade/price":{"get":{"tags":["pdax"],"summary":"Trade Price","description":"Indicative (non-binding) price for a pair.","operationId":"trade_price_api_pdax_trade_price_get","parameters":[{"name":"quote_currency","in":"query","required":true,"schema":{"type":"string","title":"Quote Currency"}},{"name":"side","in":"query","required":true,"schema":{"enum":["buy","sell"],"type":"string","title":"Side"}},{"name":"base_quantity","in":"query","required":true,"schema":{"type":"string","title":"Base Quantity"}},{"name":"base_currency","in":"query","required":false,"schema":{"type":"string","default":"PHP","title":"Base Currency"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Quote"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/pdax/trade/price/v2":{"get":{"tags":["pdax"],"summary":"Trade Price V2","description":"Indicative price (v2 — receive-side currency + quantity).","operationId":"trade_price_v2_api_pdax_trade_price_v2_get","parameters":[{"name":"quote_currency","in":"query","required":true,"schema":{"type":"string","title":"Quote Currency"}},{"name":"side","in":"query","required":true,"schema":{"enum":["buy","sell"],"type":"string","title":"Side"}},{"name":"currency","in":"query","required":true,"schema":{"type":"string","title":"Currency"}},{"name":"quantity","in":"query","required":true,"schema":{"type":"string","title":"Quantity"}},{"name":"base_currency","in":"query","required":false,"schema":{"type":"string","default":"PHP","title":"Base Currency"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Quote"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/pdax/trade/quote":{"post":{"tags":["pdax"],"summary":"Trade Quote","description":"Firm quote (expires in ~15s) acceptable via /trade/order.","operationId":"trade_quote_api_pdax_trade_quote_post","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FirmQuoteRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Quote"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/pdax/trade/quote/v2":{"post":{"tags":["pdax"],"summary":"Trade Quote V2","description":"Firm quote (v2).","operationId":"trade_quote_v2_api_pdax_trade_quote_v2_post","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FirmQuoteV2Request"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Quote"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/pdax/trade/order":{"post":{"tags":["pdax"],"summary":"Trade Order","description":"Accept a firm quote and execute the trade.","operationId":"trade_order_api_pdax_trade_order_post","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Order"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/pdax/trade/orders/{order_id}":{"get":{"tags":["pdax"],"summary":"Get order details","description":"Details of a single executed order by its PDAX order id.","operationId":"trade_order_details_api_pdax_trade_orders__order_id__get","parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"integer","title":"Order Id"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Order"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/pdax/trade/orders":{"get":{"tags":["pdax"],"summary":"List orders","description":"Executed orders, paginated and optionally filtered by date range.","operationId":"trade_orders_api_pdax_trade_orders_get","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","default":1,"title":"Page"}},{"name":"pageSize","in":"query","required":false,"schema":{"type":"integer","default":10,"title":"Pagesize"}},{"name":"startDate","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Startdate"}},{"name":"endDate","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Enddate"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrdersResponse"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/pdax/crypto/deposit":{"get":{"tags":["pdax"],"summary":"Crypto Deposit","description":"Wallet address to deposit a crypto token, e.g. currency=USDCXLM.","operationId":"crypto_deposit_api_pdax_crypto_deposit_get","parameters":[{"name":"currency","in":"query","required":true,"schema":{"type":"string","title":"Currency"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CryptoDepositAddress"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/pdax/fiat/deposit":{"post":{"tags":["pdax"],"summary":"Fiat Deposit","description":"Initiate a PHP cash-in; returns a payment_checkout_url.","operationId":"fiat_deposit_api_pdax_fiat_deposit_post","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FiatDepositRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FiatDepositResult"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/pdax/fiat/withdraw":{"post":{"tags":["pdax"],"summary":"Fiat Withdraw","description":"Withdraw PHP to a bank / e-wallet beneficiary.","operationId":"fiat_withdraw_api_pdax_fiat_withdraw_post","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FiatWithdrawRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FiatWithdrawResult"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/pdax/fiat/user-info-upload":{"post":{"tags":["pdax"],"summary":"Fiat User Info Upload","description":"Upload sender/beneficiary travel-rule data for a fiat withdrawal.","operationId":"fiat_user_info_upload_api_pdax_fiat_user_info_upload_post","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FiatWithdrawRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FiatWithdrawResult"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/pdax/crypto/withdraw":{"post":{"tags":["pdax"],"summary":"Crypto Withdraw","description":"Send a crypto token to an external address (e.g. USDCXLM).","operationId":"crypto_withdraw_api_pdax_crypto_withdraw_post","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CryptoOutRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CryptoOutResult"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/pdax/fiat/transactions":{"get":{"tags":["pdax"],"summary":"Fiat Transactions","description":"Track PHP cash-in/out by mode (CashIn/CashOut) or identifier.","operationId":"fiat_transactions_api_pdax_fiat_transactions_get","parameters":[{"name":"mode","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mode"}},{"name":"identifier","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Identifier"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","default":1,"title":"Page"}},{"name":"pageSize","in":"query","required":false,"schema":{"type":"integer","default":10,"title":"Pagesize"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FiatTransactionsResponse"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/pdax/crypto/transactions":{"get":{"tags":["pdax"],"summary":"Crypto Transactions","description":"Track crypto deposits/withdrawals by identifier, hash, or type.","operationId":"crypto_transactions_api_pdax_crypto_transactions_get","parameters":[{"name":"identifier","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Identifier"}},{"name":"txn_hash","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Txn Hash"}},{"name":"type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Type"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","default":1,"title":"Page"}},{"name":"pageSize","in":"query","required":false,"schema":{"type":"integer","default":10,"title":"Pagesize"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CryptoTransactionsResponse"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/pdax/balances":{"get":{"tags":["pdax"],"summary":"Balances","description":"View balances for all assets (or a single currency).","operationId":"balances_api_pdax_balances_get","parameters":[{"name":"currency","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Currency"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BalancesResponse"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/pdax/webhooks/register":{"post":{"tags":["pdax"],"summary":"Webhook Register","description":"Register this backend's URL to receive crypto or fiat events.","operationId":"webhook_register_api_pdax_webhooks_register_post","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookRegisterRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookRegistration"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/pdax/ramp/estimate":{"post":{"tags":["pdax"],"summary":"Ramp Estimate","description":"Indicative conversion preview. `currency` denominates `amount`; pass\ncurrency=USDC on an on-ramp to price a target USDC amount (workflow cost).","operationId":"ramp_estimate_api_pdax_ramp_estimate_post","parameters":[{"name":"direction","in":"query","required":true,"schema":{"enum":["onramp","offramp"],"type":"string","title":"Direction"}},{"name":"amount","in":"query","required":true,"schema":{"type":"string","title":"Amount"}},{"name":"currency","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Currency"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RampEstimate"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/pdax/ramp/funding-quote":{"post":{"tags":["pdax"],"summary":"Ramp Funding Quote","description":"Pesos to pay to fund a workflow costing `usdc` USDC — buffered + rounded\nup so the amount always covers it.","operationId":"ramp_funding_quote_api_pdax_ramp_funding_quote_post","parameters":[{"name":"usdc","in":"query","required":true,"schema":{"type":"string","title":"Usdc"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FundingQuote"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/pdax/ramp/onramp":{"post":{"tags":["pdax"],"summary":"Ramp Onramp","description":"Start a PHP → USDCXLM ramp. Returns a checkout URL for the buyer to pay;\nsettlement is completed by the fiat-deposit webhook.","operationId":"ramp_onramp_api_pdax_ramp_onramp_post","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnRampRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RampRecord"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/pdax/ramp/offramp":{"post":{"tags":["pdax"],"summary":"Ramp Offramp","description":"Start a USDCXLM → PHP ramp. Returns a deposit address for the agent to\nsend USDC to; settlement is completed by the crypto-deposit webhook.","operationId":"ramp_offramp_api_pdax_ramp_offramp_post","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OffRampRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RampRecord"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/pdax/ramp":{"get":{"tags":["pdax"],"summary":"Ramp List","description":"Ramps tracked this process lifetime (insertion order), paginated.\nAccount numbers are masked to their last 4 digits in this bulk view.","operationId":"ramp_list_api_pdax_ramp_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Ramp List Api Pdax Ramp Get"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/pdax/ramp/{ramp_id}":{"get":{"tags":["pdax"],"summary":"Ramp Status","description":"Current state + stage history of a single ramp.","operationId":"ramp_status_api_pdax_ramp__ramp_id__get","parameters":[{"name":"ramp_id","in":"path","required":true,"schema":{"type":"string","title":"Ramp Id"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RampRecord"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/pdax/ramp/{ramp_id}/reconcile":{"post":{"tags":["pdax"],"summary":"Ramp Reconcile","description":"Check PDAX for settlement and advance the ramp — used by the UI to track\nprogress without relying on PDAX's redirect page.","operationId":"ramp_reconcile_api_pdax_ramp__ramp_id__reconcile_post","parameters":[{"name":"ramp_id","in":"path","required":true,"schema":{"type":"string","title":"Ramp Id"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RampRecord"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — retry after the indicated delay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unhandled server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/health":{"get":{"tags":["meta"],"summary":"Liveness probe (proxy-reachable)","description":"Byte-for-byte the root `/health` body, reachable through the frontend's\n`/api/*` proxy so the browser and external monitors can confirm the\nbackend is up.","operationId":"health_api_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}}}}},"/":{"get":{"tags":["meta"],"summary":"Service identity ping","operationId":"root__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Root  Get"}}}}}}},"/health":{"get":{"tags":["meta"],"summary":"Liveness probe","description":"Liveness probe — process is up and serving. The body comes from the\nshared `health_payload()`, so this route and the proxy-reachable\n`/api/health` (routers/health.py) always answer identically.","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}}}}},"/readiness":{"get":{"tags":["meta"],"summary":"Readiness probe with per-dependency status","description":"503 only when a dependency the API cannot serve without is missing:\nthe LLM key or the Stellar contract/RPC config. The signing key is\ndeliberately informational — read-only deployments are legitimate — and\nso is `cold_start`: a floor that shuts newcomers out is a policy the\nprocess serves correctly, not a dependency it lacks. `ratings` is\ninformational on the signing key's own grounds: a deployment that cannot\nwrite ratings still serves every request.","operationId":"readiness_readiness_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__main__ReadinessResponse"}}}},"503":{"description":"A required dependency is not configured.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__main__ReadinessResponse"}}}}}}}},"components":{"schemas":{"AdoptionAgent":{"properties":{"agent_id":{"type":"string","title":"Agent Id"},"name":{"type":"string","title":"Name"},"active":{"type":"boolean","title":"Active"},"bound":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Bound"},"settled_workflows":{"items":{"$ref":"#/components/schemas/SettledWorkflow"},"type":"array","title":"Settled Workflows"}},"type":"object","required":["agent_id","name","active","bound","settled_workflows"],"title":"AdoptionAgent"},"AdoptionCounts":{"properties":{"external_agents":{"type":"integer","title":"External Agents"},"unique_operator_wallets":{"type":"integer","title":"Unique Operator Wallets"},"settled_external_workflows":{"type":"integer","title":"Settled External Workflows"}},"type":"object","required":["external_agents","unique_operator_wallets","settled_external_workflows"],"title":"AdoptionCounts"},"AdoptionMet":{"properties":{"external_agents":{"type":"boolean","title":"External Agents"},"unique_operator_wallets":{"type":"boolean","title":"Unique Operator Wallets"},"settled_external_workflows":{"type":"boolean","title":"Settled External Workflows"}},"type":"object","required":["external_agents","unique_operator_wallets","settled_external_workflows"],"title":"AdoptionMet"},"AdoptionOperator":{"properties":{"owner":{"type":"string","title":"Owner"},"owner_explorer":{"type":"string","title":"Owner Explorer"},"agents":{"items":{"$ref":"#/components/schemas/AdoptionAgent"},"type":"array","title":"Agents"}},"type":"object","required":["owner","owner_explorer","agents"],"title":"AdoptionOperator"},"AdoptionReport":{"properties":{"network":{"type":"string","title":"Network"},"generated_at":{"type":"integer","title":"Generated At"},"window_days":{"type":"number","title":"Window Days"},"targets":{"$ref":"#/components/schemas/AdoptionCounts"},"totals":{"$ref":"#/components/schemas/AdoptionCounts"},"met":{"$ref":"#/components/schemas/AdoptionMet"},"operators":{"items":{"$ref":"#/components/schemas/AdoptionOperator"},"type":"array","title":"Operators"},"excluded":{"items":{"$ref":"#/components/schemas/ExcludedOwner"},"type":"array","title":"Excluded"},"degraded":{"type":"boolean","title":"Degraded"},"unreadable_agents":{"items":{"type":"string"},"type":"array","title":"Unreadable Agents"}},"type":"object","required":["network","generated_at","window_days","targets","totals","met","operators","excluded","degraded","unreadable_agents"],"title":"AdoptionReport","description":"SOW §6.3's answer, with the limits of what was looked at.\n\n`window_days` is how far back `settled_external_workflows` can see. The\nsettled workflows come from `settlement_svc`'s scan of Soroban RPC events,\nwhich the node keeps for about seven days, so an older settlement is not\ncounted. It is the scan's MEASURED span (`SettlementEvidence.window_days`),\nnot a constant: when the per-agent scans cover different spans, it is the\nsmallest, so \"settled in the last N days\" holds for every agent. Only scans\nthat ran count toward it; an agent whose scan did not run is already named\nin `unreadable_agents`. 0 when no scan ran, e.g. no external agents."},"Agent":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"skills":{"items":{"type":"string"},"type":"array","title":"Skills"},"price":{"type":"number","title":"Price"},"rep":{"type":"number","title":"Rep"},"status":{"type":"string","enum":["online","idle","offline"],"title":"Status"},"runs":{"type":"integer","title":"Runs"},"real":{"type":"boolean","title":"Real","default":false},"owner":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Owner"},"source":{"type":"string","enum":["seeded","onchain"],"title":"Source","default":"seeded"},"bound":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Bound"}},"type":"object","required":["id","name","skills","price","rep","status","runs"],"title":"Agent"},"AgentIdAvailability":{"properties":{"available":{"type":"boolean","title":"Available"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message"},"owner":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Owner"}},"type":"object","required":["available"],"title":"AgentIdAvailability"},"AgentRead":{"properties":{"agent":{"title":"Agent"}},"type":"object","required":["agent"],"title":"AgentRead"},"ArtifactResponse":{"properties":{"artifact":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Artifact"},"charge_tx":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Charge Tx"},"proof_tx":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Proof Tx"}},"type":"object","title":"ArtifactResponse","description":"Response shape for /tasks/{task_id}/artifact.\n\nMirrors the fields the frontend consumes: `artifact` carries the\nCodeArtifact-shaped dict (`preview_html` for the iframe, `files[]` for\nthe code viewer), plus the on-chain charge/proof transaction hashes."},"AttestationRead":{"properties":{"attestation":{"title":"Attestation"}},"type":"object","required":["attestation"],"title":"AttestationRead"},"AuthorizeReq":{"properties":{"payer":{"type":"string","pattern":"^G[A-Z2-7]{55}$","title":"Payer"},"agent_id":{"type":"string","pattern":"^[A-Za-z0-9_]{1,32}$","title":"Agent Id"},"max_amount_usdc":{"type":"number","maximum":10000.0,"exclusiveMinimum":0.0,"title":"Max Amount Usdc"},"ttl_seconds":{"type":"integer","maximum":3600.0,"minimum":30.0,"title":"Ttl Seconds","default":1800}},"type":"object","required":["payer","agent_id","max_amount_usdc"],"title":"AuthorizeReq"},"AuthorizeXdrResponse":{"properties":{"xdr":{"type":"string","title":"Xdr"},"expires_at":{"type":"integer","title":"Expires At"}},"type":"object","required":["xdr","expires_at"],"title":"AuthorizeXdrResponse"},"Balance":{"properties":{"currency":{"type":"string","title":"Currency"},"available":{"type":"string","title":"Available"},"hold":{"type":"string","title":"Hold","default":"0"},"total":{"type":"string","title":"Total"},"asset_type":{"type":"string","title":"Asset Type"}},"type":"object","required":["currency","available","total","asset_type"],"title":"Balance"},"BalancesResponse":{"properties":{"balances":{"items":{"$ref":"#/components/schemas/Balance"},"type":"array","title":"Balances"}},"type":"object","required":["balances"],"title":"BalancesResponse","description":"Envelope for the balances list route."},"BindChallengeReq":{"properties":{"endpoint_url":{"type":"string","maxLength":2048,"minLength":8,"title":"Endpoint Url"}},"type":"object","required":["endpoint_url"],"title":"BindChallengeReq"},"BindChallengeResponse":{"properties":{"agent_id":{"type":"string","title":"Agent Id"},"nonce":{"type":"string","title":"Nonce"},"message":{"type":"string","title":"Message"},"expires_at":{"type":"number","title":"Expires At"},"ttl_seconds":{"type":"integer","title":"Ttl Seconds"}},"type":"object","required":["agent_id","nonce","message","expires_at","ttl_seconds"],"title":"BindChallengeResponse"},"BindReq":{"properties":{"endpoint_url":{"type":"string","maxLength":2048,"minLength":8,"title":"Endpoint Url"},"signature":{"type":"string","maxLength":256,"minLength":1,"title":"Signature","description":"base64 ed25519 signature"}},"type":"object","required":["endpoint_url","signature"],"title":"BindReq"},"BindingResponse":{"properties":{"agent_id":{"type":"string","title":"Agent Id"},"endpoint_url":{"type":"string","title":"Endpoint Url"},"owner":{"type":"string","title":"Owner"},"bound_at":{"type":"number","title":"Bound At"},"replaced":{"type":"boolean","title":"Replaced"}},"type":"object","required":["agent_id","endpoint_url","owner","bound_at","replaced"],"title":"BindingResponse"},"ChargeReq":{"properties":{"auth_id_hex":{"type":"string","pattern":"^[0-9a-fA-F]{32}$","title":"Auth Id Hex"},"amount_usdc":{"type":"number","maximum":10000.0,"exclusiveMinimum":0.0,"title":"Amount Usdc"},"job_id_hex":{"type":"string","pattern":"^[0-9a-fA-F]{32}$","title":"Job Id Hex"}},"type":"object","required":["auth_id_hex","amount_usdc","job_id_hex"],"title":"ChargeReq"},"ColdStartReadiness":{"properties":{"routable":{"type":"boolean","title":"Routable"},"lower_bound_bps":{"type":"integer","title":"Lower Bound Bps"},"floor_bps":{"type":"integer","title":"Floor Bps"},"margin_bps":{"type":"integer","title":"Margin Bps"}},"type":"object","required":["routable","lower_bound_bps","floor_bps","margin_bps"],"title":"ColdStartReadiness","description":"Whether this deployment can route an agent that has never been rated.\n\nThe startup line from `_report_cold_start_routability` says the same\nthing, once per boot — and on the free tier a boot is every wake from idle,\nso by the time anyone asks, the line is buried under a request log or gone\nwith the instance that wrote it. This puts the verdict behind a probe that\nanswers whenever it is asked, for the configuration actually in force: the\nRender dashboard overrides render.yaml, so no repo file can say what it is.\n\nInformational only — it never moves `status`, for the startup check's own\nreason. Readiness answers \"can this process serve\"; a floor above the\nprior's bound serves every request correctly and simply hires nobody new,\nwhich is a policy an operator may intend (a curated network), not a missing\ndependency. A not-ready answer would also misfire twice over: it would fail\nprobes on a deployment that is working as configured, and a monitor keyed on\nthe status would page someone about a decision rather than a fault.\n\nEvery field is copied from `reputation_svc.cold_start_margin()` rather than\nrecomputed, so this answer and the startup line cannot disagree. None of it\nis secret: the floor and the prior inputs are already public on\n/api/stellar/reputation/params, and the rest is arithmetic over them."},"CreditPolicy":{"properties":{"credited_fraction":{"type":"number","title":"Credited Fraction"},"funded_by":{"type":"string","const":"platform","title":"Funded By"},"adjudicated_by":{"type":"string","const":"platform","title":"Adjudicated By"}},"type":"object","required":["credited_fraction","funded_by","adjudicated_by"],"title":"CreditPolicy","description":"The terms an upheld dispute is paid under, as the buyer is shown them.\n\nExists so the receipt can state the policy BEFORE the buyer signs anything,\nfrom the same setting the payout reads: ADR 0002 promises buyer and\noperator the terms in advance, and a dispute button that only reveals what\nit pays once it has been pressed does not keep that promise.\n\n`funded_by` and `adjudicated_by` are the trust model `refund_svc` discloses\n— the platform's own wallet pays the credit, and the platform decides the\nclaim, with no on-chain arbitration behind it. Single-value literals, so\nthe schema itself says there is no other answer today: the day there is\none, widening the literal is a deliberate contract change rather than a\nstring that quietly started meaning something else."},"CryptoDepositAddress":{"properties":{"currency":{"type":"string","title":"Currency"},"address":{"type":"string","title":"Address"},"tag":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tag"}},"type":"object","required":["currency","address"],"title":"CryptoDepositAddress","description":"Payload for GET /v1/crypto/deposit?currency=USDCXLM."},"CryptoOutRequest":{"properties":{"identifier":{"type":"string","title":"Identifier"},"currency":{"type":"string","title":"Currency","description":"Token symbol, e.g. USDCXLM"},"amount":{"type":"string","title":"Amount"},"address":{"type":"string","title":"Address"},"tag":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tag","default":""},"beneficiary_first_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Beneficiary First Name"},"beneficiary_last_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Beneficiary Last Name"},"beneficiary_exchange":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Beneficiary Exchange"},"send_to_self":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Send To Self","default":"false"},"beneficiary_wallet":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Beneficiary Wallet","default":"false"}},"type":"object","required":["identifier","currency","amount","address"],"title":"CryptoOutRequest","description":"Body for POST /v1/crypto/withdraw."},"CryptoOutResult":{"properties":{"identifier":{"type":"string","title":"Identifier"},"transaction_id":{"type":"integer","title":"Transaction Id"},"transaction_hash":{"type":"string","title":"Transaction Hash","default":""},"amount":{"type":"string","title":"Amount"},"address":{"type":"string","title":"Address"},"tag":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tag"},"total":{"type":"string","title":"Total"},"fee":{"type":"string","title":"Fee"},"currency":{"type":"string","title":"Currency"},"status":{"type":"string","title":"Status","default":"IN PROGRESS"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At"}},"type":"object","required":["identifier","transaction_id","amount","address","total","fee","currency"],"title":"CryptoOutResult","description":"Response from POST /v1/crypto/withdraw."},"CryptoTransaction":{"properties":{"transaction_id":{"type":"integer","title":"Transaction Id"},"type":{"type":"string","title":"Type","description":"crypto_in | crypto_out"},"debit_ccy":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Debit Ccy"},"credit_ccy":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Credit Ccy"},"debit_amount":{"type":"string","title":"Debit Amount","default":"0"},"debit_net_amount":{"type":"string","title":"Debit Net Amount","default":"0"},"credit_amount":{"type":"string","title":"Credit Amount","default":"0"},"credit_net_amount":{"type":"string","title":"Credit Net Amount","default":"0"},"fee_amount":{"type":"string","title":"Fee Amount","default":"0"},"status":{"type":"string","title":"Status"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At"},"txn_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Txn Hash"},"sender_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sender Email"},"sender_wallet_address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sender Wallet Address"},"sender_wallet_address_tag":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sender Wallet Address Tag"},"receiver_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Receiver Email"},"receiver_wallet_address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Receiver Wallet Address"},"receiver_wallet_address_tag":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Receiver Wallet Address Tag"},"identifier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Identifier"}},"type":"object","required":["transaction_id","type","status"],"title":"CryptoTransaction","description":"One crypto deposit/withdrawal record."},"CryptoTransactionsResponse":{"properties":{"transactions":{"items":{"$ref":"#/components/schemas/CryptoTransaction"},"type":"array","title":"Transactions"}},"type":"object","required":["transactions"],"title":"CryptoTransactionsResponse","description":"Envelope for the crypto transaction-history list route."},"DecomposeRequest":{"properties":{"intent":{"type":"string","maxLength":500,"minLength":3,"title":"Intent"}},"type":"object","required":["intent"],"title":"DecomposeRequest"},"DecomposeResponse":{"properties":{"plan_id":{"type":"string","title":"Plan Id"},"intent":{"type":"string","title":"Intent"},"steps":{"items":{"$ref":"#/components/schemas/PlanStep"},"type":"array","title":"Steps"},"total_usdc":{"type":"number","title":"Total Usdc"},"total_eta":{"type":"number","title":"Total Eta"},"notices":{"items":{"$ref":"#/components/schemas/PlanFloorNotice"},"type":"array","title":"Notices"},"floor_bps":{"type":"integer","title":"Floor Bps","default":0},"reputation_degraded":{"type":"boolean","title":"Reputation Degraded","default":false},"planner_fallback":{"type":"boolean","title":"Planner Fallback","default":false}},"type":"object","required":["plan_id","intent","steps","total_usdc","total_eta"],"title":"DecomposeResponse"},"DisputeChallengeReq":{"properties":{"job_id_hex":{"type":"string","pattern":"^[0-9a-fA-F]{32}$","title":"Job Id Hex"},"step_index":{"type":"integer","maximum":63.0,"minimum":0.0,"title":"Step Index"}},"type":"object","required":["job_id_hex","step_index"],"title":"DisputeChallengeReq","description":"What the wallet is about to sign is derived from these two, so both are\nsupplied when the challenge is minted rather than first seen at open time."},"DisputeChallengeResponse":{"properties":{"message":{"type":"string","title":"Message"},"nonce":{"type":"string","title":"Nonce"},"expires_at":{"type":"number","title":"Expires At"}},"type":"object","required":["message","nonce","expires_at"],"title":"DisputeChallengeResponse"},"DisputeReadChallengeReq":{"properties":{"task_id":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,128}$","title":"Task Id"}},"type":"object","required":["task_id"],"title":"DisputeReadChallengeReq","description":"Which task's disputes the payer is about to prove they may read (D-067)."},"DisputeReadChallengeResponse":{"properties":{"nonce":{"type":"string","title":"Nonce"},"message":{"type":"string","title":"Message"},"expires_at":{"type":"number","title":"Expires At"}},"type":"object","required":["nonce","message","expires_at"],"title":"DisputeReadChallengeResponse"},"DisputeReadGrantReq":{"properties":{"task_id":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,128}$","title":"Task Id"},"nonce":{"type":"string","maxLength":128,"minLength":1,"title":"Nonce"},"signature_b64":{"type":"string","maxLength":256,"minLength":1,"title":"Signature B64","description":"base64 ed25519 signature"}},"type":"object","required":["task_id","nonce","signature_b64"],"title":"DisputeReadGrantReq","description":"The payer's signature over the read challenge. No `payer` field: the\nsigner is checked against the settlement's payer and nobody else, so there\nis nothing for the caller to claim."},"DisputeReadGrantResponse":{"properties":{"grant":{"type":"string","title":"Grant"},"expires_at":{"type":"number","title":"Expires At"}},"type":"object","required":["grant","expires_at"],"title":"DisputeReadGrantResponse"},"DisputeResponse":{"properties":{"id":{"type":"string","title":"Id"},"job_id_hex":{"type":"string","title":"Job Id Hex"},"task_id":{"type":"string","title":"Task Id"},"step_index":{"type":"integer","title":"Step Index"},"agent_id":{"type":"string","title":"Agent Id"},"payer":{"type":"string","title":"Payer"},"reason":{"type":"string","title":"Reason"},"status":{"type":"string","enum":["open","upheld","crediting","credited","rejected"],"title":"Status"},"charged_usdc":{"type":"number","title":"Charged Usdc"},"creditable_usdc":{"type":"number","title":"Creditable Usdc"},"opened_at":{"type":"number","title":"Opened At"},"resolved_at":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Resolved At"},"refund_tx":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refund Tx"},"rating_tx":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rating Tx"},"credited_usdc":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Credited Usdc"},"updated_at":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Updated At"},"rating_confirmed":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Rating Confirmed"},"rejection_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rejection Reason"},"reason_withheld":{"type":"boolean","title":"Reason Withheld","default":false}},"type":"object","required":["id","job_id_hex","task_id","step_index","agent_id","payer","reason","status","charged_usdc","creditable_usdc","opened_at"],"title":"DisputeResponse","description":"One dispute, as the console and the buyer's client read it.\n\nA flat mirror of `dispute_store.DisputeRecord` rather than the record\nitself: the record is a storage shape that 4.03 and 4.04 will add columns\nto, and returning it directly would publish each of those as API the moment\nit landed."},"DisputesReadiness":{"properties":{"store":{"type":"string","enum":["postgres","memory"],"title":"Store"},"reconcile":{"$ref":"#/components/schemas/RefundReconcileReadiness"}},"type":"object","required":["store","reconcile"],"title":"DisputesReadiness","description":"Which store holds settlements and disputes in this process (D-063).\n\n`postgres` when DATABASE_URL is set, `memory` otherwise — and `memory`\nloses every settlement and dispute on restart (D-058), which is the check\nan operator runs after a deploy. The boot log names it too; this is for\nwhoever cannot read that log, or reads it after a restart took the line.\n\nThe KIND of store only, never the DSN or anything derived from it: the DSN\ncarries the database password. It reports the selection, not a live\nconnection — the probe dials nothing, and a Postgres that is unreachable\nis answered by the first request that needs it, loudly, never by a quiet\nfall back to memory.\n\nInformational, like `cold_start`: an in-memory store serves every request."},"DuplicateDisputeResponse":{"properties":{"detail":{"type":"string","title":"Detail"},"error":{"additionalProperties":{"type":"string"},"type":"object","title":"Error"},"dispute":{"$ref":"#/components/schemas/DisputeResponse"}},"type":"object","required":["detail","error","dispute"],"title":"DuplicateDisputeResponse","description":"The `duplicate_dispute` 409 body: the error envelope, plus the dispute.\n\nOne dispute per `(job_id, step)` is a product rule, and the second attempt\nis answered with the FIRST dispute unchanged — that is the acceptance\ncriterion, and a bare error code cannot satisfy it. Declared as a model so\nthe schema says so and the frontend can read `dispute` off the 409 instead\nof issuing a second request to find out what it already has."},"EndpointCheckResponse":{"properties":{"allowed":{"type":"boolean","title":"Allowed"},"rule":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rule"},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message"}},"type":"object","required":["allowed"],"title":"EndpointCheckResponse"},"ErrorBody":{"properties":{"code":{"type":"string","title":"Code"},"message":{"type":"string","title":"Message"},"request_id":{"type":"string","title":"Request Id"}},"type":"object","required":["code","message","request_id"],"title":"ErrorBody","description":"Structured half of the unified error envelope."},"ErrorEnvelope":{"properties":{"detail":{"title":"Detail"},"error":{"$ref":"#/components/schemas/ErrorBody"}},"type":"object","required":["detail","error"],"title":"ErrorEnvelope","description":"Every error response body: the legacy FastAPI \"detail\" (string or\nvalidation-error list) plus the structured \"error\" object.\n\nDeclared here rather than in `app/main.py`, which assembles it: a router\nthat wants to document a status of its own has to NAME this model in its\n`responses=`, and `main` imports the routers, so it cannot be the one to\nhold it. The schema name is what reaches the spec, so moving it changed\nnothing a client can see."},"EscrowReadiness":{"properties":{"contract":{"type":"string","title":"Contract"},"version":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Version"}},"type":"object","required":["contract","version"],"title":"EscrowReadiness","description":"Which PaymentEscrow this process settles through, and its version (ADR 0010).\n\n`version` is 2 when runs are settled per delivered step through custody,\n1 when they go through v1's `charge`, and null until this process has read\nit. Never read on the probe's path: the answer is the client's cache, and a\nprobe that finds none starts one background read for the next probe to\nsee, the way `ratings` refreshes. Informational, like the rest."},"ExcludedOwner":{"properties":{"owner":{"type":"string","title":"Owner"},"owner_explorer":{"type":"string","title":"Owner Explorer"},"reason":{"type":"string","enum":["team_wallet","platform_key"],"title":"Reason"},"role":{"type":"string","title":"Role"},"agent_ids":{"items":{"type":"string"},"type":"array","title":"Agent Ids"}},"type":"object","required":["owner","owner_explorer","reason","role","agent_ids"],"title":"ExcludedOwner"},"ExecuteRequest":{"properties":{"plan_id":{"type":"string","maxLength":64,"title":"Plan Id"},"auth_id_hex":{"anyOf":[{"type":"string","pattern":"^[0-9a-fA-F]{32}$"},{"type":"null"}],"title":"Auth Id Hex"},"payer":{"anyOf":[{"type":"string","pattern":"^G[A-Z2-7]{55}$"},{"type":"null"}],"title":"Payer"}},"type":"object","required":["plan_id"],"title":"ExecuteRequest"},"ExecuteResponse":{"properties":{"task_id":{"type":"string","title":"Task Id"},"read_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Read Token"}},"type":"object","required":["task_id"],"title":"ExecuteResponse"},"FiatDepositRequest":{"properties":{"amount":{"type":"string","maxLength":32,"title":"Amount"},"method":{"type":"string","maxLength":64,"title":"Method","description":"See FIAT_DEPOSIT_METHODS"},"identifier":{"type":"string","maxLength":128,"title":"Identifier","description":"Unique client identifier"},"currency":{"type":"string","title":"Currency","description":"PHP only","default":"PHP"},"sender_first_name":{"type":"string","maxLength":200,"title":"Sender First Name"},"sender_middle_name":{"type":"string","title":"Sender Middle Name","default":"n.a."},"sender_last_name":{"type":"string","maxLength":200,"title":"Sender Last Name"},"sender_country_origin":{"type":"string","maxLength":100,"title":"Sender Country Origin"},"sender_address_line_one":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sender Address Line One"},"sender_address_line_two":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sender Address Line Two"},"sender_city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sender City"},"sender_province":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sender Province"},"sender_country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sender Country"},"sender_zip_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sender Zip Code"},"sender_phone_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sender Phone Number"},"sender_nationality":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sender Nationality"},"sender_national_identity_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sender National Identity Number"},"sender_dob":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sender Dob","description":"mm-dd-yyyy"},"sender_place_of_birth":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sender Place Of Birth"},"source_of_funds":{"type":"string","title":"Source Of Funds"},"sender_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sender Email"},"beneficiary_first_name":{"type":"string","title":"Beneficiary First Name"},"beneficiary_middle_name":{"type":"string","title":"Beneficiary Middle Name","default":"n.a."},"beneficiary_last_name":{"type":"string","title":"Beneficiary Last Name"},"beneficiary_sex":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Beneficiary Sex"},"beneficiary_nationality":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Beneficiary Nationality"},"beneficiary_dob":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Beneficiary Dob"},"beneficiary_address_line_one":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Beneficiary Address Line One"},"beneficiary_address_line_two":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Beneficiary Address Line Two"},"beneficiary_barangay":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Beneficiary Barangay"},"beneficiary_city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Beneficiary City"},"beneficiary_province":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Beneficiary Province"},"beneficiary_country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Beneficiary Country"},"beneficiary_zip_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Beneficiary Zip Code"},"beneficiary_government_issued_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Beneficiary Government Issued Id"},"beneficiary_phone_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Beneficiary Phone Number"},"purpose":{"type":"string","title":"Purpose"},"relationship_of_sender_to_beneficiary":{"type":"string","title":"Relationship Of Sender To Beneficiary"},"nature_of_business":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nature Of Business"}},"type":"object","required":["amount","method","identifier","sender_first_name","sender_last_name","sender_country_origin","source_of_funds","beneficiary_first_name","beneficiary_last_name","purpose","relationship_of_sender_to_beneficiary"],"title":"FiatDepositRequest","description":"Body for POST /v1/fiat/deposit. Many sender fields are conditionally\nrequired for amounts ≥ 50,000 PHP (travel rule); kept optional here and\nenforced by the service layer."},"FiatDepositResult":{"properties":{"request_id":{"type":"string","title":"Request Id"},"identifier":{"type":"string","title":"Identifier"},"reference_number":{"type":"string","title":"Reference Number"},"amount":{"type":"number","title":"Amount"},"method":{"type":"string","title":"Method"},"payment_checkout_url":{"type":"string","title":"Payment Checkout Url"},"fee":{"type":"number","title":"Fee"},"status":{"type":"string","title":"Status","default":"PENDING"}},"type":"object","required":["request_id","identifier","reference_number","amount","method","payment_checkout_url","fee"],"title":"FiatDepositResult","description":"Response from POST /v1/fiat/deposit."},"FiatTransaction":{"properties":{"request_id":{"type":"string","title":"Request Id"},"transaction_id":{"type":"integer","title":"Transaction Id"},"amount":{"type":"string","title":"Amount"},"fee":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fee"},"method":{"type":"string","title":"Method"},"mode":{"type":"string","title":"Mode","description":"CashIn | CashOut"},"reference_number":{"type":"string","title":"Reference Number"},"fulfilled_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fulfilled At"},"declined_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Declined At"},"rejection_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rejection Reason"},"currency":{"type":"string","title":"Currency","default":"PHP"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At"},"updated_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Updated At"},"status":{"type":"string","title":"Status"},"identifier":{"type":"string","title":"Identifier"},"fee_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fee Type"},"retried_methods":{"items":{"$ref":"#/components/schemas/RetryMethod"},"type":"array","title":"Retried Methods"}},"type":"object","required":["request_id","transaction_id","amount","method","mode","reference_number","status","identifier"],"title":"FiatTransaction","description":"One fiat deposit/withdrawal record."},"FiatTransactionsResponse":{"properties":{"transactions":{"items":{"$ref":"#/components/schemas/FiatTransaction"},"type":"array","title":"Transactions"}},"type":"object","required":["transactions"],"title":"FiatTransactionsResponse","description":"Envelope for the fiat transaction-history list route."},"FiatWithdrawRequest":{"properties":{"identifier":{"type":"string","maxLength":160,"title":"Identifier"},"amount":{"type":"string","maxLength":64,"title":"Amount"},"currency":{"type":"string","maxLength":64,"title":"Currency","description":"PHP only","default":"PHP"},"method":{"type":"string","maxLength":64,"title":"Method","description":"PAY-TO-ACCOUNT-REAL-TIME | -NON-REAL-TIME"},"fee_type":{"type":"string","maxLength":64,"title":"Fee Type","description":"Sender | Beneficiary"},"sender_first_name":{"type":"string","maxLength":200,"title":"Sender First Name"},"sender_middle_name":{"type":"string","maxLength":200,"title":"Sender Middle Name","default":"n.a."},"sender_last_name":{"type":"string","maxLength":200,"title":"Sender Last Name"},"sender_country_origin":{"type":"string","maxLength":200,"title":"Sender Country Origin"},"sender_address_line_one":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Sender Address Line One"},"sender_address_line_two":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Sender Address Line Two"},"sender_city":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Sender City"},"sender_province":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Sender Province"},"sender_country":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Sender Country"},"sender_zip_code":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Sender Zip Code"},"sender_phone_number":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Sender Phone Number"},"sender_nationality":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Sender Nationality"},"sender_national_identity_number":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Sender National Identity Number"},"sender_dob":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Sender Dob"},"sender_place_of_birth":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Sender Place Of Birth"},"source_of_funds":{"type":"string","maxLength":200,"title":"Source Of Funds"},"sender_email":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Sender Email"},"beneficiary_first_name":{"type":"string","maxLength":200,"title":"Beneficiary First Name"},"beneficiary_middle_name":{"type":"string","maxLength":200,"title":"Beneficiary Middle Name","default":"n.a."},"beneficiary_last_name":{"type":"string","maxLength":200,"title":"Beneficiary Last Name"},"beneficiary_sex":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Beneficiary Sex"},"beneficiary_nationality":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Beneficiary Nationality"},"beneficiary_dob":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Beneficiary Dob"},"beneficiary_bank_code":{"type":"string","maxLength":200,"title":"Beneficiary Bank Code"},"beneficiary_account_name":{"type":"string","maxLength":200,"title":"Beneficiary Account Name"},"beneficiary_account_number":{"type":"string","maxLength":200,"title":"Beneficiary Account Number"},"beneficiary_address_line_one":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Beneficiary Address Line One"},"beneficiary_address_line_two":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Beneficiary Address Line Two"},"beneficiary_barangay":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Beneficiary Barangay"},"beneficiary_city":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Beneficiary City"},"beneficiary_province":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Beneficiary Province"},"beneficiary_country":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Beneficiary Country"},"beneficiary_zip_code":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Beneficiary Zip Code"},"beneficiary_government_issued_id":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Beneficiary Government Issued Id"},"beneficiary_phone_number":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Beneficiary Phone Number"},"purpose":{"type":"string","maxLength":200,"title":"Purpose"},"relationship_of_sender_to_beneficiary":{"type":"string","maxLength":200,"title":"Relationship Of Sender To Beneficiary"},"nature_of_business":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Nature Of Business"},"instructions":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Instructions"}},"type":"object","required":["identifier","amount","method","fee_type","sender_first_name","sender_last_name","sender_country_origin","source_of_funds","beneficiary_first_name","beneficiary_last_name","beneficiary_bank_code","beneficiary_account_name","beneficiary_account_number","purpose","relationship_of_sender_to_beneficiary"],"title":"FiatWithdrawRequest","description":"Body for POST /v1/fiat/withdraw."},"FiatWithdrawResult":{"properties":{"request_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Request Id"},"identifier":{"type":"string","title":"Identifier"},"reference_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reference Number"},"amount":{"type":"number","title":"Amount"},"method":{"type":"string","title":"Method"},"retry_methods":{"items":{"$ref":"#/components/schemas/RetryMethod"},"type":"array","title":"Retry Methods"},"status":{"type":"string","title":"Status","default":"PENDING"},"fee":{"type":"number","title":"Fee","default":0}},"type":"object","required":["identifier","amount","method"],"title":"FiatWithdrawResult","description":"Response from POST /v1/fiat/withdraw."},"FirmQuoteRequest":{"properties":{"quote_currency":{"type":"string","title":"Quote Currency"},"base_currency":{"type":"string","title":"Base Currency","default":"PHP"},"side":{"type":"string","enum":["buy","sell"],"title":"Side"},"base_quantity":{"type":"string","title":"Base Quantity"}},"type":"object","required":["quote_currency","side","base_quantity"],"title":"FirmQuoteRequest","description":"Body for POST /v1/trade/quote."},"FirmQuoteV2Request":{"properties":{"side":{"type":"string","enum":["buy","sell"],"title":"Side"},"quote_currency":{"type":"string","title":"Quote Currency"},"base_currency":{"type":"string","title":"Base Currency","default":"PHP"},"currency":{"type":"string","title":"Currency"},"quantity":{"type":"string","title":"Quantity"}},"type":"object","required":["side","quote_currency","currency","quantity"],"title":"FirmQuoteV2Request","description":"Body for POST /v2/trade/quote."},"Flow":{"properties":{"nodes":{"items":{"$ref":"#/components/schemas/FlowNode"},"type":"array","title":"Nodes"},"edges":{"items":{"prefixItems":[{"type":"string"},{"type":"string"}],"type":"array","maxItems":2,"minItems":2},"type":"array","title":"Edges"}},"type":"object","required":["nodes","edges"],"title":"Flow"},"FlowNode":{"properties":{"id":{"type":"string","title":"Id"},"label":{"type":"string","title":"Label"},"sub":{"type":"string","title":"Sub"},"x":{"type":"number","title":"X"},"y":{"type":"number","title":"Y"}},"type":"object","required":["id","label","sub","x","y"],"title":"FlowNode"},"FundingQuote":{"properties":{"usdc_target":{"type":"number","title":"Usdc Target"},"php_to_pay":{"type":"number","title":"Php To Pay"},"php_base":{"type":"number","title":"Php Base"},"buffer_bps":{"type":"integer","title":"Buffer Bps"},"price":{"type":"number","title":"Price"}},"type":"object","required":["usdc_target","php_to_pay","php_base","buffer_bps","price"],"title":"FundingQuote","description":"How many pesos to pay to fund a workflow priced in USDC. `php_to_pay`\nincludes a safety buffer and is rounded up, so it always covers the target\nafter spread, fees, and step rounding."},"HealthResponse":{"properties":{"status":{"type":"string","title":"Status"},"version":{"type":"string","title":"Version"},"uptime_seconds":{"type":"number","title":"Uptime Seconds"}},"type":"object","required":["status","version","uptime_seconds"],"title":"HealthResponse","description":"Liveness body: process facts only, never dependency status."},"InvalidatedReputation":{"properties":{"agent_id":{"type":"string","title":"Agent Id"},"invalidated":{"type":"boolean","title":"Invalidated"},"read_ttl_seconds":{"type":"number","title":"Read Ttl Seconds"}},"type":"object","required":["agent_id","invalidated","read_ttl_seconds"],"title":"InvalidatedReputation"},"NetworkInfo":{"properties":{"network":{"type":"string","title":"Network"},"rpc_url":{"type":"string","title":"Rpc Url"},"network_passphrase":{"type":"string","title":"Network Passphrase"},"admin":{"type":"string","title":"Admin"},"dispatch_signer":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dispatch Signer"},"asset":{"type":"string","title":"Asset"},"asset_sac":{"type":"string","title":"Asset Sac"},"contracts":{"additionalProperties":{"type":"string"},"type":"object","title":"Contracts"}},"type":"object","required":["network","rpc_url","network_passphrase","admin","asset","asset_sac","contracts"],"title":"NetworkInfo"},"NewIdResponse":{"properties":{"id_hex":{"type":"string","title":"Id Hex"}},"type":"object","required":["id_hex"],"title":"NewIdResponse"},"OffRampRequest":{"properties":{"usdc_amount":{"type":"string","title":"Usdc Amount"},"identifier":{"type":"string","title":"Identifier"},"beneficiary_bank_code":{"type":"string","maxLength":200,"title":"Beneficiary Bank Code"},"beneficiary_account_name":{"type":"string","maxLength":200,"title":"Beneficiary Account Name"},"beneficiary_account_number":{"type":"string","maxLength":200,"title":"Beneficiary Account Number"},"fee_type":{"type":"string","title":"Fee Type","default":"Sender"},"method":{"type":"string","title":"Method","default":"PAY-TO-ACCOUNT-NON-REAL-TIME"},"sender_first_name":{"type":"string","title":"Sender First Name"},"sender_last_name":{"type":"string","title":"Sender Last Name"},"sender_country_origin":{"type":"string","title":"Sender Country Origin","default":"Philippines"},"source_of_funds":{"type":"string","title":"Source Of Funds","default":"Business Income"},"beneficiary_first_name":{"type":"string","maxLength":200,"title":"Beneficiary First Name"},"beneficiary_last_name":{"type":"string","maxLength":200,"title":"Beneficiary Last Name"},"purpose":{"type":"string","title":"Purpose","default":"Business Transaction"},"relationship_of_sender_to_beneficiary":{"type":"string","title":"Relationship Of Sender To Beneficiary","default":"Myself"}},"type":"object","required":["usdc_amount","identifier","beneficiary_bank_code","beneficiary_account_name","beneficiary_account_number","sender_first_name","sender_last_name","beneficiary_first_name","beneficiary_last_name"],"title":"OffRampRequest","description":"Start a USDCXLM → PHP ramp. The agent sends USDCXLM to the returned\ndeposit address; the converted PHP is paid out to the beneficiary bank."},"OnRampRequest":{"properties":{"php_amount":{"type":"string","title":"Php Amount"},"stellar_address":{"type":"string","pattern":"^G[A-Z2-7]{55}$","title":"Stellar Address","description":"Where USDCXLM is delivered"},"method":{"type":"string","maxLength":64,"title":"Method","description":"Fiat deposit channel, e.g. instapay_upay_cashin"},"identifier":{"type":"string","maxLength":128,"title":"Identifier"},"sender_first_name":{"type":"string","maxLength":200,"title":"Sender First Name"},"sender_last_name":{"type":"string","maxLength":200,"title":"Sender Last Name"},"sender_country_origin":{"type":"string","title":"Sender Country Origin","default":"Philippines"},"source_of_funds":{"type":"string","title":"Source Of Funds","default":"Compensation"},"beneficiary_first_name":{"type":"string","maxLength":200,"title":"Beneficiary First Name"},"beneficiary_last_name":{"type":"string","maxLength":200,"title":"Beneficiary Last Name"},"purpose":{"type":"string","title":"Purpose","default":"Purchase of Goods"},"relationship_of_sender_to_beneficiary":{"type":"string","title":"Relationship Of Sender To Beneficiary","default":"Myself"}},"type":"object","required":["php_amount","stellar_address","method","identifier","sender_first_name","sender_last_name","beneficiary_first_name","beneficiary_last_name"],"title":"OnRampRequest","description":"Start a PHP → USDCXLM ramp. The buyer pays PHP via a bank/e-wallet\nchannel; the converted USDCXLM is delivered to `stellar_address`."},"OpenDisputeReq":{"properties":{"job_id_hex":{"type":"string","pattern":"^[0-9a-fA-F]{32}$","title":"Job Id Hex"},"step_index":{"type":"integer","maximum":63.0,"minimum":0.0,"title":"Step Index"},"reason":{"type":"string","maxLength":500,"minLength":1,"title":"Reason","description":"What was wrong with the step. 1 to MAX_REASON_CHARS characters once control characters are removed, at least one visible; anything else is 422 `reason_invalid`."},"payer":{"type":"string","pattern":"^G[A-Z2-7]{55}$","title":"Payer"},"nonce":{"type":"string","maxLength":128,"minLength":1,"title":"Nonce"},"signature_b64":{"type":"string","maxLength":256,"minLength":1,"title":"Signature B64","description":"base64 ed25519 signature"}},"type":"object","required":["job_id_hex","step_index","reason","payer","nonce","signature_b64"],"title":"OpenDisputeReq"},"Order":{"properties":{"order_id":{"type":"integer","title":"Order Id"},"status":{"type":"string","title":"Status"},"quote_currency":{"type":"string","title":"Quote Currency"},"base_currency":{"type":"string","title":"Base Currency"},"side":{"type":"string","enum":["buy","sell"],"title":"Side"},"base_quantity":{"type":"number","title":"Base Quantity"},"price":{"type":"number","title":"Price"},"total_amount":{"type":"number","title":"Total Amount"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At"},"updated_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Updated At"}},"type":"object","required":["order_id","status","quote_currency","base_currency","side","base_quantity","price","total_amount"],"title":"Order","description":"Order result from POST /trade and GET /orders/{id}."},"OrderRequest":{"properties":{"quote_id":{"type":"string","title":"Quote Id"},"side":{"type":"string","enum":["buy","sell"],"title":"Side"},"idempotency_id":{"type":"string","title":"Idempotency Id","description":"Client-generated UUIDv4"}},"type":"object","required":["quote_id","side","idempotency_id"],"title":"OrderRequest","description":"Body for POST /v1/trade — accept a firm quote."},"OrdersResponse":{"properties":{"orders":{"items":{"$ref":"#/components/schemas/Order"},"type":"array","title":"Orders"}},"type":"object","required":["orders"],"title":"OrdersResponse","description":"Envelope for the order-history list route."},"OverviewMetrics":{"properties":{"agents_online":{"type":"integer","title":"Agents Online"},"tasks_per_sec":{"type":"number","title":"Tasks Per Sec"},"avg_completion":{"type":"number","title":"Avg Completion"},"avg_trust":{"type":"number","title":"Avg Trust"},"throughput":{"items":{"type":"integer"},"type":"array","title":"Throughput"},"skills":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Skills"}},"type":"object","required":["agents_online","tasks_per_sec","avg_completion","avg_trust","throughput","skills"],"title":"OverviewMetrics"},"PlanFloorNotice":{"properties":{"kind":{"type":"string","enum":["excluded","substituted","degraded"],"title":"Kind"},"agent_id":{"type":"string","title":"Agent Id"},"agent_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agent Name"},"replacement_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Replacement Id"},"replacement_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Replacement Name"},"reason":{"type":"string","title":"Reason"},"reason_code":{"type":"string","enum":["below_floor","unbound_endpoint","floor_relaxed"],"title":"Reason Code","default":"below_floor"},"lower_bound_bps":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Lower Bound Bps"},"floor_bps":{"type":"integer","title":"Floor Bps","default":0},"count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Count"},"dispute_rate_bps":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Dispute Rate Bps"},"awaiting_fresh_read":{"type":"boolean","title":"Awaiting Fresh Read","default":false}},"type":"object","required":["kind","agent_id","reason"],"title":"PlanFloorNotice","description":"One reputation-floor action taken while building a plan.\n\nSurfaced on DecomposeResponse so the buyer sees why a curated pipeline\nchanged shape rather than a silently reshuffled plan — story 3.02 renders\nthese. Additive with a safe default; clients that ignore it are unaffected."},"PlanStep":{"properties":{"agent_id":{"type":"string","title":"Agent Id","description":"Must match a registered agent id"},"agent_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agent Name"},"rationale":{"type":"string","title":"Rationale","description":"<= 20 words"},"est_price_usdc":{"type":"number","minimum":0.0,"title":"Est Price Usdc"},"est_eta_seconds":{"type":"number","minimum":0.0,"title":"Est Eta Seconds"},"rep_bps":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rep Bps"},"rep_source":{"anyOf":[{"type":"string","enum":["onchain","prior"]},{"type":"null"}],"title":"Rep Source"},"rep_lower_bound_bps":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rep Lower Bound Bps"},"rep_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rep Count"},"rep_dispute_rate_bps":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rep Dispute Rate Bps"},"rep_degraded":{"type":"boolean","title":"Rep Degraded","default":false},"substituted_for":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Substituted For"},"degraded":{"type":"boolean","title":"Degraded","default":false}},"type":"object","required":["agent_id","rationale","est_price_usdc","est_eta_seconds"],"title":"PlanStep"},"Quote":{"properties":{"quote_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Quote Id"},"expires_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Expires At"},"quote_currency":{"type":"string","title":"Quote Currency"},"base_currency":{"type":"string","title":"Base Currency"},"side":{"type":"string","enum":["buy","sell"],"title":"Side"},"base_quantity":{"type":"number","title":"Base Quantity"},"price":{"type":"number","title":"Price"},"total_amount":{"type":"number","title":"Total Amount"}},"type":"object","required":["quote_currency","base_currency","side","base_quantity","price","total_amount"],"title":"Quote","description":"Indicative or firm quote payload (firm adds quote_id + expires_at)."},"RampEstimate":{"properties":{"direction":{"type":"string","enum":["onramp","offramp"],"title":"Direction"},"php_amount":{"type":"number","title":"Php Amount"},"usdc_amount":{"type":"number","title":"Usdc Amount"},"price":{"type":"number","title":"Price"},"quote_currency":{"type":"string","title":"Quote Currency","default":"USDC"},"base_currency":{"type":"string","title":"Base Currency","default":"PHP"}},"type":"object","required":["direction","php_amount","usdc_amount","price"],"title":"RampEstimate","description":"Indicative conversion preview for a ramp (non-binding)."},"RampRecord":{"properties":{"ramp_id":{"type":"string","title":"Ramp Id"},"direction":{"type":"string","enum":["onramp","offramp"],"title":"Direction"},"status":{"type":"string","enum":["quoted","awaiting_payment","funded","converting","settling","completed","failed"],"title":"Status"},"created_at":{"type":"string","title":"Created At"},"php_amount":{"type":"number","title":"Php Amount","default":0},"usdc_amount":{"type":"number","title":"Usdc Amount","default":0},"price":{"type":"number","title":"Price","default":0},"stellar_address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stellar Address"},"deposit_address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Deposit Address"},"deposit_tag":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Deposit Tag"},"identifier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Identifier"},"reference_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reference Number"},"checkout_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Checkout Url"},"order_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Order Id"},"crypto_tx_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Crypto Tx Id"},"withdraw_request_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Withdraw Request Id"},"stages":{"items":{"$ref":"#/components/schemas/RampStage"},"type":"array","title":"Stages"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","required":["ramp_id","direction","status","created_at"],"title":"RampRecord","description":"The full state of a ramp as it moves through its stages."},"RampStage":{"properties":{"name":{"type":"string","title":"Name"},"status":{"type":"string","title":"Status"},"detail":{"type":"string","title":"Detail","default":""}},"type":"object","required":["name","status"],"title":"RampStage","description":"One step within a ramp's lifecycle."},"RatingsReadiness":{"properties":{"writer":{"type":"string","enum":["disabled","no_signer","scorer","not_scorer","unchecked"],"title":"Writer"},"signer":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Signer"},"scorer":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scorer"}},"type":"object","required":["writer","signer","scorer"],"title":"RatingsReadiness","description":"Whether this deployment can write ratings — `rating_writer`'s verdict.\n\n`signer` says \"configured\" on a key's mere presence, which cannot tell a\nworking deployment from one whose key is not the ReputationLedger's Scorer\n— where every rating reverts with Unauthorized while the service looks\nhealthy. `writer` answers the real question for the configuration and the\nchain actually in force; services/rating_writer.py defines its statuses.\n\nInformational only, like `cold_start` and for the same reason: a\ndeployment that cannot rate still serves every request, and read-only\ndeployments are legitimate. It adds no live network call to the probe\neither: it reports the last cached chain read and, when that is stale,\nstarts a background refresh for the next probe to see.\n\nNothing here is secret. `signer` is the public key — the secret never\nleaves the keypair — and `scorer` is public chain data. Both are here\nbecause the fix for `not_scorer` is `set_scorer(<signer>)`, and after a\nrestart has taken the startup line with it, this is where an operator can\nstill read the two addresses."},"ReadinessStep":{"properties":{"key":{"type":"string","enum":["registered","active","bound","reachable","routable","first_run","first_settlement"],"title":"Key"},"status":{"type":"string","enum":["done","todo","failed","unknown"],"title":"Status"},"detail":{"type":"string","title":"Detail"},"action":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Action"},"evidence":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Evidence"}},"type":"object","required":["key","status","detail","action","evidence"],"title":"ReadinessStep"},"ReclaimReq":{"properties":{"payer":{"type":"string","pattern":"^G[A-Z2-7]{55}$","title":"Payer"},"auth_id_hex":{"type":"string","pattern":"^[0-9a-f]{32}$","title":"Auth Id Hex"}},"type":"object","required":["payer","auth_id_hex"],"title":"ReclaimReq"},"RefundReconcileReadiness":{"properties":{"enabled":{"type":"boolean","title":"Enabled"},"running":{"type":"boolean","title":"Running"},"last_run_at":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Last Run At"},"last_skipped":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Skipped"},"last_outcomes":{"additionalProperties":{"type":"integer"},"type":"object","title":"Last Outcomes"}},"type":"object","required":["enabled","running","last_run_at","last_skipped","last_outcomes"],"title":"RefundReconcileReadiness","description":"The refund reconcile sweep (services/refund_reconcile.py) and its last pass.\n\n`enabled` is both switches together — REFUND_RECONCILE_ENABLED and the\nDISPUTE_REFUNDS_ENABLED it depends on — and `running` whether the loop is\nalive in this process. The last pass is counts by action and nothing\nelse: no dispute ids and no hashes reach this unauthenticated route. A\nnonzero `history_gap`, `no_hash`, `not_this_refund`, `amount_mismatch`,\n`not_crediting`, `missing` or `lost_race` is a claim waiting on a human,\nand the log names it. `last_skipped` says why a pass read nothing, such\nas a deployment that cannot pay credits. Informational, like the rest."},"RegisterAgentReq":{"properties":{"owner":{"type":"string","pattern":"^G[A-Z2-7]{55}$","title":"Owner","description":"G... address of the agent owner"},"agent_id":{"type":"string","pattern":"^[A-Za-z0-9_]{1,32}$","title":"Agent Id"},"name":{"type":"string","maxLength":100,"minLength":1,"title":"Name"},"skills":{"items":{"type":"string","pattern":"^[A-Za-z0-9_]{1,32}$"},"type":"array","maxItems":16,"title":"Skills"},"price_usdc":{"type":"number","maximum":10000.0,"exclusiveMinimum":0.0,"title":"Price Usdc"}},"type":"object","required":["owner","agent_id","name","price_usdc"],"title":"RegisterAgentReq"},"RejectDisputeReq":{"properties":{"note":{"type":"string","maxLength":500,"minLength":1,"title":"Note","description":"Why the dispute was rejected. SHOWN TO THE BUYER as the dispute's `rejection_reason`, and readable by anyone who can read the task's disputes — write it for the buyer."}},"type":"object","required":["note"],"title":"RejectDisputeReq","description":"The adjudicator's word on why a dispute was not upheld — which the buyer reads.\n\nREQUIRED, because it is the buyer's answer: it comes back on the dispute\nas `rejection_reason`, and a rejection with no explanation is worse than\nno dispute system at all. So a body with no note, a null note or an empty\none is the field-level `validation_error` here, before anything is read.\nThe edge settles only the shape; what cleaning leaves of the text is the\nservice's to judge, since only it cleans — a note of whitespace or control\ncharacters passes this bound, cleans to nothing, and is refused there as\n`rejection_reason_required`.\n\nBounded at the buyer's reason's number — one paragraph — because it is\nthe same kind of thing from the other side of the table, and a rejection\nthat outgrew the complaint it answers would be the one free-text field in\nthis surface nobody had sized. Bounded HERE, unlike the reason, because\nthe caller is the operator holding the key rather than a buyer, so the\ngeneric field-level 422 is an answer they can read. `dispute_svc.reject`\nrefuses a note past the same MAX_REASON_CHARS (`rejection_reason_too_long`)\nrather than cutting it, so no bound anywhere shows the buyer an\nadjudicator's reason cut short."},"ReputationBatch":{"properties":{"reputations":{"additionalProperties":{"$ref":"#/components/schemas/ReputationInfo"},"type":"object","title":"Reputations"},"floor_bps":{"type":"integer","title":"Floor Bps"},"prior_bps":{"type":"integer","title":"Prior Bps"}},"type":"object","required":["reputations","floor_bps","prior_bps"],"title":"ReputationBatch","description":"Reputation for every registered agent + the routing constants."},"ReputationInfo":{"properties":{"agent_id":{"type":"string","title":"Agent Id"},"smoothed_bps":{"type":"integer","title":"Smoothed Bps"},"lower_bound_bps":{"type":"integer","title":"Lower Bound Bps"},"avg_bps":{"type":"integer","title":"Avg Bps"},"count":{"type":"integer","title":"Count"},"weight":{"type":"integer","title":"Weight"},"disputed":{"type":"integer","title":"Disputed"},"dispute_rate_bps":{"type":"integer","title":"Dispute Rate Bps"},"source":{"type":"string","enum":["onchain","prior"],"title":"Source"},"degraded":{"type":"boolean","title":"Degraded","default":false},"stale":{"type":"boolean","title":"Stale","default":false},"stale_age_seconds":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Stale Age Seconds"}},"type":"object","required":["agent_id","smoothed_bps","lower_bound_bps","avg_bps","count","weight","disputed","dispute_rate_bps","source"],"title":"ReputationInfo","description":"Smoothed reputation for one agent (mirror of reputation_svc.RepInfo)."},"ReputationParams":{"properties":{"enabled":{"type":"boolean","title":"Enabled"},"prior_bps":{"type":"integer","title":"Prior Bps"},"prior_weight_usdc":{"type":"number","title":"Prior Weight Usdc"},"floor_bps":{"type":"integer","title":"Floor Bps"},"max_rating_weight_usdc":{"type":"number","title":"Max Rating Weight Usdc"},"max_rating_to_prior_ratio":{"type":"number","title":"Max Rating To Prior Ratio"},"read_ttl_seconds":{"type":"number","title":"Read Ttl Seconds"},"wilson_z":{"type":"number","title":"Wilson Z"},"epoch_seconds":{"type":"integer","title":"Epoch Seconds"},"decay_bps_per_epoch":{"type":"integer","title":"Decay Bps Per Epoch"},"max_decay_epochs":{"type":"integer","title":"Max Decay Epochs"},"contract_id":{"type":"string","title":"Contract Id"},"network":{"type":"string","title":"Network"}},"type":"object","required":["enabled","prior_bps","prior_weight_usdc","floor_bps","max_rating_weight_usdc","max_rating_to_prior_ratio","read_ttl_seconds","wilson_z","epoch_seconds","decay_bps_per_epoch","max_decay_epochs","contract_id","network"],"title":"ReputationParams","description":"Full parameter set of the reputation system — routing constants applied\nby the backend plus the deployed ledger's on-chain decay constants."},"RetryMethod":{"properties":{"request_id":{"type":"string","title":"Request Id"},"channel":{"type":"string","title":"Channel"},"status":{"type":"string","title":"Status"},"fail_reason":{"type":"string","title":"Fail Reason","default":""},"time":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Time"}},"type":"object","required":["request_id","channel","status"],"title":"RetryMethod","description":"One attempted payment channel within a fiat withdrawal."},"SealReq":{"properties":{"job_id_hex":{"type":"string","pattern":"^[0-9a-fA-F]{32}$","title":"Job Id Hex"},"orchestrator":{"type":"string","pattern":"^G[A-Z2-7]{55}$","title":"Orchestrator"},"intent_hash_hex":{"type":"string","pattern":"^[0-9a-fA-F]{64}$","title":"Intent Hash Hex"},"agents":{"items":{"type":"string","maxLength":32,"minLength":1},"type":"array","maxItems":32,"title":"Agents"},"receipts_hex":{"items":{"type":"string","pattern":"^[0-9a-fA-F]{32}$"},"type":"array","maxItems":32,"title":"Receipts Hex"},"total_spent_usdc":{"type":"number","maximum":100000.0,"minimum":0.0,"title":"Total Spent Usdc"}},"type":"object","required":["job_id_hex","orchestrator","intent_hash_hex","agents","receipts_hex","total_spent_usdc"],"title":"SealReq"},"SetActiveReq":{"properties":{"owner":{"type":"string","pattern":"^G[A-Z2-7]{55}$","title":"Owner","description":"G... address of the owner (the signer)"},"agent_id":{"type":"string","pattern":"^[A-Za-z0-9_]{1,32}$","title":"Agent Id"},"active":{"type":"boolean","title":"Active","description":"True relists the agent, False delists it"}},"type":"object","required":["owner","agent_id","active"],"title":"SetActiveReq"},"SettledWorkflow":{"properties":{"job_id_hex":{"type":"string","title":"Job Id Hex"},"tx_hash":{"type":"string","title":"Tx Hash"},"explorer":{"type":"string","title":"Explorer"},"amount_usdc":{"type":"number","title":"Amount Usdc"},"payer":{"type":"string","title":"Payer"},"payer_team_role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Payer Team Role"},"settled_at":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Settled At"}},"type":"object","required":["job_id_hex","tx_hash","explorer","amount_usdc","payer","payer_team_role","settled_at"],"title":"SettledWorkflow","description":"One charge an external agent was paid, as a reviewer verifies it."},"SettlementEntry":{"properties":{"job_id":{"type":"string","title":"Job Id"},"auth_id":{"type":"string","title":"Auth Id"},"amount_stroops":{"type":"integer","title":"Amount Stroops"},"ledger":{"type":"integer","title":"Ledger"},"tx_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tx Hash"},"at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"At"},"payer":{"type":"string","title":"Payer"},"self_payment":{"type":"boolean","title":"Self Payment"},"exclusion":{"anyOf":[{"type":"string","enum":["payer_unreadable","owner","settler","settler_unreadable"]},{"type":"null"}],"title":"Exclusion"}},"type":"object","required":["job_id","auth_id","amount_stroops","ledger","tx_hash","at","payer","self_payment","exclusion"],"title":"SettlementEntry","description":"One on-chain `charged` event (mirror of settlement_svc.SettlementEntry)."},"SettlementEvidence":{"properties":{"agent_id":{"type":"string","title":"Agent Id"},"asset":{"type":"string","title":"Asset"},"window_days":{"type":"number","title":"Window Days"},"scanned_ledgers":{"type":"integer","title":"Scanned Ledgers"},"entries":{"items":{"$ref":"#/components/schemas/SettlementEntry"},"type":"array","title":"Entries"},"total_stroops":{"type":"integer","title":"Total Stroops"},"self_payment_stroops":{"type":"integer","title":"Self Payment Stroops"},"truncated":{"type":"boolean","title":"Truncated"},"unavailable":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Unavailable"}},"type":"object","required":["agent_id","asset","window_days","scanned_ledgers","entries","total_stroops","self_payment_stroops","truncated","unavailable"],"title":"SettlementEvidence","description":"What the chain says one agent has been paid, and the limits of the look.\n\nMirror of settlement_svc.SettlementEvidence. Three fields are load-bearing\nand must not be dropped by a client: `window_days` (an empty `entries` only\never means \"nothing in this window\", never \"never paid\"), `unavailable`\n(set when no scan happened, which is a different fact from zero earnings),\nand `self_payment_stroops` (charges excluded from the total because the\nplatform — or an unidentifiable payer — funded them)."},"SettlementStepView":{"properties":{"step_index":{"type":"integer","title":"Step Index"},"agent_id":{"type":"string","title":"Agent Id"},"agent_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agent Name"},"price_usdc":{"type":"number","title":"Price Usdc"},"delivered":{"type":"boolean","title":"Delivered"},"creditable_usdc":{"type":"number","title":"Creditable Usdc"},"output_summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Output Summary"},"paid_usdc":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Paid Usdc"},"receipt_id_hex":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Receipt Id Hex"},"unpaid_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Unpaid Reason"}},"type":"object","required":["step_index","agent_id","agent_name","price_usdc","delivered","creditable_usdc","output_summary"],"title":"SettlementStepView","description":"One settled step, and what disputing it would credit.\n\nExists because the trace a buyer reads is evicted from memory long before\ntheir window closes, and this is read off the settlement record instead —\nso it is the one account that survives of which agent ran each step, what\nit was charged, whether it delivered and what it produced. A mirror of\n`dispute_store.SettlementStep` rather than the dataclass itself, for\n`DisputeResponse`'s reason.\n\n`creditable_usdc` is computed HERE, with the refund's own rule, so the\nreceipt never re-derives the rounding: it is the figure `open_dispute`\nwould freeze onto a dispute opened now. What an uphold transfers is also\nbounded by the settled total (`refund_svc.creditable_for`), so this is the\nceiling the buyer is shown, never a sum the platform could exceed.\n\n`output_summary` is untrusted — an external agent's own words — and is the\nline the world-readable trace already showed for the step, cleaned to\n`OUTPUT_SUMMARY_MAX_CHARS` by its writer before it was stored. It is passed\nthrough verbatim and escaped on render like every other stored string.\nNone for a step that delivered nothing, and for every settlement recorded\nbefore 4.05."},"SettlementView":{"properties":{"job_id_hex":{"type":"string","title":"Job Id Hex"},"payer":{"type":"string","title":"Payer"},"settled_at":{"type":"number","title":"Settled At"},"window_closes_at":{"type":"number","title":"Window Closes At"},"settled_usdc":{"type":"number","title":"Settled Usdc"},"charge_tx":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Charge Tx"},"proof_tx":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Proof Tx"},"steps":{"items":{"$ref":"#/components/schemas/SettlementStepView"},"type":"array","title":"Steps"},"policy":{"$ref":"#/components/schemas/CreditPolicy"}},"type":"object","required":["job_id_hex","payer","settled_at","window_closes_at","settled_usdc","charge_tx","proof_tx","steps","policy"],"title":"SettlementView","description":"What a task settled as: the facts a buyer's FIRST dispute starts from.\n\nExists because the per-task read used to carry only the deadline, and a\ndispute cannot be started from a deadline. The challenge is minted against\nthe job id, only the payer's wallet may sign it, and the buyer has to see\nwhich step they are disputing and what it would credit — every one of which\nlived on the settlement record and nowhere a client could read it.\n\nA mirror of `dispute_store.SettlementRecord`, for `DisputeResponse`'s\nreason, and a deliberately narrower one: `auth_id_hex` is left out because\nnothing a client does needs it, and a field is only ever added to this\nshape for a reader who does."},"SubmitReq":{"properties":{"signed_xdr":{"type":"string","maxLength":32768,"minLength":1,"title":"Signed Xdr"}},"type":"object","required":["signed_xdr"],"title":"SubmitReq"},"SyncResponse":{"properties":{"synced":{"type":"integer","title":"Synced"}},"type":"object","required":["synced"],"title":"SyncResponse"},"Task":{"properties":{"id":{"type":"string","title":"Id"},"intent":{"type":"string","title":"Intent"},"agents":{"type":"integer","title":"Agents"},"spent":{"type":"number","title":"Spent"},"status":{"type":"string","enum":["pending","running","complete","failed"],"title":"Status"},"started_at":{"type":"number","title":"Started At"},"charge_tx":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Charge Tx"},"proof_tx":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Proof Tx"},"settlement":{"anyOf":[{"type":"string","enum":["settled","released","skipped","unconfirmed","failed"]},{"type":"null"}],"title":"Settlement"},"artifact":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Artifact"},"started":{"type":"string","title":"Started","description":"Human-readable age (\"2m ago\"), computed at serialization time.","readOnly":true}},"type":"object","required":["id","intent","agents","spent","status","started"],"title":"Task","description":"A stored task, artifact included. This is what app state holds and what\nthe per-task routes serve; only the list route narrows to TaskSummary."},"TaskDisputesResponse":{"properties":{"task_id":{"type":"string","title":"Task Id"},"window_closes_at":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Window Closes At"},"now":{"type":"number","title":"Now"},"settlement":{"anyOf":[{"$ref":"#/components/schemas/SettlementView"},{"type":"null"}]},"disputes":{"items":{"$ref":"#/components/schemas/DisputeResponse"},"type":"array","title":"Disputes"},"settlement_state":{"anyOf":[{"type":"string","enum":["settled","released","skipped","unconfirmed","failed"]},{"type":"null"}],"title":"Settlement State"}},"type":"object","required":["task_id","window_closes_at","now","settlement","disputes"],"title":"TaskDisputesResponse","description":"A task's settlement, its dispute window, and everything raised against it.\n\n`settlement` and `window_closes_at` are null until the task settles — a\ntask that was never paid for has nothing to dispute and no deadline to\nshow. The deadline is read from the settlement record rather than\nrecomputed from `DISPUTE_WINDOW_SECONDS`, so retuning that setting cannot\nmove a deadline a buyer was already given. It stays at the top level,\nalways equal to `settlement.window_closes_at`, because clients written\nbefore 4.05 read it there.\n\n`now` is this server's clock when the response was built. The window is a\ndeadline the SERVER enforces, so a countdown run off the browser's clock is\nwrong by however far that clock has drifted: it shows a window open that\n`open_dispute` will refuse as closed, or closed while there is still time.\nThe console measures the skew from this and corrects by it."},"TaskSummary":{"properties":{"id":{"type":"string","title":"Id"},"intent":{"type":"string","title":"Intent"},"agents":{"type":"integer","title":"Agents"},"spent":{"type":"number","title":"Spent"},"status":{"type":"string","enum":["pending","running","complete","failed"],"title":"Status"},"started_at":{"type":"number","title":"Started At"},"charge_tx":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Charge Tx"},"proof_tx":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Proof Tx"},"settlement":{"anyOf":[{"type":"string","enum":["settled","released","skipped","unconfirmed","failed"]},{"type":"null"}],"title":"Settlement"},"started":{"type":"string","title":"Started","description":"Human-readable age (\"2m ago\"), computed at serialization time.","readOnly":true}},"type":"object","required":["id","intent","agents","spent","status","started"],"title":"TaskSummary","description":"A task without its artifact — the shape the task list is served in.\n\nAn artifact carries `files[*].content` plus a byte-identical `preview_html`\n(30–38 KB for a baked kit), so a completed task is ~70 KB. The dashboard\npolls the list every 5s and reads none of it, which made a full list ~1.4 MB\nper poll per open tab. Listing summaries keeps the poll cheap; the payload\nis served by GET /tasks/{id}/artifact, the one place it is actually read."},"TraceLine":{"properties":{"t":{"type":"string","title":"T"},"level":{"type":"string","enum":["input","exec","proof","cost","out","error","artifact"],"title":"Level"},"msg":{"type":"string","title":"Msg"},"settlement":{"anyOf":[{"type":"string","enum":["settled","released","skipped","unconfirmed","failed"]},{"type":"null"}],"title":"Settlement"}},"type":"object","required":["t","level","msg"],"title":"TraceLine"},"UnbindChallengeResponse":{"properties":{"agent_id":{"type":"string","title":"Agent Id"},"nonce":{"type":"string","title":"Nonce"},"message":{"type":"string","title":"Message"},"expires_at":{"type":"number","title":"Expires At"},"ttl_seconds":{"type":"integer","title":"Ttl Seconds"}},"type":"object","required":["agent_id","nonce","message","expires_at","ttl_seconds"],"title":"UnbindChallengeResponse","description":"Same shape as BindChallengeResponse, declared separately so the schema\nthe console generates names the flow it belongs to — the two messages are\nNOT interchangeable and a shared model would suggest they were."},"UnbindReq":{"properties":{"signature":{"type":"string","maxLength":256,"minLength":1,"title":"Signature","description":"base64 ed25519 signature"}},"type":"object","required":["signature"],"title":"UnbindReq"},"UnbindResponse":{"properties":{"agent_id":{"type":"string","title":"Agent Id"},"owner":{"type":"string","title":"Owner"},"was_bound":{"type":"boolean","title":"Was Bound"},"unbound_at":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Unbound At"}},"type":"object","required":["agent_id","owner","was_bound","unbound_at"],"title":"UnbindResponse"},"UpdatePriceReq":{"properties":{"owner":{"type":"string","pattern":"^G[A-Z2-7]{55}$","title":"Owner","description":"G... address of the owner (the signer)"},"agent_id":{"type":"string","pattern":"^[A-Za-z0-9_]{1,32}$","title":"Agent Id"},"price_usdc":{"type":"number","maximum":10000.0,"exclusiveMinimum":0.0,"title":"Price Usdc"}},"type":"object","required":["owner","agent_id","price_usdc"],"title":"UpdatePriceReq"},"WebhookRegisterRequest":{"properties":{"event_type":{"type":"string","title":"Event Type","description":"crypto | fiat"},"webhook_endpoint":{"type":"string","title":"Webhook Endpoint"}},"type":"object","required":["event_type","webhook_endpoint"],"title":"WebhookRegisterRequest"},"WebhookRegistration":{"properties":{"webhook_endpoint":{"type":"string","title":"Webhook Endpoint"},"event_type":{"type":"string","title":"Event Type"}},"type":"object","required":["webhook_endpoint","event_type"],"title":"WebhookRegistration"},"X402Request":{"properties":{"agent_id":{"type":"string","maxLength":64,"pattern":"^[A-Za-z0-9_.\\-]{1,64}$","title":"Agent Id"},"amount_usdc":{"type":"number","maximum":10000.0,"exclusiveMinimum":0.0,"title":"Amount Usdc"}},"type":"object","required":["agent_id","amount_usdc"],"title":"X402Request"},"X402Response":{"properties":{"status":{"type":"string","enum":["402","paid"],"title":"Status"},"receipt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Receipt"}},"type":"object","required":["status"],"title":"X402Response"},"XdrResponse":{"properties":{"xdr":{"type":"string","title":"Xdr"}},"type":"object","required":["xdr"],"title":"XdrResponse"},"app__main__ReadinessResponse":{"properties":{"status":{"type":"string","title":"Status"},"llm":{"type":"string","title":"Llm"},"stellar":{"type":"string","title":"Stellar"},"signer":{"type":"string","title":"Signer"},"pdax":{"type":"string","title":"Pdax"},"cold_start":{"$ref":"#/components/schemas/ColdStartReadiness"},"ratings":{"$ref":"#/components/schemas/RatingsReadiness"},"disputes":{"$ref":"#/components/schemas/DisputesReadiness"},"escrow":{"$ref":"#/components/schemas/EscrowReadiness"}},"type":"object","required":["status","llm","stellar","signer","pdax","cold_start","ratings","disputes","escrow"],"title":"ReadinessResponse","description":"Per-dependency readiness report. No live network calls, so the probe\nstays cheap and deterministic: everything is config-derived except\n`ratings`, which reports the rating writer's last cached chain read."},"app__routers__binding__ReadinessResponse":{"properties":{"agent_id":{"type":"string","title":"Agent Id"},"checked_at":{"type":"integer","title":"Checked At"},"ready":{"type":"boolean","title":"Ready"},"steps":{"items":{"$ref":"#/components/schemas/ReadinessStep"},"type":"array","title":"Steps"}},"type":"object","required":["agent_id","checked_at","ready","steps"],"title":"ReadinessResponse","description":"Frozen contract (story 5.02): all seven steps, always, in this order."}},"securitySchemes":{"OperatorApiKey":{"type":"apiKey","description":"The operator's API_KEY. Required by the adjudication routes, which spend the platform's own settler balance — they fail CLOSED, so a deployment with no key configured refuses them outright rather than serving them openly.","in":"header","name":"X-API-Key"}}},"tags":[{"name":"meta","description":"Service identity and health/readiness probes."},{"name":"agents","description":"Registered agents and their skills, pricing, and reputation."},{"name":"orchestrator","description":"Decompose a goal into a plan and execute it across agents."},{"name":"tasks","description":"Task history, status, and produced artifacts."},{"name":"trace","description":"Per-task execution traces, polled or streamed."},{"name":"metrics","description":"Aggregate network metrics for the dashboard."},{"name":"flow","description":"Agent-graph flow layout consumed by the frontend visualizer."},{"name":"payments","description":"x402 payment challenges and settlement."},{"name":"stellar","description":"Soroban contract reads, unsigned-XDR builds, and signed-XDR submits."},{"name":"binding","description":"Bind an operator HTTPS endpoint to an on-chain agent id, proved by a wallet signature."},{"name":"disputes","description":"Dispute a settled step inside its 24-hour window, proved by the payer's wallet signature; and the operator-keyed adjudication that upholds one into a credit or rejects it."},{"name":"pdax","description":"PDAX PHP-to-crypto on/off-ramp: trade, funding, withdrawals, webhooks."}]}