{"openapi":"3.1.0","info":{"title":"JASOTO public catalog and business directory","version":"1.2.0","description":"Free read-only access to JASOTO's curated public offering descriptions. No account, API key or payment is required. The directory endpoints return approved public business listing fields only. Private customer and account records are unavailable. Directory results are paginated with at most 25 items per page. At most 20 curated offerings are returned; no pagination is needed. Cache successful results for at least 60 seconds and retry HTTP 429 only after Retry-After. The optional API-Version header selects major version 1; omission remains version 1. Unsupported values return HTTP 400. Breaking changes require a new opt-in major version. Retirement is announced at least 90 days ahead with Deprecation, Sunset and a deprecation-policy Link; version 1 has no scheduled retirement.","contact":{"name":"JASOTO support","email":"hello@jasoto.co.uk","url":"https://www.jasoto.co.uk/contact"}},"servers":[{"url":"https://www.jasoto.co.uk"}],"security":[],"externalDocs":{"description":"API and MCP usage guide","url":"https://www.jasoto.co.uk/developers"},"paths":{"/api/directory":{"get":{"operationId":"searchJasotoBusinesses","summary":"Search approved public businesses","description":"Search approved public listings by service or name and location. All q terms must match. Stable alphabetical order; at most 25 results per page. nextOffset is null when no further page is available within the 1000-offset browsing limit. No matches returns an empty items array, not an error. Private records, paid generation and account operations are unavailable.","parameters":[{"name":"API-Version","in":"header","required":false,"description":"Select public REST API version 1. Omitting this header selects version 1 and will not automatically advance to a future version. Unsupported values return HTTP 400.","schema":{"type":"string","enum":["1"],"default":"1"},"example":"1"},{"name":"q","in":"query","description":"Up to six plain search terms. Letters, digits, spaces, apostrophes, periods, ampersands and hyphens are accepted.","schema":{"type":"string","maxLength":120},"example":"plumber"},{"name":"location","in":"query","description":"City, region or postal-code substring using plain text.","schema":{"type":"string","maxLength":80},"example":"London"},{"name":"country","in":"query","description":"Two-letter country code, case-insensitive.","schema":{"type":"string","pattern":"^[A-Za-z]{2}$"},"example":"GB"},{"name":"limit","in":"query","description":"Maximum number of businesses returned.","schema":{"type":"integer","minimum":1,"maximum":25,"default":10}},{"name":"offset","in":"query","description":"Pagination offset; use nextOffset from the previous response.","schema":{"type":"integer","minimum":0,"maximum":1000,"default":0}}],"responses":{"200":{"description":"Matching businesses and pagination","headers":{"API-Version":{"description":"The public REST API major version used for this response.","schema":{"type":"string","const":"1"}}},"content":{"application/json":{"schema":{"type":"object","required":["items","limit","offset","nextOffset"],"properties":{"items":{"type":"array","maxItems":25,"items":{"$ref":"#/components/schemas/PublicBusiness"}},"limit":{"type":"integer","minimum":1,"maximum":25},"offset":{"type":"integer","minimum":0,"maximum":1000},"nextOffset":{"type":["integer","null"],"minimum":0,"maximum":1000}}}}}},"400":{"description":"Structured error with code, message and resolution hint, including unsupported API versions.","headers":{"API-Version":{"description":"The public REST API major version used for this response.","schema":{"type":"string","const":"1"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Structured error with code, message and resolution hint, including unsupported API versions.","headers":{"API-Version":{"description":"The public REST API major version used for this response.","schema":{"type":"string","const":"1"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Structured error with code, message and resolution hint, including unsupported API versions.","headers":{"API-Version":{"description":"The public REST API major version used for this response.","schema":{"type":"string","const":"1"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","example":30}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/directory/{identifier}":{"get":{"operationId":"getJasotoBusiness","summary":"Read an approved public business","description":"Read a public business by slug or UUID returned by searchJasotoBusinesses. quoteUrl links to the existing website enquiry flow; it does not submit an enquiry, charge money or book work.","parameters":[{"name":"API-Version","in":"header","required":false,"description":"Select public REST API version 1. Omitting this header selects version 1 and will not automatically advance to a future version. Unsupported values return HTTP 400.","schema":{"type":"string","enum":["1"],"default":"1"},"example":"1"},{"name":"identifier","in":"path","required":true,"description":"Public business slug or UUID.","schema":{"type":"string","maxLength":200,"pattern":"^[A-Za-z0-9][A-Za-z0-9-]*$"}}],"responses":{"200":{"description":"Public business profile","headers":{"API-Version":{"description":"The public REST API major version used for this response.","schema":{"type":"string","const":"1"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBusiness"}}}},"400":{"description":"Structured error with code, message and resolution hint, including unsupported API versions.","headers":{"API-Version":{"description":"The public REST API major version used for this response.","schema":{"type":"string","const":"1"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Structured error with code, message and resolution hint, including unsupported API versions.","headers":{"API-Version":{"description":"The public REST API major version used for this response.","schema":{"type":"string","const":"1"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Structured error with code, message and resolution hint, including unsupported API versions.","headers":{"API-Version":{"description":"The public REST API major version used for this response.","schema":{"type":"string","const":"1"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Structured error with code, message and resolution hint, including unsupported API versions.","headers":{"API-Version":{"description":"The public REST API major version used for this response.","schema":{"type":"string","const":"1"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/offerings":{"get":{"operationId":"listJasotoOfferings","summary":"List or search public offerings","description":"Read every curated public offering, or search name, description, audience and features. All whitespace-separated query terms must match. An unmatched query returns an empty list with HTTP 200.","parameters":[{"name":"API-Version","in":"header","required":false,"description":"Select public REST API version 1. Omitting this header selects version 1 and will not automatically advance to a future version. Unsupported values return HTTP 400.","schema":{"type":"string","enum":["1"],"default":"1"},"example":"1"},{"name":"q","in":"query","required":false,"description":"Optional search terms; at most 200 characters.","schema":{"type":"string","maxLength":200},"example":"language"}],"responses":{"200":{"description":"Matching public offerings","headers":{"API-Version":{"description":"The public REST API major version used for this response.","schema":{"type":"string","const":"1"}}},"content":{"application/json":{"schema":{"type":"object","required":["items","total"],"properties":{"items":{"type":"array","maxItems":20,"items":{"$ref":"#/components/schemas/Offering"}},"total":{"type":"integer","minimum":0,"maximum":20}}}}}},"400":{"description":"Invalid query parameters or unsupported API version","headers":{"API-Version":{"description":"The public REST API major version used for this response.","schema":{"type":"string","const":"1"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Unsupported method; use GET or HEAD","headers":{"API-Version":{"description":"The public REST API major version used for this response.","schema":{"type":"string","const":"1"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/offerings/{slug}":{"get":{"operationId":"getJasotoOffering","summary":"Read one public offering","description":"Read the full curated description, access conditions, features, steps, FAQ and canonical guide links for a slug returned by the catalog.","parameters":[{"name":"API-Version","in":"header","required":false,"description":"Select public REST API version 1. Omitting this header selects version 1 and will not automatically advance to a future version. Unsupported values return HTTP 400.","schema":{"type":"string","enum":["1"],"default":"1"},"example":"1"},{"name":"slug","in":"path","required":true,"description":"An exact offering slug returned by GET /api/offerings.","schema":{"type":"string"},"example":"free-business-listing"}],"responses":{"200":{"description":"The public offering","headers":{"API-Version":{"description":"The public REST API major version used for this response.","schema":{"type":"string","const":"1"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Offering"}}}},"400":{"description":"Unsupported API version","headers":{"API-Version":{"description":"The public REST API major version used for this response.","schema":{"type":"string","const":"1"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No offering matches this slug","headers":{"API-Version":{"description":"The public REST API major version used for this response.","schema":{"type":"string","const":"1"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Unsupported method; use GET or HEAD","headers":{"API-Version":{"description":"The public REST API major version used for this response.","schema":{"type":"string","const":"1"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"schemas":{"Offering":{"type":"object","additionalProperties":false,"required":["slug","name","description","audience","href","action","access","features","steps","questions","url","guideUrl","markdownUrl"],"properties":{"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"audience":{"type":"string"},"href":{"type":"string"},"action":{"type":"string"},"access":{"type":"string"},"url":{"type":"string","format":"uri"},"guideUrl":{"type":"string","format":"uri"},"markdownUrl":{"type":"string","format":"uri"},"features":{"type":"array","items":{"type":"object","required":["title","text"],"properties":{"title":{"type":"string"},"text":{"type":"string"},"link":{"type":"object","required":["href","label"],"properties":{"href":{"type":"string"},"label":{"type":"string"}}}}}},"steps":{"type":"array","items":{"type":"string"}},"questions":{"type":"array","items":{"type":"object","required":["question","answer"],"properties":{"question":{"type":"string"},"answer":{"type":"string"}}}}}},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message","resolution"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"resolution":{"type":"string"}}}}},"PublicBusiness":{"type":"object","additionalProperties":false,"required":["id","slug","name","service","category","description","location","profileUrl","markdownUrl","quoteUrl"],"properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"service":{"type":"string"},"category":{"type":"string"},"description":{"type":"string","maxLength":3000},"location":{"type":"object","additionalProperties":false,"required":["city","region","postalCode","country"],"properties":{"city":{"type":"string"},"region":{"type":"string"},"postalCode":{"type":"string"},"country":{"type":"string"}}},"profileUrl":{"type":"string","format":"uri"},"markdownUrl":{"type":"string","format":"uri"},"quoteUrl":{"type":"string","format":"uri"}}}}}}