{"openapi":"3.1.0","info":{"title":"Pirate Skills agent API","version":"1","summary":"Search the Pirate Skills codices, list and join events, see the passes and act for a signed-in person.","description":"The same tools as the MCP server at https://pirateskills.com/mcp, over plain HTTP. Public tools need no sign-in. A tool about the person needs an API key (made at https://pirateskills.com/lab/settings, see https://pirateskills.com/docs/sign-in) or an OAuth sign-in with their Pirate Skills account, and costs gold from their wallet.\n\n**Versions.** The version is in the path: /api/public/agent/v1/. v1 is stable – fields may be added, none removed or changed. A change that would break a caller ships as /v2, beside v1. **Deprecation policy:** a version is retired only after at least 90 days' notice – from the day it is announced, its answers carry a `Deprecation` header (RFC 9745) and a `Sunset` header (RFC 8594) with the last day, and the date is published at https://pirateskills.com/docs/versions. The unversioned address /api/public/agent/tools is an alias of v1.\n\n**Retries.** A tool that changes something accepts an `Idempotency-Key` header; see each operation.\n\n**Limits.** 60 calls a minute per address; every answer carries `RateLimit-Policy` and `X-RateLimit-Limit`.","contact":{"name":"Pirate Skills","url":"https://pirateskills.com/contact","email":"contact@pirateskills.com"}},"externalDocs":{"description":"Docs – API keys, the MCP server, the CLI, WebMCP and every tool","url":"https://pirateskills.com/docs"},"x-deprecation-policy":{"noticeDays":90,"headers":["Deprecation","Sunset"],"url":"https://pirateskills.com/docs/versions"},"servers":[{"url":"https://pirateskills.com"}],"tags":[{"name":"Discovery","description":"What this caller may use."},{"name":"Public tools","description":"No sign-in, free."},{"name":"Signed-in tools","description":"Act for one person; each call costs gold."}],"paths":{"/api/public/agent/v1/tools":{"get":{"operationId":"list_tools","summary":"The tools this caller may use.","description":"A visitor sees the public tools; a signed-in person or an API-key holder sees their tier. Each tool carries `confirm` (ask the person first) and its input as JSON Schema.","tags":["Discovery"],"security":[{},{"apiKey":[]},{"oauth2":["openid","profile","email"]}],"responses":{"200":{"description":"The tools, with their inputs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolList"}}}},"401":{"description":"The token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/public/agent/v1/tools/search_knowledge":{"post":{"operationId":"search_knowledge","summary":"Search the Pirate Skills knowledge: the Growth Codex, the Builder Codex and Insights.","description":"Search the Pirate Skills knowledge: the Growth Codex, the Builder Codex and Insights. Returns the best matching chapters with a link; for a signed-in person each also carries a short excerpt. Without sign-in it returns titles and links only (which codex, the title, the url): the person signs in for the excerpts. Cite the url of every chapter you use in your answer.\n\nReads only. Also runs as a GET with the input in the query string.\n\nPublic: no sign-in needed, free.","tags":["Public tools"],"security":[{},{"apiKey":[]},{"oauth2":["openid","profile","email"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"query":{"type":"string","minLength":2,"maxLength":200},"limit":{"default":5,"type":"integer","minimum":1,"maximum":20}},"required":["query"]}}}},"responses":{"200":{"description":"The tool ran. `result` is the tool's answer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"description":"The input does not match the tool's schema; `issues` says which field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The tool needs a signed-in person, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"The person's wallet has no gold left for a tool call (`code: out_of_gold`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The person's tier does not include this tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No tool by that name.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/public/agent/v1/tools/list_events":{"post":{"operationId":"list_events","summary":"Upcoming Pirate Skills events, soonest first by date, with a link to each event page (a Forge session links the Forge page, where the seat is sold) and, for a signed-in person, whether they are registered.","description":"Upcoming Pirate Skills events, soonest first by date, with a link to each event page (a Forge session links the Forge page, where the seat is sold) and, for a signed-in person, whether they are registered. A Forge cohort appears only as its start – the first session of its Build or Grow part; its weekly sessions are never listed here. Present them in that date order, and give each event its one line from `about` – what it is and who it is for – so the person knows what they are looking at (an event without `about` is a one-off; its subtitle says it). When the person asks about their own Forge cohort or its sessions, use my_forge_sessions instead. `cadence` is how often that event's format meets – weekly only for the Forge (every week of a six-week phase), monthly for Vibe Coding Cologne, the Pirate Lab and AI Compass, quarterly for the Vibe Hackathon, one-off otherwise; give each event its own and never carry one event's cadence over to the others. `when` is the day and time to quote, in Berlin time; `startsAt`/`endsAt` are the same moment in UTC, for working with, never for quoting (the Captain's copy leaves them out, and gives a subtitle an earlier event already carried as null).\n\nReads only. Also runs as a GET with the input in the query string.\n\nPublic: no sign-in needed, free.","tags":["Public tools"],"security":[{},{"apiKey":[]},{"oauth2":["openid","profile","email"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"type":{"description":"Filter by event type label, e.g. \"Pirate Lab\" or \"Vibe Coding Cologne\". Omit for all.","type":"string"},"limit":{"default":10,"type":"integer","minimum":1,"maximum":50}}}}}},"responses":{"200":{"description":"The tool ran. `result` is the tool's answer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"description":"The input does not match the tool's schema; `issues` says which field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The tool needs a signed-in person, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"The person's wallet has no gold left for a tool call (`code: out_of_gold`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The person's tier does not include this tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No tool by that name.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/public/agent/v1/tools/get_offers":{"post":{"operationId":"get_offers","summary":"What Pirate Skills sells right now, with prices, read live (only what is on sale appears, and only what create_checkout sells): the Pirate Pass and the Forge Pass (monthly, prices before VAT, three-month minimum), which replace the Pirate Forge tiers (those are listed only until the passes are on sale), and a Captain on Deck session with Ben (the price is per session; up to 10 in one checkout) while it is on sale – each bought with create_checkout.","description":"What Pirate Skills sells right now, with prices, read live (only what is on sale appears, and only what create_checkout sells): the Pirate Pass and the Forge Pass (monthly, prices before VAT, three-month minimum), which replace the Pirate Forge tiers (those are listed only until the passes are on sale), and a Captain on Deck session with Ben (the price is per session; up to 10 in one checkout) while it is on sale – each bought with create_checkout. `priceText` is the price to quote: euros, plus US dollars once a dollar price is set (both in one string, \"€ / $\"), with the person's likely currency first. An offer marked purchasable false carries a note saying why (a Pirate Pass holder cannot buy the Forge Pass on top). Event tickets (the Vibe Hackathon) are not listed here: a ticket is bought on the event page from list_events, where the price depends on the date and tier. Free events are registered with register_for_event, and the free Codex is read with search_knowledge. Every purchase is paid by the person on Stripe's own page; no agent takes a card or charges anyone.\n\nReads only. Also runs as a GET with the input in the query string.\n\nPublic: no sign-in needed, free.","tags":["Public tools"],"security":[{},{"apiKey":[]},{"oauth2":["openid","profile","email"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{}}}}},"responses":{"200":{"description":"The tool ran. `result` is the tool's answer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"description":"The input does not match the tool's schema; `issues` says which field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The tool needs a signed-in person, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"The person's wallet has no gold left for a tool call (`code: out_of_gold`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The person's tier does not include this tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No tool by that name.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/public/agent/v1/tools/register_for_event":{"post":{"operationId":"register_for_event","summary":"Register the signed-in person for a free upcoming event by its id (from list_events).","description":"Register the signed-in person for a free upcoming event by its id (from list_events). Paid events are not registered here: the answer carries the event page where a ticket is bought.\n\nChanges something for the person: ask them first. Runs on POST only.\n\nNeeds a signed-in person (an API key or an OAuth sign-in); each call costs gold from their wallet.","tags":["Signed-in tools"],"security":[{"apiKey":[]},{"oauth2":["openid","profile","email"]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Makes a retry safe: send the same key again and you get the first answer back (header `Idempotent-Replayed: true`) instead of a second run. Kept 24 hours. 1–255 visible ASCII characters, e.g. a UUID; one key per intended action.","schema":{"type":"string","minLength":1,"maxLength":255}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"eventId":{"type":"string","minLength":1,"maxLength":128}},"required":["eventId"]}}}},"responses":{"200":{"description":"The tool ran. `result` is the tool's answer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"description":"The input does not match the tool's schema; `issues` says which field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The tool needs a signed-in person, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"The person's wallet has no gold left for a tool call (`code: out_of_gold`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The person's tier does not include this tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No tool by that name.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A request with this Idempotency-Key is still running (`code: idempotency_in_progress`). Retry in a moment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"This Idempotency-Key was already used for a different request (`code: idempotency_key_reused`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/public/agent/v1/tools/cancel_registration":{"post":{"operationId":"cancel_registration","summary":"Cancel the signed-in person's own registration for an event by its id.","description":"Cancel the signed-in person's own registration for an event by its id.\n\nChanges something for the person: ask them first. Runs on POST only.\n\nNeeds a signed-in person (an API key or an OAuth sign-in); each call costs gold from their wallet.","tags":["Signed-in tools"],"security":[{"apiKey":[]},{"oauth2":["openid","profile","email"]}],"x-destructive":true,"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Makes a retry safe: send the same key again and you get the first answer back (header `Idempotent-Replayed: true`) instead of a second run. Kept 24 hours. 1–255 visible ASCII characters, e.g. a UUID; one key per intended action.","schema":{"type":"string","minLength":1,"maxLength":255}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"eventId":{"type":"string","minLength":1,"maxLength":128}},"required":["eventId"]}}}},"responses":{"200":{"description":"The tool ran. `result` is the tool's answer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"description":"The input does not match the tool's schema; `issues` says which field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The tool needs a signed-in person, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"The person's wallet has no gold left for a tool call (`code: out_of_gold`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The person's tier does not include this tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No tool by that name.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A request with this Idempotency-Key is still running (`code: idempotency_in_progress`). Retry in a moment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"This Idempotency-Key was already used for a different request (`code: idempotency_key_reused`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/public/agent/v1/tools/my_access":{"post":{"operationId":"my_access","summary":"What the signed-in person has access to on Pirate Skills: the Codex, event series, the Forge, tools — with when and how each was unlocked.","description":"What the signed-in person has access to on Pirate Skills: the Codex, event series, the Forge, tools — with when and how each was unlocked.\n\nReads only. Also runs as a GET with the input in the query string.\n\nNeeds a signed-in person (an API key or an OAuth sign-in); each call costs gold from their wallet.","tags":["Signed-in tools"],"security":[{"apiKey":[]},{"oauth2":["openid","profile","email"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{}}}}},"responses":{"200":{"description":"The tool ran. `result` is the tool's answer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"description":"The input does not match the tool's schema; `issues` says which field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The tool needs a signed-in person, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"The person's wallet has no gold left for a tool call (`code: out_of_gold`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The person's tier does not include this tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No tool by that name.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/public/agent/v1/tools/create_checkout":{"post":{"operationId":"create_checkout","summary":"Start a purchase for the signed-in person and get back a Stripe checkout link, for an offer key from get_offers: the Pirate Pass or the Forge Pass, Captain on Deck sessions while they are on sale, or a Pirate Forge tier while one is still listed.","description":"Start a purchase for the signed-in person and get back a Stripe checkout link, for an offer key from get_offers: the Pirate Pass or the Forge Pass, Captain on Deck sessions while they are on sale, or a Pirate Forge tier while one is still listed. `quantity` (1–10, default 1) is only for Captain on Deck sessions (`captain_on_deck_session`): one checkout buys that many sessions, one diamond each; any other offer with a quantity is refused. `currency` (`eur` or `usd`) is what Stripe charges in; leave it out and the checkout follows the caller's country when the request carries one – euros in Europe, dollars elsewhere – else euros. An offer without a dollar price is charged in euros either way. Event tickets are not sold here: send the person to the event page from list_events. Give the person the link; they pay on Stripe's page themselves. No agent ever charges a card, and nothing is charged until the person completes that page. The sale is credited to the agent that started it.\n\nChanges something for the person: ask them first. Runs on POST only.\n\nNeeds a signed-in person (an API key or an OAuth sign-in); each call costs gold from their wallet.","tags":["Signed-in tools"],"security":[{"apiKey":[]},{"oauth2":["openid","profile","email"]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Makes a retry safe: send the same key again and you get the first answer back (header `Idempotent-Replayed: true`) instead of a second run. Kept 24 hours. 1–255 visible ASCII characters, e.g. a UUID; one key per intended action.","schema":{"type":"string","minLength":1,"maxLength":255}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"offerKey":{"type":"string","minLength":1,"maxLength":64},"quantity":{"description":"How many Captain on Deck sessions to buy, 1–10. Only for captain_on_deck_session; omit for every other offer.","type":"integer","minimum":1,"maximum":10},"currency":{"description":"The currency Stripe charges in. Omit to follow the caller's country (Europe: eur, elsewhere: usd), or eur when it is unknown.","type":"string","enum":["eur","usd"]}},"required":["offerKey"]}}}},"responses":{"200":{"description":"The tool ran. `result` is the tool's answer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"description":"The input does not match the tool's schema; `issues` says which field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The tool needs a signed-in person, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"The person's wallet has no gold left for a tool call (`code: out_of_gold`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The person's tier does not include this tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No tool by that name.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A request with this Idempotency-Key is still running (`code: idempotency_in_progress`). Retry in a moment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"This Idempotency-Key was already used for a different request (`code: idempotency_key_reused`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/public/agent/v1/tools/my_wallet":{"post":{"operationId":"my_wallet","summary":"The signed-in person's wallet: `gold.balance` and `diamonds` are counts; `emerald` is the pass they hold, in words (\"Pirate Pass until 17 Oct 2026\", \"Forge Pass until …\" or \"no pass\") – emerald is never a number, so never give it as one.","description":"The signed-in person's wallet: `gold.balance` and `diamonds` are counts; `emerald` is the pass they hold, in words (\"Pirate Pass until 17 Oct 2026\", \"Forge Pass until …\" or \"no pass\") – emerald is never a number, so never give it as one. Also how much of this month's gold drip is left and what they earned, the next refill date, when earned gold expires next (earned gold keeps twelve months, oldest first; `gold.expiresNext` is the amount and day within 60 days, or null), and the recent history. What gold is and buys, for the person: https://pirateskills.com/gold.\n\nReads only. Also runs as a GET with the input in the query string.\n\nNeeds a signed-in person (an API key or an OAuth sign-in); each call costs gold from their wallet.","tags":["Signed-in tools"],"security":[{"apiKey":[]},{"oauth2":["openid","profile","email"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"limit":{"default":10,"type":"integer","minimum":1,"maximum":50}}}}}},"responses":{"200":{"description":"The tool ran. `result` is the tool's answer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"description":"The input does not match the tool's schema; `issues` says which field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The tool needs a signed-in person, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"The person's wallet has no gold left for a tool call (`code: out_of_gold`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The person's tier does not include this tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No tool by that name.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/public/agent/v1/tools/my_referrals":{"post":{"operationId":"my_referrals","summary":"The signed-in person's referral link, the people who signed up through it (first name and initial), and what each brought: gold or a diamond already paid, rewards pending with their pay date, and rewards not paid with the reason.","description":"The signed-in person's referral link, the people who signed up through it (first name and initial), and what each brought: gold or a diamond already paid, rewards pending with their pay date, and rewards not paid with the reason. Referrals pay nothing on signup; they pay when someone brought shows up to their first event, buys, or joins the Forge, after a wait and not at all if the purchase is refunded in that time. What each outcome pays right now and the wait in days are in `terms`, read from the live rules; `terms.on` false means rewards are paused.\n\nReads only. Also runs as a GET with the input in the query string.\n\nNeeds a signed-in person (an API key or an OAuth sign-in); each call costs gold from their wallet.","tags":["Signed-in tools"],"security":[{"apiKey":[]},{"oauth2":["openid","profile","email"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{}}}}},"responses":{"200":{"description":"The tool ran. `result` is the tool's answer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"description":"The input does not match the tool's schema; `issues` says which field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The tool needs a signed-in person, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"The person's wallet has no gold left for a tool call (`code: out_of_gold`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The person's tier does not include this tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No tool by that name.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/public/agent/v1/tools/my_profile":{"post":{"operationId":"my_profile","summary":"The signed-in person's name and email as Pirate Skills knows them.","description":"The signed-in person's name and email as Pirate Skills knows them.\n\nReads only. Also runs as a GET with the input in the query string.\n\nNeeds a signed-in person (an API key or an OAuth sign-in); each call costs gold from their wallet.","tags":["Signed-in tools"],"security":[{"apiKey":[]},{"oauth2":["openid","profile","email"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{}}}}},"responses":{"200":{"description":"The tool ran. `result` is the tool's answer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"description":"The input does not match the tool's schema; `issues` says which field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The tool needs a signed-in person, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"The person's wallet has no gold left for a tool call (`code: out_of_gold`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The person's tier does not include this tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No tool by that name.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/public/agent/v1/tools/my_forge_sessions":{"post":{"operationId":"my_forge_sessions","summary":"The Pirate Forge live sessions the signed-in person can still join: each upcoming quarter's Build phase (weeks 1–6) and Grow phase (weeks 7–12), sessions left, and whether they are in.","description":"The Pirate Forge live sessions the signed-in person can still join: each upcoming quarter's Build phase (weeks 1–6) and Grow phase (weeks 7–12), sessions left, and whether they are in. Empty with hasAccess false when they hold no active Forge access.\n\nReads only. Also runs as a GET with the input in the query string.\n\nNeeds a signed-in person (an API key or an OAuth sign-in); each call costs gold from their wallet.","tags":["Signed-in tools"],"security":[{"apiKey":[]},{"oauth2":["openid","profile","email"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{}}}}},"responses":{"200":{"description":"The tool ran. `result` is the tool's answer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"description":"The input does not match the tool's schema; `issues` says which field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The tool needs a signed-in person, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"The person's wallet has no gold left for a tool call (`code: out_of_gold`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The person's tier does not include this tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No tool by that name.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/public/agent/v1/tools/join_forge_cohort":{"post":{"operationId":"join_forge_cohort","summary":"Join the signed-in person to Pirate Forge live sessions: a whole cohort from now on (phase \"all\") or one phase (\"build\" or \"grow\"), by quarter key from my_forge_sessions.","description":"Join the signed-in person to Pirate Forge live sessions: a whole cohort from now on (phase \"all\") or one phase (\"build\" or \"grow\"), by quarter key from my_forge_sessions. Only sessions still ahead are added; needs active Forge access. The answer says whether the calendar invite went out or Ben adds it by hand.\n\nChanges something for the person: ask them first. Runs on POST only.\n\nNeeds a signed-in person (an API key or an OAuth sign-in); each call costs gold from their wallet.","tags":["Signed-in tools"],"security":[{"apiKey":[]},{"oauth2":["openid","profile","email"]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Makes a retry safe: send the same key again and you get the first answer back (header `Idempotent-Replayed: true`) instead of a second run. Kept 24 hours. 1–255 visible ASCII characters, e.g. a UUID; one key per intended action.","schema":{"type":"string","minLength":1,"maxLength":255}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"quarterKey":{"type":"string","pattern":"^\\d{4}_q[1-4]$","description":"The quarter, e.g. \"2026_q4\" (from my_forge_sessions)."},"phase":{"type":"string","enum":["build","grow","all"],"description":"\"build\" (weeks 1–6), \"grow\" (weeks 7–12), or \"all\" for the whole cohort from now on."}},"required":["quarterKey","phase"]}}}},"responses":{"200":{"description":"The tool ran. `result` is the tool's answer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"description":"The input does not match the tool's schema; `issues` says which field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The tool needs a signed-in person, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"The person's wallet has no gold left for a tool call (`code: out_of_gold`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The person's tier does not include this tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No tool by that name.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A request with this Idempotency-Key is still running (`code: idempotency_in_progress`). Retry in a moment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"This Idempotency-Key was already used for a different request (`code: idempotency_key_reused`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/public/agent/v1/tools/my_bookings":{"post":{"operationId":"my_bookings","summary":"The signed-in person's time with Ben.","description":"The signed-in person's time with Ben. Their hours with Ben: how many diamonds they hold (one diamond = one hour, one to one), their bookings with status (held, confirmed, cancelled) and join link, and the open hours ahead they can book with book_hour_with_ben. And the free 30-minute intro call (introCall): their upcoming one with its join link, or, when they have none, the open times they can book with book_intro_call. Each booking has its `id`, `label`, `canCancel` and `canMove`: cancel one with cancel_booking, move one with move_booking to an open time of the same kind (`openHours` for an hour with Ben, `introCall.moveTimes` for the free intro call). Booking, moving and cancelling happen here; `url` is a page to fall back to only if booking here fails. Each open time has `label` (weekday, date, time and time zone, worked out for the person's time zone, e.g. \"Thursday, 17 September · 10:00–10:30 (Berlin time)\") and `day`: quote `label` exactly as it is, and never work out a weekday or a date from `start` yourself. Pass `start` exactly as listed to book. `openDays` and `introCall.openDays` group the times by day; `bookableUntil` is the last day the calendar takes bookings for. Pass their time zone to get the times in it. Pass `purpose` when the person wants to book (intro_call or hour_with_ben): the next two weeks are listed, and a chat that can show a time picker shows one.\n\nReads only. Also runs as a GET with the input in the query string.\n\nNeeds a signed-in person (an API key or an OAuth sign-in); each call costs gold from their wallet.","tags":["Signed-in tools"],"security":[{"apiKey":[]},{"oauth2":["openid","profile","email"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"timeZone":{"description":"The person's time zone, e.g. \"Europe/Berlin\". Defaults to Berlin.","type":"string","maxLength":64},"limit":{"default":20,"description":"How many open hours, and how many intro-call times, to list.","type":"integer","minimum":1,"maximum":40},"purpose":{"description":"What the person wants to book right now: intro_call (the free 30-minute call) or hour_with_ben (one diamond). Omit when they only ask about their bookings.","type":"string","enum":["intro_call","hour_with_ben"]}}}}}},"responses":{"200":{"description":"The tool ran. `result` is the tool's answer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"description":"The input does not match the tool's schema; `issues` says which field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The tool needs a signed-in person, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"The person's wallet has no gold left for a tool call (`code: out_of_gold`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The person's tier does not include this tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No tool by that name.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/public/agent/v1/tools/book_hour_with_ben":{"post":{"operationId":"book_hour_with_ben","summary":"Spend one of the signed-in person's diamonds on a one-to-one hour with Ben, at an open hour from my_bookings (pass its start exactly as listed, and name the hour by its label, never by a weekday you work out).","description":"Spend one of the signed-in person's diamonds on a one-to-one hour with Ben, at an open hour from my_bookings (pass its start exactly as listed, and name the hour by its label, never by a weekday you work out). The diamond is held at once and spent when Ben's calendar confirms, usually within a minute; if the hour is not booked it comes back. The answer's booking has its own label. Before the hour starts the person can move it with move_booking, or cancel it with cancel_booking and get the diamond back.\n\nChanges something for the person: ask them first. Runs on POST only.\n\nNeeds a signed-in person (an API key or an OAuth sign-in); each call costs gold from their wallet.","tags":["Signed-in tools"],"security":[{"apiKey":[]},{"oauth2":["openid","profile","email"]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Makes a retry safe: send the same key again and you get the first answer back (header `Idempotent-Replayed: true`) instead of a second run. Kept 24 hours. 1–255 visible ASCII characters, e.g. a UUID; one key per intended action.","schema":{"type":"string","minLength":1,"maxLength":255}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"start":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","description":"The start of an open hour exactly as my_bookings lists it, e.g. \"2026-09-17T13:30:00.000+02:00\"."},"timeZone":{"description":"The person's time zone, e.g. \"Europe/Berlin\". Defaults to Berlin.","type":"string","maxLength":64},"topic":{"description":"What the person wants to work on in the hour, in a sentence or two.","type":"string","maxLength":500}},"required":["start"]}}}},"responses":{"200":{"description":"The tool ran. `result` is the tool's answer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"description":"The input does not match the tool's schema; `issues` says which field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The tool needs a signed-in person, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"The person's wallet has no gold left for a tool call (`code: out_of_gold`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The person's tier does not include this tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No tool by that name.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A request with this Idempotency-Key is still running (`code: idempotency_in_progress`). Retry in a moment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"This Idempotency-Key was already used for a different request (`code: idempotency_key_reused`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/public/agent/v1/tools/book_intro_call":{"post":{"operationId":"book_intro_call","summary":"Book the signed-in person a free 30-minute intro call with Ben, at a time from my_bookings (introCall.openTimes; pass its start exactly as listed, and name the time by its label, never by a weekday you work out).","description":"Book the signed-in person a free 30-minute intro call with Ben, at a time from my_bookings (introCall.openTimes; pass its start exactly as listed, and name the time by its label, never by a weekday you work out). Book it here: do not send the person to a booking page unless this refuses or fails. No diamond, nothing charged; the calendar invite comes from cal.com. The answer's booking has its own label and join link; move it with move_booking, cancel it with cancel_booking. One upcoming free call per person at a time: while one stands, this refuses and names it. Offer the free 30-minute intro call with Ben when the person is interested in the Pirate Forge (the Forge Pass) or in working with Ben one to one – Captain on Deck, which people also call an in-house workshop, consulting or freelance work. Never offer it for the Pirate Pass or for an event ticket.\n\nChanges something for the person: ask them first. Runs on POST only.\n\nNeeds a signed-in person (an API key or an OAuth sign-in); each call costs gold from their wallet.","tags":["Signed-in tools"],"security":[{"apiKey":[]},{"oauth2":["openid","profile","email"]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Makes a retry safe: send the same key again and you get the first answer back (header `Idempotent-Replayed: true`) instead of a second run. Kept 24 hours. 1–255 visible ASCII characters, e.g. a UUID; one key per intended action.","schema":{"type":"string","minLength":1,"maxLength":255}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"start":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","description":"The start of a free intro-call time exactly as my_bookings lists it under introCall.openTimes, e.g. \"2026-09-17T10:00:00.000+02:00\"."},"timeZone":{"description":"The person's time zone, e.g. \"Europe/Berlin\". Defaults to Berlin.","type":"string","maxLength":64},"topic":{"description":"What the person is deciding about (the Forge Pass, a Captain on Deck session) or wants to ask, in a sentence or two.","type":"string","maxLength":500}},"required":["start"]}}}},"responses":{"200":{"description":"The tool ran. `result` is the tool's answer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"description":"The input does not match the tool's schema; `issues` says which field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The tool needs a signed-in person, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"The person's wallet has no gold left for a tool call (`code: out_of_gold`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The person's tier does not include this tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No tool by that name.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A request with this Idempotency-Key is still running (`code: idempotency_in_progress`). Retry in a moment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"This Idempotency-Key was already used for a different request (`code: idempotency_key_reused`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/public/agent/v1/tools/move_booking":{"post":{"operationId":"move_booking","summary":"Move one of the signed-in person's own upcoming bookings (the free intro call or an hour with Ben, by its id from my_bookings, where canMove is true) to another open time of the same kind: for an hour with Ben a start from openHours, for the free intro call a start from introCall.moveTimes.","description":"Move one of the signed-in person's own upcoming bookings (the free intro call or an hour with Ben, by its id from my_bookings, where canMove is true) to another open time of the same kind: for an hour with Ben a start from openHours, for the free intro call a start from introCall.moveTimes. Pass the start exactly as listed, and name the new time by its label, never by a weekday you work out. Nothing is charged: an hour keeps its diamond, the call stays free, and the calendar sends the updated invite. The answer's booking has the new label. Refused, with a reason, for a booking that is not theirs, already cancelled, begun, still waiting for the calendar, or a time that is not open.\n\nChanges something for the person: ask them first. Runs on POST only.\n\nNeeds a signed-in person (an API key or an OAuth sign-in); each call costs gold from their wallet.","tags":["Signed-in tools"],"security":[{"apiKey":[]},{"oauth2":["openid","profile","email"]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Makes a retry safe: send the same key again and you get the first answer back (header `Idempotent-Replayed: true`) instead of a second run. Kept 24 hours. 1–255 visible ASCII characters, e.g. a UUID; one key per intended action.","schema":{"type":"string","minLength":1,"maxLength":255}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"bookingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The id of one of the person's own upcoming bookings, exactly as my_bookings lists it."},"start":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","description":"The new start, exactly as my_bookings lists it for that kind of booking: openHours for an hour with Ben, introCall.moveTimes for the free intro call, e.g. \"2026-09-18T11:30:00.000+02:00\"."},"timeZone":{"description":"The person's time zone, e.g. \"Europe/Berlin\". Defaults to the booking's own.","type":"string","maxLength":64}},"required":["bookingId","start"]}}}},"responses":{"200":{"description":"The tool ran. `result` is the tool's answer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"description":"The input does not match the tool's schema; `issues` says which field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The tool needs a signed-in person, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"The person's wallet has no gold left for a tool call (`code: out_of_gold`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The person's tier does not include this tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No tool by that name.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A request with this Idempotency-Key is still running (`code: idempotency_in_progress`). Retry in a moment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"This Idempotency-Key was already used for a different request (`code: idempotency_key_reused`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/public/agent/v1/tools/cancel_booking":{"post":{"operationId":"cancel_booking","summary":"Cancel one of the signed-in person's own upcoming bookings by its id from my_bookings (where canCancel is true): the free intro call, or an hour with Ben, whose diamond comes back in their wallet.","description":"Cancel one of the signed-in person's own upcoming bookings by its id from my_bookings (where canCancel is true): the free intro call, or an hour with Ben, whose diamond comes back in their wallet. Name the booking by its label when you ask for their yes. Refused, with a reason, for a booking that is not theirs, already cancelled, or already begun.\n\nChanges something for the person: ask them first. Runs on POST only.\n\nNeeds a signed-in person (an API key or an OAuth sign-in); each call costs gold from their wallet.","tags":["Signed-in tools"],"security":[{"apiKey":[]},{"oauth2":["openid","profile","email"]}],"x-destructive":true,"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Makes a retry safe: send the same key again and you get the first answer back (header `Idempotent-Replayed: true`) instead of a second run. Kept 24 hours. 1–255 visible ASCII characters, e.g. a UUID; one key per intended action.","schema":{"type":"string","minLength":1,"maxLength":255}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"bookingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The id of one of the person's own upcoming bookings, exactly as my_bookings lists it."},"reason":{"description":"Why, in the person's words, when they gave one. Optional.","type":"string","maxLength":300}},"required":["bookingId"]}}}},"responses":{"200":{"description":"The tool ran. `result` is the tool's answer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"description":"The input does not match the tool's schema; `issues` says which field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The tool needs a signed-in person, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"The person's wallet has no gold left for a tool call (`code: out_of_gold`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The person's tier does not include this tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No tool by that name.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A request with this Idempotency-Key is still running (`code: idempotency_in_progress`). Retry in a moment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"This Idempotency-Key was already used for a different request (`code: idempotency_key_reused`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"A Pirate Skills API key, made in Settings → API keys (https://pirateskills.com/docs/sign-in). It acts as the person who made it, with their tier."},"oauth2":{"type":"oauth2","description":"Sign the person in with their Pirate Skills account (Clerk). Clients can register themselves at the registration endpoint in the authorization server metadata.","flows":{"authorizationCode":{"authorizationUrl":"https://clerk.pirateskills.com/oauth/authorize","tokenUrl":"https://clerk.pirateskills.com/oauth/token","refreshUrl":"https://clerk.pirateskills.com/oauth/token","scopes":{"openid":"Sign the person in with their Pirate Skills account.","profile":"Read the person's name, so tools can greet and address them.","email":"Read the person's email address, which identifies their registrations and purchases."}}}}},"schemas":{"Error":{"type":"object","required":["ok","error"],"properties":{"ok":{"const":false},"error":{"type":"string","description":"What went wrong, in words."},"code":{"type":"string","description":"A machine-readable reason where there is one, e.g. `out_of_gold`."},"issues":{"type":"array","items":{"type":"object"},"description":"For an invalid input: which fields and why."}}},"ToolResult":{"type":"object","required":["ok","tool","result"],"properties":{"ok":{"const":true},"tool":{"type":"string"},"result":{"description":"The tool's answer; its shape is described in the tool's description."}}},"ToolList":{"type":"object","required":["ok","viewer","tools"],"properties":{"ok":{"const":true},"viewer":{"type":"object","properties":{"tier":{"enum":["public","user","admin"]}}},"docs":{"type":"string","format":"uri"},"tools":{"type":"array","items":{"type":"object","required":["name","tier","description","confirm","inputSchema"],"properties":{"name":{"type":"string"},"tier":{"enum":["public","user"]},"description":{"type":"string"},"confirm":{"type":"boolean"},"destructive":{"type":"boolean"},"inputSchema":{"type":"object"}}}}}}}}}