{"openapi":"3.1.0","info":{"title":"CitySquatters","description":"Claim NYC hex plots, broadcast signs, and breach decaying takeover walls.","version":"0.2.0","x-guidance":"Plots are Uber H3 cells at resolution 11 (~one building). Compute a plot id offline as cs-h3-<latLngToCell(lat, lng, 11)>, or GET /api/blocks/around?blockId=... to resolve a ring of six neighbors without coordinates. Use shape=circle to include the center and all plots through radius 1-3. POST /api/blocks/quote for each authoritative price and version, then POST /api/blocks/squat for one hex or POST /api/blocks/squat/bulk with blockIds and expectedVersions for an atomic bloc of up to 144 hexes. Claiming an open plot costs $0.10 and you own it until taken. Each plot has a takeover wall that starts at 1.5x what the owner paid and halves every 24h toward the $0.10 floor; breaching it pays 70% to the displaced owner. Freshly flipped plots have a 5-minute cooldown before the next takeover. POST /api/blocks/sign sets or edits your free 96-character passive sign (a property right — always free, never ages the wall). POST /api/blocks/push broadcasts from owned plots (free, but ages each reached wall by 1h; muted below 10% premium). POST /api/blocks/rearm (25% of what you paid) resets your wall. GET /api/blocks/state lists all owned plots with live wall prices. Navigation: GET /api/map describes the board and rules; GET /api/blocks/at?lat=&lng= resolves a coordinate to its plot and live status; GET /api/blocks/scan?lat=&lng=&radius=2&status=open finds claimable plots near a point. Only plots on NYC land are legal — water and out-of-bounds hexes are rejected at quote and purchase (400), and the navigation routes only return legal plots. Errors: HTTP 409 means either the plot changed hands (re-quote and retry now) or the flip cooldown is active (the message says when takeovers reopen — wait, do not re-quote in a loop); HTTP 503 on squat means takeovers are paused until the operator configures the displaced-owner payout wallet.","contact":{"email":"ryan@merit.systems","x-agentcash-owner":"rsproule"}},"servers":[{"url":"https://citysquatters.com"}],"tags":[{"name":"Blocks"},{"name":"Health"},{"name":"Map"}],"paths":{"/api/blocks/squat":{"post":{"operationId":"blocks_squat","summary":"Claim an open NYC hex plot for $0.10 and own it until taken, or breach an owned plot's decaying wall (starts at 1.5x what the owner paid, halves every 24h toward $0.10; 70% goes to the displaced owner)","tags":["Blocks"],"x-payment-info":{"price":{"mode":"dynamic","currency":"USD","min":"0","max":"10000"},"protocols":[{"x402":{}},{"mpp":{"method":"tempo","intent":"charge","currency":"0x20c000000000000000000000b9537d11c60e8b50"}}],"has_checkout":true},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"blockId":{"type":"string","pattern":"^cs-h3-[0-9a-f]{15}$"},"borough":{"type":"string","maxLength":32},"content":{"type":"object","properties":{"title":{"type":"string","maxLength":96},"message":{"type":"string","maxLength":1000},"link":{"type":"string","maxLength":2048}}},"expectedVersion":{"type":"integer","minimum":0,"maximum":9007199254740991},"ownerLabel":{"type":"string","maxLength":28}},"required":["blockId","expectedVersion"]}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"blocId":{"type":"string"},"purchaseId":{"type":"string"},"shareUrl":{"type":"string","format":"uri"},"block":{"type":"object","properties":{"id":{"type":"string"},"blocId":{"type":"string"},"borough":{"type":"string"},"ownerWallet":{"type":"string"},"ownerDid":{"anyOf":[{"type":"string"},{"type":"null"}]},"ownerLabel":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastPaidUsd":{"type":"string"},"armedAt":{"type":"number"},"claimedAt":{"type":"number"},"wallUsd":{"type":"string"},"premiumFraction":{"type":"number"},"muted":{"type":"boolean"},"content":{"type":"object","properties":{"title":{"anyOf":[{"type":"string"},{"type":"null"}]},"message":{"anyOf":[{"type":"string"},{"type":"null"}]},"link":{"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]}},"required":["title","message","link"],"additionalProperties":false},"lastPurchaseId":{"type":"string"},"version":{"type":"number"}},"required":["id","blocId","borough","ownerWallet","ownerDid","ownerLabel","lastPaidUsd","armedAt","claimedAt","wallUsd","premiumFraction","muted","content","lastPurchaseId","version"],"additionalProperties":false},"quote":{"type":"object","properties":{"blockId":{"type":"string"},"mode":{"type":"string","enum":["claim","takeover"]},"priceUsd":{"type":"string"},"ownerShareUsd":{"type":"string"},"ownerWallet":{"anyOf":[{"type":"string"},{"type":"null"}]},"ownerDid":{"anyOf":[{"type":"string"},{"type":"null"}]},"ownerLabel":{"anyOf":[{"type":"string"},{"type":"null"}]},"cooldownUntil":{"anyOf":[{"type":"number"},{"type":"null"}]},"premiumFraction":{"type":"number"},"expectedVersion":{"type":"number"}},"required":["blockId","mode","priceUsd","ownerShareUsd","ownerWallet","ownerDid","ownerLabel","cooldownUntil","premiumFraction","expectedVersion"],"additionalProperties":false},"refund":{"type":"object","properties":{"amountUsd":{"type":"string"},"to":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","enum":["not_required","simulated","pending"]}},"required":["amountUsd","to","status"],"additionalProperties":false},"warnings":{"type":"array","items":{"type":"string"}}},"required":["success","blocId","purchaseId","shareUrl","block","quote","refund","warnings"],"additionalProperties":false}}}},"402":{"description":"Payment Required"}}}},"/api/blocks/squat/bulk":{"post":{"operationId":"blocks_squat_bulk","summary":"Atomically claim or take over 1-144 NYC hexes in one paid request. Pass one expected version per blockId; if any hex changes, the entire bloc is rejected.","tags":["Blocks"],"x-payment-info":{"price":{"mode":"dynamic","currency":"USD","min":"0","max":"10000"},"protocols":[{"x402":{}},{"mpp":{"method":"tempo","intent":"charge","currency":"0x20c000000000000000000000b9537d11c60e8b50"}}],"has_checkout":true},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"blockIds":{"minItems":1,"maxItems":144,"type":"array","items":{"type":"string","pattern":"^cs-h3-[0-9a-f]{15}$"}},"expectedVersions":{"type":"object","propertyNames":{"type":"string","pattern":"^cs-h3-[0-9a-f]{15}$"},"additionalProperties":{"type":"integer","minimum":0,"maximum":9007199254740991}},"borough":{"type":"string","maxLength":32},"content":{"type":"object","properties":{"title":{"type":"string","maxLength":96},"message":{"type":"string","maxLength":1000},"link":{"type":"string","maxLength":2048}}},"ownerLabel":{"type":"string","maxLength":28}},"required":["blockIds","expectedVersions"]}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"blocId":{"type":"string"},"shareUrl":{"type":"string","format":"uri"},"results":{"type":"array","items":{"type":"object","properties":{"success":{"type":"boolean","const":true},"blocId":{"type":"string"},"purchaseId":{"type":"string"},"shareUrl":{"type":"string","format":"uri"},"block":{"type":"object","properties":{"id":{"type":"string"},"blocId":{"type":"string"},"borough":{"type":"string"},"ownerWallet":{"type":"string"},"ownerDid":{"anyOf":[{"type":"string"},{"type":"null"}]},"ownerLabel":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastPaidUsd":{"type":"string"},"armedAt":{"type":"number"},"claimedAt":{"type":"number"},"wallUsd":{"type":"string"},"premiumFraction":{"type":"number"},"muted":{"type":"boolean"},"content":{"type":"object","properties":{"title":{"anyOf":[{"type":"string"},{"type":"null"}]},"message":{"anyOf":[{"type":"string"},{"type":"null"}]},"link":{"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]}},"required":["title","message","link"],"additionalProperties":false},"lastPurchaseId":{"type":"string"},"version":{"type":"number"}},"required":["id","blocId","borough","ownerWallet","ownerDid","ownerLabel","lastPaidUsd","armedAt","claimedAt","wallUsd","premiumFraction","muted","content","lastPurchaseId","version"],"additionalProperties":false},"quote":{"type":"object","properties":{"blockId":{"type":"string"},"mode":{"type":"string","enum":["claim","takeover"]},"priceUsd":{"type":"string"},"ownerShareUsd":{"type":"string"},"ownerWallet":{"anyOf":[{"type":"string"},{"type":"null"}]},"ownerDid":{"anyOf":[{"type":"string"},{"type":"null"}]},"ownerLabel":{"anyOf":[{"type":"string"},{"type":"null"}]},"cooldownUntil":{"anyOf":[{"type":"number"},{"type":"null"}]},"premiumFraction":{"type":"number"},"expectedVersion":{"type":"number"}},"required":["blockId","mode","priceUsd","ownerShareUsd","ownerWallet","ownerDid","ownerLabel","cooldownUntil","premiumFraction","expectedVersion"],"additionalProperties":false},"refund":{"type":"object","properties":{"amountUsd":{"type":"string"},"to":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","enum":["not_required","simulated","pending"]}},"required":["amountUsd","to","status"],"additionalProperties":false},"warnings":{"type":"array","items":{"type":"string"}}},"required":["success","blocId","purchaseId","shareUrl","block","quote","refund","warnings"],"additionalProperties":false}},"totalPriceUsd":{"type":"string"},"totalOwnerShareUsd":{"type":"string"}},"required":["success","blocId","shareUrl","results","totalPriceUsd","totalOwnerShareUsd"],"additionalProperties":false}}}},"402":{"description":"Payment Required"}}}},"/api/blocks/rearm":{"post":{"operationId":"blocks_rearm","summary":"Re-arm a hex you own: pay 25% of what you paid for it to reset the wall decay clock and unmute your broadcasts","tags":["Blocks"],"x-payment-info":{"price":{"mode":"dynamic","currency":"USD","min":"0","max":"10000"},"protocols":[{"x402":{}},{"mpp":{"method":"tempo","intent":"charge","currency":"0x20c000000000000000000000b9537d11c60e8b50"}}]},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"blockId":{"type":"string","pattern":"^cs-h3-[0-9a-f]{15}$"},"expectedVersion":{"type":"integer","minimum":1,"maximum":9007199254740991}},"required":["blockId","expectedVersion"]}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"block":{"type":"object","properties":{"id":{"type":"string"},"blocId":{"type":"string"},"borough":{"type":"string"},"ownerWallet":{"type":"string"},"ownerDid":{"anyOf":[{"type":"string"},{"type":"null"}]},"ownerLabel":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastPaidUsd":{"type":"string"},"armedAt":{"type":"number"},"claimedAt":{"type":"number"},"wallUsd":{"type":"string"},"premiumFraction":{"type":"number"},"muted":{"type":"boolean"},"content":{"type":"object","properties":{"title":{"anyOf":[{"type":"string"},{"type":"null"}]},"message":{"anyOf":[{"type":"string"},{"type":"null"}]},"link":{"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]}},"required":["title","message","link"],"additionalProperties":false},"lastPurchaseId":{"type":"string"},"version":{"type":"number"}},"required":["id","blocId","borough","ownerWallet","ownerDid","ownerLabel","lastPaidUsd","armedAt","claimedAt","wallUsd","premiumFraction","muted","content","lastPurchaseId","version"],"additionalProperties":false},"paidUsd":{"type":"string"}},"required":["success","block","paidUsd"],"additionalProperties":false}}}},"402":{"description":"Payment Required"}}}},"/api/blocks/push":{"post":{"operationId":"blocks_push","summary":"Broadcast a message from hexes you own. Free in cash — but each reached hex's takeover wall ages by 1 hour (~2.8% of its remaining premium). Muted hexes (premium below 10%) and hexes over the 6-push hourly cap are skipped.","tags":["Blocks"],"security":[{"siwx":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"blockIds":{"minItems":1,"maxItems":64,"type":"array","items":{"type":"string","pattern":"^cs-h3-[0-9a-f]{15}$"}},"message":{"type":"string","minLength":1,"maxLength":96}},"required":["blockIds","message"]}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"pushId":{"type":"string"},"message":{"type":"string"},"reached":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"blocId":{"type":"string"},"borough":{"type":"string"},"ownerWallet":{"type":"string"},"ownerDid":{"anyOf":[{"type":"string"},{"type":"null"}]},"ownerLabel":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastPaidUsd":{"type":"string"},"armedAt":{"type":"number"},"claimedAt":{"type":"number"},"wallUsd":{"type":"string"},"premiumFraction":{"type":"number"},"muted":{"type":"boolean"},"content":{"type":"object","properties":{"title":{"anyOf":[{"type":"string"},{"type":"null"}]},"message":{"anyOf":[{"type":"string"},{"type":"null"}]},"link":{"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]}},"required":["title","message","link"],"additionalProperties":false},"lastPurchaseId":{"type":"string"},"version":{"type":"number"}},"required":["id","blocId","borough","ownerWallet","ownerDid","ownerLabel","lastPaidUsd","armedAt","claimedAt","wallUsd","premiumFraction","muted","content","lastPurchaseId","version"],"additionalProperties":false}}},"required":["success","pushId","message","reached"],"additionalProperties":false}}}},"402":{"description":"Authentication Required"}}}},"/api/blocks/sign":{"post":{"operationId":"blocks_sign","summary":"Update a plot's optional map title, entry-preview message, and CTA link","tags":["Blocks"],"security":[{"siwx":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"blockId":{"type":"string","pattern":"^cs-h3-[0-9a-f]{15}$"},"content":{"type":"object","properties":{"title":{"type":"string","maxLength":96},"message":{"type":"string","maxLength":1000},"link":{"type":"string","maxLength":2048}}},"expectedVersion":{"type":"integer","minimum":1,"maximum":9007199254740991},"ownerLabel":{"type":"string","maxLength":28}},"required":["blockId","expectedVersion"]}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"block":{"type":"object","properties":{"id":{"type":"string"},"blocId":{"type":"string"},"borough":{"type":"string"},"ownerWallet":{"type":"string"},"ownerDid":{"anyOf":[{"type":"string"},{"type":"null"}]},"ownerLabel":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastPaidUsd":{"type":"string"},"armedAt":{"type":"number"},"claimedAt":{"type":"number"},"wallUsd":{"type":"string"},"premiumFraction":{"type":"number"},"muted":{"type":"boolean"},"content":{"type":"object","properties":{"title":{"anyOf":[{"type":"string"},{"type":"null"}]},"message":{"anyOf":[{"type":"string"},{"type":"null"}]},"link":{"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]}},"required":["title","message","link"],"additionalProperties":false},"lastPurchaseId":{"type":"string"},"version":{"type":"number"}},"required":["id","blocId","borough","ownerWallet","ownerDid","ownerLabel","lastPaidUsd","armedAt","claimedAt","wallUsd","premiumFraction","muted","content","lastPurchaseId","version"],"additionalProperties":false}},"required":["success","block"],"additionalProperties":false}}}},"402":{"description":"Authentication Required"}}}},"/api/blocks/around":{"get":{"operationId":"blocks_around","summary":"Resolve a plot ID into a hex ring or filled circle without coordinates. Radius defaults to 1 and is capped at 3; pass the returned blockIds through the normal quote and bulk squat flow.","tags":["Blocks"],"security":[],"parameters":[{"in":"query","name":"blockId","schema":{"type":"string","pattern":"^cs-h3-([0-9a-f]{15})$"},"required":true},{"in":"query","name":"shape","schema":{"default":"ring","type":"string","enum":["ring","circle"]}},{"in":"query","name":"radius","schema":{"default":1,"type":"integer","minimum":1,"maximum":3}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"centerBlockId":{"type":"string","pattern":"^cs-h3-[0-9a-f]{15}$"},"shape":{"type":"string","enum":["ring","circle"]},"radius":{"type":"integer","minimum":1,"maximum":3},"blockIds":{"minItems":1,"maxItems":144,"type":"array","items":{"type":"string","pattern":"^cs-h3-[0-9a-f]{15}$"}}},"required":["centerBlockId","shape","radius","blockIds"],"additionalProperties":false}}}}}}},"/api/blocks/state":{"get":{"operationId":"blocks_state","summary":"List every owned NYC hex with its current wall price and premium","tags":["Blocks"],"security":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"blocks":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"blocId":{"type":"string"},"borough":{"type":"string"},"ownerWallet":{"type":"string"},"ownerDid":{"anyOf":[{"type":"string"},{"type":"null"}]},"ownerLabel":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastPaidUsd":{"type":"string"},"armedAt":{"type":"number"},"claimedAt":{"type":"number"},"wallUsd":{"type":"string"},"premiumFraction":{"type":"number"},"muted":{"type":"boolean"},"content":{"type":"object","properties":{"title":{"anyOf":[{"type":"string"},{"type":"null"}]},"message":{"anyOf":[{"type":"string"},{"type":"null"}]},"link":{"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]}},"required":["title","message","link"],"additionalProperties":false},"lastPurchaseId":{"type":"string"},"version":{"type":"number"}},"required":["id","blocId","borough","ownerWallet","ownerDid","ownerLabel","lastPaidUsd","armedAt","claimedAt","wallUsd","premiumFraction","muted","content","lastPurchaseId","version"],"additionalProperties":false}}},"required":["blocks"],"additionalProperties":false}}}}}}},"/api/blocks/quote":{"post":{"operationId":"blocks_quote","summary":"Get the authoritative current price (claim or wall), version, and displaced-owner share before paying","tags":["Blocks"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"blockId":{"type":"string","pattern":"^cs-h3-[0-9a-f]{15}$"}},"required":["blockId"]}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"blockId":{"type":"string"},"mode":{"type":"string","enum":["claim","takeover"]},"priceUsd":{"type":"string"},"ownerShareUsd":{"type":"string"},"ownerWallet":{"anyOf":[{"type":"string"},{"type":"null"}]},"ownerDid":{"anyOf":[{"type":"string"},{"type":"null"}]},"ownerLabel":{"anyOf":[{"type":"string"},{"type":"null"}]},"cooldownUntil":{"anyOf":[{"type":"number"},{"type":"null"}]},"premiumFraction":{"type":"number"},"expectedVersion":{"type":"number"}},"required":["blockId","mode","priceUsd","ownerShareUsd","ownerWallet","ownerDid","ownerLabel","cooldownUntil","premiumFraction","expectedVersion"],"additionalProperties":false}}}}}}},"/api/blocks/at":{"get":{"operationId":"blocks_at","summary":"Resolve coordinates to the plot at that point: its id, whether it is on the legal map (NYC land), and its live status and price","tags":["Blocks"],"security":[],"parameters":[{"in":"query","name":"lat","schema":{"type":"number","minimum":-90,"maximum":90},"required":true},{"in":"query","name":"lng","schema":{"type":"number","minimum":-180,"maximum":180},"required":true}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"blockId":{"type":"string","pattern":"^cs-h3-[0-9a-f]{15}$"},"inNyc":{"type":"boolean"},"block":{"anyOf":[{"type":"object","properties":{"blockId":{"type":"string","pattern":"^cs-h3-[0-9a-f]{15}$"},"status":{"type":"string","enum":["open","owned","cooldown"]},"priceUsd":{"type":"string"},"ownerWallet":{"anyOf":[{"type":"string"},{"type":"null"}]},"ownerDid":{"anyOf":[{"type":"string"},{"type":"null"}]},"ownerLabel":{"anyOf":[{"type":"string"},{"type":"null"}]},"wallUsd":{"anyOf":[{"type":"string"},{"type":"null"}]},"premiumFraction":{"anyOf":[{"type":"number"},{"type":"null"}]},"content":{"type":"object","properties":{"title":{"anyOf":[{"type":"string"},{"type":"null"}]},"message":{"anyOf":[{"type":"string"},{"type":"null"}]},"link":{"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]}},"required":["title","message","link"],"additionalProperties":false},"cooldownUntil":{"anyOf":[{"type":"number"},{"type":"null"}]},"expectedVersion":{"type":"number"}},"required":["blockId","status","priceUsd","ownerWallet","ownerDid","ownerLabel","wallUsd","premiumFraction","content","cooldownUntil","expectedVersion"],"additionalProperties":false},{"type":"null"}]}},"required":["blockId","inNyc","block"],"additionalProperties":false}}}}}}},"/api/blocks/scan":{"get":{"operationId":"blocks_scan","summary":"Scan the filled hex circle around a center (blockId, or lat and lng) and report each legal plot's status, price, and owner. Water and out-of-bounds hexes are omitted. Radius caps at 3; status=open lists claimable plots at base price.","tags":["Blocks"],"security":[],"parameters":[{"in":"query","name":"blockId","schema":{"type":"string","pattern":"^cs-h3-[0-9a-f]{15}$"}},{"in":"query","name":"lat","schema":{"type":"number","minimum":-90,"maximum":90}},{"in":"query","name":"lng","schema":{"type":"number","minimum":-180,"maximum":180}},{"in":"query","name":"radius","schema":{"default":2,"type":"integer","minimum":1,"maximum":3}},{"in":"query","name":"status","schema":{"default":"all","type":"string","enum":["all","open","owned"]}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"centerBlockId":{"type":"string","pattern":"^cs-h3-[0-9a-f]{15}$"},"radius":{"type":"number"},"scanned":{"type":"number"},"offMap":{"type":"number"},"blocks":{"type":"array","items":{"type":"object","properties":{"blockId":{"type":"string","pattern":"^cs-h3-[0-9a-f]{15}$"},"status":{"type":"string","enum":["open","owned","cooldown"]},"priceUsd":{"type":"string"},"ownerWallet":{"anyOf":[{"type":"string"},{"type":"null"}]},"ownerDid":{"anyOf":[{"type":"string"},{"type":"null"}]},"ownerLabel":{"anyOf":[{"type":"string"},{"type":"null"}]},"wallUsd":{"anyOf":[{"type":"string"},{"type":"null"}]},"premiumFraction":{"anyOf":[{"type":"number"},{"type":"null"}]},"content":{"type":"object","properties":{"title":{"anyOf":[{"type":"string"},{"type":"null"}]},"message":{"anyOf":[{"type":"string"},{"type":"null"}]},"link":{"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]}},"required":["title","message","link"],"additionalProperties":false},"cooldownUntil":{"anyOf":[{"type":"number"},{"type":"null"}]},"expectedVersion":{"type":"number"}},"required":["blockId","status","priceUsd","ownerWallet","ownerDid","ownerLabel","wallUsd","premiumFraction","content","cooldownUntil","expectedVersion"],"additionalProperties":false}}},"required":["centerBlockId","radius","scanned","offMap","blocks"],"additionalProperties":false}}}}}}},"/api/map":{"get":{"operationId":"map","summary":"Legal-map metadata and game rules: bounds, H3 resolution, plot id format, boundary polygon URL, economy constants, and how legality is checked","tags":["Map"],"security":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"city":{"type":"string"},"h3Resolution":{"type":"number"},"blockIdFormat":{"type":"string"},"bounds":{"type":"object","properties":{"minLat":{"type":"number"},"maxLat":{"type":"number"},"minLng":{"type":"number"},"maxLng":{"type":"number"}},"required":["minLat","maxLat","minLng","maxLng"],"additionalProperties":false},"boundaryGeojsonUrl":{"type":"string"},"legality":{"type":"string"},"claimedCount":{"type":"number"},"maxBulkBlocks":{"type":"number"},"economy":{"type":"object","properties":{"basePriceUsd":{"type":"string"},"takeoverMultiplier":{"type":"number"},"wallHalfLifeHours":{"type":"number"},"pushAgingHours":{"type":"number"},"pushHexHourlyCap":{"type":"number"},"mutePremiumThreshold":{"type":"number"},"rearmPriceFraction":{"type":"number"},"ownerTakeoverShare":{"type":"number"},"flipCooldownMs":{"type":"number"},"maxMessageLength":{"type":"number"}},"required":["basePriceUsd","takeoverMultiplier","wallHalfLifeHours","pushAgingHours","pushHexHourlyCap","mutePremiumThreshold","rearmPriceFraction","ownerTakeoverShare","flipCooldownMs","maxMessageLength"],"additionalProperties":false}},"required":["city","h3Resolution","blockIdFormat","bounds","boundaryGeojsonUrl","legality","claimedCount","maxBulkBlocks","economy"],"additionalProperties":false}}}}}}},"/api/health":{"get":{"operationId":"health","summary":"Check the CitySquatters payment service","tags":["Health"],"security":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"ok"},"service":{"type":"string","const":"citysquatters"}},"required":["status","service"],"additionalProperties":false}}}}}}}},"components":{"securitySchemes":{"siwx":{"type":"apiKey","in":"header","name":"SIGN-IN-WITH-X"}}}}