{"openapi":"3.1.0","info":{"title":"PeerOTC desk","version":"0.3.2"},"paths":{"/health":{"get":{"summary":"Health","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/info":{"get":{"summary":"Info","description":"This desk's public profile — custody model, fee, and arbitrator.","operationId":"info_v1_info_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/book":{"get":{"summary":"Book","operationId":"book_v1_book_get","parameters":[{"name":"asset","in":"query","required":false,"schema":{"type":"string","default":"BTX","title":"Asset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/trades":{"get":{"summary":"Trades","operationId":"trades_v1_trades_get","parameters":[{"name":"asset","in":"query","required":false,"schema":{"type":"string","default":"BTX","title":"Asset"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":300,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/ticker":{"get":{"summary":"Ticker","operationId":"ticker_v1_ticker_get","parameters":[{"name":"asset","in":"query","required":false,"schema":{"type":"string","default":"BTX","title":"Asset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/offers":{"get":{"summary":"List Offers","operationId":"list_offers_v1_offers_get","parameters":[{"name":"asset","in":"query","required":false,"schema":{"type":"string","default":"BTX","title":"Asset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"summary":"Post Offer","operationId":"post_offer_v1_offers_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/offers/{oid}/take":{"post":{"summary":"Take","operationId":"take_v1_offers__oid__take_post","parameters":[{"name":"oid","in":"path","required":true,"schema":{"type":"integer","title":"Oid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TakeIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/buy":{"post":{"summary":"Buy","description":"One-call buy at best ask. JSON body so agents can post it directly.","operationId":"buy_v1_buy_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BuyIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/arbitrators":{"get":{"summary":"Arbitrators","operationId":"arbitrators_v1_arbitrators_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/deals/{did}":{"get":{"summary":"Deal","operationId":"deal_v1_deals__did__get","parameters":[{"name":"did","in":"path","required":true,"schema":{"type":"integer","title":"Did"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/deals/{did}/wait":{"get":{"summary":"Wait Deal","description":"Long-poll a deal's state so an agent gets notified WITHOUT busy-polling or a websocket.\nPass `since` = the state you last saw; this blocks until the state changes (or ~timeout s,\nmax 25) and returns the deal. Terminal states (RELEASED/REFUNDED/EXPIRED) return immediately.\nAgent loop: call /wait?since=<laststate>, act on the new state, repeat until terminal.\nOnly WAIT_MAX_CONCURRENT calls block at once; beyond that it degrades to a single immediate\nread (the agent just re-polls), so a flood of waiters can't tie up every worker thread.","operationId":"wait_deal_v1_deals__did__wait_get","parameters":[{"name":"did","in":"path","required":true,"schema":{"type":"integer","title":"Did"}},{"name":"since","in":"query","required":false,"schema":{"type":"string","default":"","title":"Since"}},{"name":"timeout","in":"query","required":false,"schema":{"type":"integer","default":25,"title":"Timeout"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/deals/{did}/cancel":{"post":{"summary":"Cancel","description":"Seller early-cancel: refund the BTX NOW if the buyer has not paid. Token-gated (the deal's\nseller/maker token). Only a FUNDED deal qualifies (CREATED = nothing locked; PAID = the buyer\nalready paid, use release/dispute). Refuses if any USDC payment to the seller is seen on Base,\nwith an ~8s grace re-check so an in-flight payment can confirm and be caught before we refund.","operationId":"cancel_v1_deals__did__cancel_post","parameters":[{"name":"did","in":"path","required":true,"schema":{"type":"integer","title":"Did"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisputeIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/deals/{did}/paid":{"post":{"summary":"Mark Paid","operationId":"mark_paid_v1_deals__did__paid_post","parameters":[{"name":"did","in":"path","required":true,"schema":{"type":"integer","title":"Did"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisputeIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/deals/{did}/release":{"post":{"summary":"Release","description":"Operator-only server-side release: signs with DESK-HELD wallets, so it is gated by\nX-Admin-Token on EVERY environment (demo included). Real third parties never use this — they\nrelease via /psbt (their own signatures are the authorization). The watcher calls\nENGINE.release() directly, not this endpoint.","operationId":"release_v1_deals__did__release_post","parameters":[{"name":"did","in":"path","required":true,"schema":{"type":"integer","title":"Did"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/deals/{did}/psbt":{"get":{"summary":"Get Psbt","description":"Remote (non-custodial) signing: the UNSIGNED 2-of-3 spend PSBT for the parties to sign on\ntheir OWN nodes. action='release' (fee+buyer), 'refund' (seller, immediate), or 'timeout'\n(seller refund locked to the deal's refund height — pre-sign it right after funding so the\ndesk can refund you automatically if the buyer never pays). The coordinator holds no\nbuyer/seller key — sign locally (e.g. `btx-cli walletprocesspsbt`) and POST it back.\nRequires your deal/maker token (?token=...).","operationId":"get_psbt_v1_deals__did__psbt_get","parameters":[{"name":"did","in":"path","required":true,"schema":{"type":"integer","title":"Did"}},{"name":"action","in":"query","required":false,"schema":{"type":"string","default":"release","title":"Action"}},{"name":"token","in":"query","required":false,"schema":{"type":"string","default":"","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"summary":"Post Psbt","description":"Submit a PSBT signed on the party's own node. When 2-of-3 signatures are present the\ncoordinator combines + finalizes + broadcasts. The deal token gates submission; the\nsignatures themselves are the spend authorization — no key ever leaves the signer's machine.","operationId":"post_psbt_v1_deals__did__psbt_post","parameters":[{"name":"did","in":"path","required":true,"schema":{"type":"integer","title":"Did"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PsbtIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/deals/{did}/dispute":{"post":{"summary":"Dispute","operationId":"dispute_v1_deals__did__dispute_post","parameters":[{"name":"did","in":"path","required":true,"schema":{"type":"integer","title":"Did"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisputeIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/deals/{did}/arbitrate":{"post":{"summary":"Arbitrate","description":"Arbitrator settles a DISPUTED deal (operator-only, requires X-Admin-Token). Server-side when\nthe parties' wallets are local (our own deals); otherwise the arbitrator contributes its\nsignature and the honest party completes the 2-of-3 on their own node via /psbt.","operationId":"arbitrate_v1_deals__did__arbitrate_post","parameters":[{"name":"did","in":"path","required":true,"schema":{"type":"integer","title":"Did"}},{"name":"outcome","in":"query","required":true,"schema":{"type":"string","title":"Outcome"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/stats":{"get":{"summary":"Stats","description":"Cumulative real activity (trust signal): total USDC transacted + trades settled to date.\nSourced from the real settlements DB (PEEROTC_STATS_DB) when set, else this desk's own.","operationId":"stats_v1_stats_get","parameters":[{"name":"asset","in":"query","required":false,"schema":{"type":"string","default":"BTX","title":"Asset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/settlements":{"get":{"summary":"Settlements","description":"Transparency: every completed deal with its on-chain settlement tx.","operationId":"settlements_v1_settlements_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/tick":{"post":{"summary":"Admin Tick","operationId":"admin_tick_admin_tick_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/":{"get":{"summary":"Home","operationId":"home__get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/{page}":{"get":{"summary":"Page","operationId":"page__page__get","parameters":[{"name":"page","in":"path","required":true,"schema":{"type":"string","title":"Page"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/{page}/{sub}":{"get":{"summary":"Page2","operationId":"page2__page___sub__get","parameters":[{"name":"page","in":"path","required":true,"schema":{"type":"string","title":"Page"}},{"name":"sub","in":"path","required":true,"schema":{"type":"string","title":"Sub"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"BuyIn":{"properties":{"asset":{"type":"string","title":"Asset","default":"BTX"},"amount":{"type":"number","exclusiveMinimum":0.0,"title":"Amount"},"taker_payout":{"type":"string","title":"Taker Payout"},"taker_pubkey":{"type":"string","title":"Taker Pubkey"},"taker_wallet":{"type":"string","title":"Taker Wallet"},"taker_usdc":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Taker Usdc"},"max_price":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Max Price"}},"type":"object","required":["amount","taker_payout","taker_pubkey","taker_wallet"],"title":"BuyIn"},"DisputeIn":{"properties":{"reason":{"type":"string","title":"Reason","default":""},"token":{"type":"string","title":"Token","default":""}},"type":"object","title":"DisputeIn"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"OfferIn":{"properties":{"side":{"type":"string","title":"Side"},"asset":{"type":"string","title":"Asset","default":"BTX"},"amount":{"type":"number","exclusiveMinimum":0.0,"title":"Amount"},"price_usdc":{"type":"number","exclusiveMinimum":0.0,"title":"Price Usdc"},"maker_payout":{"type":"string","title":"Maker Payout"},"maker_pubkey":{"type":"string","title":"Maker Pubkey"},"maker_wallet":{"type":"string","title":"Maker Wallet"},"maker_usdc":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Maker Usdc"},"auto_fund":{"type":"boolean","title":"Auto Fund","default":false}},"type":"object","required":["side","amount","price_usdc","maker_payout","maker_pubkey","maker_wallet"],"title":"OfferIn"},"PsbtIn":{"properties":{"psbt":{"type":"string","title":"Psbt"},"action":{"type":"string","title":"Action","default":"release"},"token":{"type":"string","title":"Token","default":""}},"type":"object","required":["psbt"],"title":"PsbtIn"},"TakeIn":{"properties":{"amount":{"type":"number","exclusiveMinimum":0.0,"title":"Amount"},"taker_payout":{"type":"string","title":"Taker Payout"},"taker_pubkey":{"type":"string","title":"Taker Pubkey"},"taker_wallet":{"type":"string","title":"Taker Wallet"},"taker_usdc":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Taker Usdc"},"arbitrator":{"type":"string","title":"Arbitrator","default":"peerotc"}},"type":"object","required":["amount","taker_payout","taker_pubkey","taker_wallet"],"title":"TakeIn"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}}}