{"openapi":"3.1.0","info":{"title":"Maana workshop sessions API","version":"1.0.0","summary":"Read-only feed of upcoming Maana workshop sessions in Kyoto, with prices, seats left and booking links.","description":"Maana runs small-group traditional craft and tea workshops in Kyoto. This API lists upcoming sessions so AI agents and other integrations can find a date, the price per person in JPY and the seats left.\n\nThe API is free, read-only and needs no authentication: there are no API keys, accounts or sandbox. Nothing sent to it books, holds or pays for a seat.\n\nTo book, give the person the `bookingUrl` of the session they chose. It opens the booking form on maana.jp, where the guest enters their own details and payment and accepts the workshop disclaimer. Never complete payment on their behalf.","contact":{"name":"Maana Atelier","email":"atelier@maana.jp","url":"https://www.maana.jp/developers"}},"externalDocs":{"description":"Developer docs and quickstart","url":"https://www.maana.jp/developers"},"servers":[{"url":"https://www.maana.jp","description":"Production"}],"security":[],"tags":[{"name":"Workshops","description":"Upcoming workshop sessions and booking links."}],"paths":{"/api/workshops/sessions":{"get":{"operationId":"listWorkshopSessions","summary":"List upcoming workshop sessions","description":"Returns upcoming sessions in start order for every bookable workshop, or for one workshop, between two dates in Asia/Tokyo (default: today through 60 days ahead). Each session has its start and end time, price per person in JPY, seats left and a bookingUrl the person opens to book and pay on maana.jp. Sold-out sessions are included with available set to false. Responds with JSON by default and Markdown when the Accept header prefers text/markdown or format=md.","tags":["Workshops"],"security":[],"parameters":[{"name":"workshop","in":"query","required":false,"description":"Only list sessions for this workshop. Omit to list every workshop.","schema":{"$ref":"#/components/schemas/WorkshopSlug"}},{"name":"from","in":"query","required":false,"description":"First date to include, as YYYY-MM-DD in Asia/Tokyo. Defaults to today; a past date starts today.","schema":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"to","in":"query","required":false,"description":"Last date to include, as YYYY-MM-DD in Asia/Tokyo. Defaults to 60 days after from. Must not be before from, and at most 92 days after it.","schema":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"lang","in":"query","required":false,"description":"Language of the booking and workshop page links.","schema":{"type":"string","enum":["en","ja"],"default":"en"}},{"name":"format","in":"query","required":false,"description":"Response format. Overrides the Accept header; md and markdown both return Markdown.","schema":{"type":"string","enum":["json","md","markdown"]}}],"responses":{"200":{"description":"Upcoming sessions in the requested range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkshopSessionsFeed"}},"text/markdown":{"schema":{"type":"string","description":"The same sessions as a Markdown list grouped by workshop, with a booking link for each."}}}},"400":{"description":"A query parameter is invalid. The hint says how to fix it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"The booking calendar did not respond for any requested workshop. Retry shortly.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"schemas":{"WorkshopSlug":{"type":"string","enum":["indigo","tea-dye","earthen-wall","kyoto-botanical-teas","fermentation","tea-ceremony","tea-ceremony-night"],"description":"Identifier of a bookable workshop."},"WorkshopSessionsFeed":{"type":"object","description":"Upcoming workshop sessions in a date range.","required":["generatedAt","timezone","currency","from","to","booking","calendarUrl","sessions","unavailableWorkshops"],"properties":{"generatedAt":{"type":"string","format":"date-time","description":"When this response was generated (UTC)."},"timezone":{"type":"string","const":"Asia/Tokyo","description":"Time zone of from, to and every session time."},"currency":{"type":"string","const":"JPY","description":"Currency of every price."},"from":{"type":"string","format":"date","description":"First date included (Asia/Tokyo)."},"to":{"type":"string","format":"date","description":"Last date included (Asia/Tokyo)."},"booking":{"type":"string","description":"How to book a session, in plain English."},"calendarUrl":{"type":"string","format":"uri","description":"The experiences calendar on maana.jp."},"sessions":{"type":"array","description":"Sessions in start order.","items":{"$ref":"#/components/schemas/WorkshopSession"}},"unavailableWorkshops":{"type":"array","description":"Workshops whose sessions could not be loaded right now. Sessions for every other workshop are complete.","items":{"$ref":"#/components/schemas/WorkshopSlug"}}}},"WorkshopSession":{"type":"object","description":"One scheduled session of a workshop.","required":["id","workshop","start","end","durationMinutes","priceJpy","seatsRemaining","capacity","available","location","addressSentAfterBooking","bookingUrl"],"properties":{"id":{"type":"string","description":"Stable identifier of the session."},"workshop":{"type":"object","description":"The workshop this session belongs to.","required":["slug","name","url"],"properties":{"slug":{"$ref":"#/components/schemas/WorkshopSlug"},"name":{"type":"string","description":"English name of the workshop."},"url":{"type":"string","format":"uri","description":"Workshop page in the requested language."}}},"start":{"type":"string","format":"date-time","description":"Start time with the Asia/Tokyo offset, e.g. 2026-11-08T10:00:00+09:00."},"end":{"type":"string","format":"date-time","description":"End time with the Asia/Tokyo offset."},"durationMinutes":{"type":"integer","minimum":0,"description":"Length of the session in minutes."},"priceJpy":{"type":["integer","null"],"minimum":1,"description":"Price per person in whole JPY, or null when the price is shown only on the booking page."},"seatsRemaining":{"type":"integer","minimum":0,"description":"Seats still available."},"capacity":{"type":"integer","minimum":0,"description":"Total seats in the session."},"available":{"type":"boolean","description":"False when the session is sold out; it can still be viewed."},"location":{"type":"string","description":"Venue name."},"addressSentAfterBooking":{"type":"boolean","description":"True when the exact venue address is emailed after booking instead of being published."},"bookingUrl":{"type":"string","format":"uri","description":"Opens the booking form for this session on maana.jp, where the person enters their details and payment."}}},"Error":{"type":"object","description":"Error returned by every API endpoint.","required":["error","message","hint","docs"],"properties":{"error":{"type":"string","enum":["invalid_workshop","invalid_from","invalid_to","invalid_range","upstream_unavailable","not_found"],"description":"Stable snake_case error code."},"message":{"type":"string","description":"What went wrong."},"hint":{"type":"string","description":"How to fix the request or what to do instead."},"docs":{"type":"string","format":"uri","description":"Developer docs."}}}}}}