{"openapi":"3.1.0","info":{"title":"Crossword Build API","version":"0.1.0","description":"A real, playable, fully local crossword generator — stateless: the caller holds and passes the puzzle state between calls.\n\nEvery operation is read-only or compute-only. The same tools are available over MCP (streamable HTTP) at https://crosswordbuild.connectorbay.com/mcp.","contact":{"name":"Unify Dynamics LLC","email":"hr@unifydynamics.com","url":"https://connectorbay.com/crosswordbuild/docs"},"termsOfService":"https://connectorbay.com/crosswordbuild/terms"},"servers":[{"url":"https://crosswordbuild.connectorbay.com"}],"externalDocs":{"url":"https://connectorbay.com/crosswordbuild/docs"},"security":[{},{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"Optional. A Pro API key raises rate limits; no credentials are required."}},"schemas":{"Error":{"type":"object","properties":{"ok":{"const":false},"error":{"type":"object"}}}}},"paths":{"/v1/tools/new_game":{"post":{"operationId":"new_game","summary":"Generate a fresh, original crossword: a symmetric black-square layout plus a real word fill where","description":"Generate a fresh, original crossword: a symmetric black-square layout plus a real word fill where\n    every intersection agrees on its shared letter. Returns the game `state` (includes the solution — hold\n    onto it and pass it into every other tool) and a blank `render`ing to show the player.","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"size":{"default":5,"description":"Grid side length, 5-9 (even values are rounded up to the next odd size).","maximum":9,"minimum":5,"title":"Size","type":"integer"},"theme":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Optional category to restrict the hand-clued word bank to (see list_categories). Omit for a general-purpose puzzle.","title":"Theme"},"word_list":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"items":{"additionalProperties":{"type":"string"},"type":"object"},"type":"array"},{"type":"null"}],"default":null,"description":"Optional list of your own words to build the puzzle from, either plain strings or {\"word\":..., \"clue\":...} objects. Tried first for every slot; common dictionary words fill in any slot your list can't cover. Overrides `theme`.","title":"Word List"}},"title":"new_gameArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/check_answer":{"post":{"operationId":"check_answer","summary":"Check a submitted fill against the solution, slot by slot. Returns whether each slot was correct and","description":"Check a submitted fill against the solution, slot by slot. Returns whether each slot was correct and\n    whether the whole puzzle is solved.","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"state":{"additionalProperties":true,"description":"The full puzzle state returned by new_game — pass it back in unchanged. It includes the solution, so don't show it to the player directly; show them the state's `render`ing instead.","title":"State","type":"object"},"fill":{"additionalProperties":{"type":"string"},"description":"Map of slot key (e.g. \"1A\", \"4D\" — see state['slots']) to the player's answer for that slot.","title":"Fill","type":"object"}},"required":["state","fill"],"title":"check_answerArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/get_hint":{"post":{"operationId":"get_hint","summary":"One slot's clue, length, and first letter — never the whole answer.","description":"One slot's clue, length, and first letter — never the whole answer.","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"state":{"additionalProperties":true,"description":"The full puzzle state returned by new_game — pass it back in unchanged. It includes the solution, so don't show it to the player directly; show them the state's `render`ing instead.","title":"State","type":"object"},"key":{"description":"Slot key, e.g. \"1A\" or \"4D\" (see state['slots']).","title":"Key","type":"string"}},"required":["state","key"],"title":"get_hintArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/render":{"post":{"operationId":"render","summary":"A human-readable rendering of the grid (numbered and blank, or solved) plus the across/down clue","description":"A human-readable rendering of the grid (numbered and blank, or solved) plus the across/down clue\n    lists.","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"state":{"additionalProperties":true,"description":"The full puzzle state returned by new_game — pass it back in unchanged. It includes the solution, so don't show it to the player directly; show them the state's `render`ing instead.","title":"State","type":"object"},"reveal_solution":{"default":false,"description":"If true, draws the filled-in solution instead of the blank numbered grid. Only do this if the player asked to see the answer.","title":"Reveal Solution","type":"boolean"}},"required":["state"],"title":"renderArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/list_categories":{"post":{"operationId":"list_categories","summary":"List the theme categories available in the hand-clued word bank, with word counts, for use as","description":"List the theme categories available in the hand-clued word bank, with word counts, for use as\n    `new_game`'s `theme` argument.","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{},"title":"list_categoriesArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}}}}