{"openapi":"3.1.0","info":{"title":"De Fysioplek API","description":"Free physiotherapy appointment times and the practices behind them, in and around Amsterdam, as De Fysioplek reads them from the practices' own public online agendas (refreshed about every 30 minutes).\n\nPublic and read-only: no key, rate-limited per IP (60 requests per minute). Every answer is JSON in UTF-8; times are ISO 8601 in Europe/Amsterdam with an offset; lists page with an opaque `next_cursor`. Errors always look like `{\"error\": {\"code\": \"…\", \"message\": \"…\"}}`.\n\nNo patient data goes in or out, and no practice phone number, e-mail, website or outside booking link comes out. Booking happens on our own site: follow a practice's `booking_url`. An AI assistant can also search through the MCP server at https://defysioplek.nl/mcp; to book there it uses the tool `book_slot` once that is in the server's tool list (with the patient's confirmation), and until then gives the patient the link. This API never books.\n\nAttribution: keep 'Bron: De Fysioplek' and the page and booking links intact.","version":"1.0.0","x-booking":{"via":"booking_url","mcp_server":"https://defysioplek.nl/mcp","note":"A person books through booking_url (a practice) or a time's link on our own site, defysioplek.nl. An AI assistant can search through the MCP server at /mcp; to book, it uses the tool book_slot once that is in the server's tool list, and until then gives the patient the link. /api/v1 is read-only and never books."}},"servers":[{"url":"https://defysioplek.nl"}],"paths":{"/api/v1/practices":{"get":{"tags":["v1"],"summary":"Every practice listed on De Fysioplek","description":"Every practice listed on De Fysioplek, in slug order, with its public facts: branches, specialisms,\ninsurers, next free time, its page and our booking link. No contact details (ADR-049).","operationId":"practices_api_v1_practices_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Practices per page.","default":100,"title":"Limit"},"description":"Practices per page."},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"description":"The previous page's next_cursor.","title":"Cursor"},"description":"The previous page's next_cursor."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1PracticeList"}}}},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}},"description":"Bad Request"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}},"description":"Not Found"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}},"description":"Too Many Requests"}}}},"/api/v1/practices/{slug}":{"get":{"tags":["v1"],"summary":"One practice","description":"One listed practice: the listing's facts plus its therapists and the therapies it offers.","operationId":"practice_api_v1_practices__slug__get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":60,"pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$","description":"The practice's slug, as in /praktijk/{slug}.","title":"Slug"},"description":"The practice's slug, as in /praktijk/{slug}."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1PracticeDetail"}}}},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}},"description":"Bad Request"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}},"description":"Not Found"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}},"description":"Too Many Requests"}}}},"/api/v1/areas":{"get":{"tags":["v1"],"summary":"Our service areas","description":"Every public service area (Amsterdam districts and nearby towns) with its districts and practice counts.\nUse an area's id as ``?area=`` on /api/v1/slots.","operationId":"areas_api_v1_areas_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1AreaList"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"description":"Too Many Requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}}}}},"/api/v1/categories":{"get":{"tags":["v1"],"summary":"Complaint categories","description":"Every complaint category with its slug (use as ``?category=`` on /api/v1/slots). Names follow\n``Accept-Language`` (``nl`` default, ``en``); slugs never change with the language.","operationId":"categories_api_v1_categories_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1CategoryList"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"description":"Too Many Requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}}}}},"/api/v1/slots":{"get":{"tags":["v1"],"summary":"Free times","description":"Free times, soonest first, each with ``handoff_url``: the link that opens exactly that time in our booking\ndialog. The same times the site shows (the next 14 days; a practice's next 60), not every time an agenda\nholds. Times are suggestions until the practice confirms. A person books through ``handoff_url``; an assistant\nuses the MCP tool ``book_slot`` once it is in the server's tool list, until then the link.","operationId":"slots_api_v1_slots_get","parameters":[{"name":"area","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":60,"pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$"},{"type":"null"}],"description":"A service area id from /api/v1/areas.","title":"Area"},"description":"A service area id from /api/v1/areas."},{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":60,"pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$"},{"type":"null"}],"description":"A category slug from /api/v1/categories.","title":"Category"},"description":"A category slug from /api/v1/categories."},{"name":"practice","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":60,"pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$"},{"type":"null"}],"description":"A practice slug from /api/v1/practices (searches its next 60 days).","title":"Practice"},"description":"A practice slug from /api/v1/practices (searches its next 60 days)."},{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"First day (YYYY-MM-DD), Europe/Amsterdam.","title":"From"},"description":"First day (YYYY-MM-DD), Europe/Amsterdam."},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Last day (YYYY-MM-DD), Europe/Amsterdam.","title":"To"},"description":"Last day (YYYY-MM-DD), Europe/Amsterdam."},{"name":"daypart","in":"query","required":false,"schema":{"anyOf":[{"enum":["morning","afternoon","evening","weekend"],"type":"string"},{"type":"null"}],"title":"Daypart"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":20,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"description":"The previous page's next_cursor.","title":"Cursor"},"description":"The previous page's next_cursor."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1SlotList"}}}},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}},"description":"Bad Request"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}},"description":"Not Found"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}},"description":"Too Many Requests"}}}},"/api/v1/meta":{"get":{"tags":["v1"],"summary":"Freshness, coverage and how to book","description":"When the index was last refreshed, how many practices it lists, and where bookings go.","operationId":"meta_api_v1_meta_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Meta"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"description":"Too Many Requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}}}}}},"components":{"schemas":{"V1Area":{"properties":{"id":{"type":"string","title":"Id","description":"Stable id, e.g. amsterdam-oost; pass as ?area= to /api/v1/slots."},"name":{"type":"string","title":"Name"},"city":{"type":"string","title":"City"},"districts":{"items":{"type":"string"},"type":"array","title":"Districts","description":"The map districts the area covers."},"practices":{"type":"integer","title":"Practices"},"practices_with_free_times":{"type":"integer","title":"Practices With Free Times"}},"type":"object","required":["id","name","city","districts","practices","practices_with_free_times"],"title":"V1Area","description":"A public service area (a city district or a town) and the listed practices in it."},"V1AreaList":{"properties":{"areas":{"items":{"$ref":"#/components/schemas/V1Area"},"type":"array","title":"Areas"}},"type":"object","required":["areas"],"title":"V1AreaList","description":"Every public service area."},"V1Booking":{"properties":{"via":{"type":"string","const":"booking_url","title":"Via","description":"The field that leads to our own booking flow."},"mcp_server":{"type":"string","title":"Mcp Server","description":"The MCP server: search tools now, the booking tool book_slot once listed."},"note":{"type":"string","title":"Note"}},"type":"object","required":["via","mcp_server","note"],"title":"V1Booking","description":"How booking works: through our own flow today; the MCP tool book_slot once it is live. Never this API."},"V1Branch":{"properties":{"street":{"type":"string","title":"Street","description":"Street and house number of the practice building ('' when unknown)."},"postcode4":{"type":"string","title":"Postcode4","description":"The 4 digits of the building's postcode ('' when unknown)."},"city":{"type":"string","title":"City"},"district":{"type":"string","title":"District","description":"The district or town the building is in, as the site names it ('' when unknown)."},"lat":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Lat"},"lng":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Lng"}},"type":"object","required":["street","postcode4","city","district"],"title":"V1Branch","description":"One building of a practice: where it is, without a 6-character postcode."},"V1Category":{"properties":{"slug":{"type":"string","title":"Slug","description":"Stable id, e.g. knie-been; pass as ?category= to /api/v1/slots."},"name":{"type":"string","title":"Name"},"practices_with_free_times":{"type":"integer","title":"Practices With Free Times"}},"type":"object","required":["slug","name","practices_with_free_times"],"title":"V1Category","description":"A complaint category; the name follows Accept-Language (nl or en), the slug never changes."},"V1CategoryList":{"properties":{"categories":{"items":{"$ref":"#/components/schemas/V1Category"},"type":"array","title":"Categories"}},"type":"object","required":["categories"],"title":"V1CategoryList","description":"Every complaint category."},"V1Error":{"properties":{"error":{"$ref":"#/components/schemas/V1ErrorBody"}},"type":"object","required":["error"],"title":"V1Error","description":"Every ``/api/v1`` error, whatever the status (400, 404, 422, 429)."},"V1ErrorBody":{"properties":{"code":{"type":"string","title":"Code"},"message":{"type":"string","title":"Message"}},"type":"object","required":["code","message"],"title":"V1ErrorBody","description":"What went wrong: a fixed machine code and a short message without any input echoed."},"V1Insurance":{"properties":{"status":{"type":"string","enum":["all","some","none"],"title":"Status","description":"all: every insurer; some: the listed ones; none: no contracts."},"insurers":{"items":{"type":"string"},"type":"array","title":"Insurers","description":"Named insurers when status is some."},"except_insurers":{"items":{"type":"string"},"type":"array","title":"Except Insurers","description":"Insurers excluded when status is all."},"checked_at":{"type":"string","title":"Checked At","description":"When the site last read it ('' for the practice's own answer).","default":""}},"type":"object","required":["status"],"title":"V1Insurance","description":"Which health insurers the practice has contracts with, as the practice page shows it (ADR-050)."},"V1Meta":{"properties":{"api_version":{"type":"string","title":"Api Version"},"data_refreshed_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Data Refreshed At","description":"Last successful refresh of the whole index, ISO 8601 with offset."},"practices":{"type":"integer","title":"Practices","description":"Practices listed on De Fysioplek."},"practices_with_free_times":{"type":"integer","title":"Practices With Free Times"},"coverage":{"type":"string","title":"Coverage"},"booking":{"$ref":"#/components/schemas/V1Booking"},"terms":{"type":"string","title":"Terms"}},"type":"object","required":["api_version","data_refreshed_at","practices","practices_with_free_times","coverage","booking","terms"],"title":"V1Meta","description":"Data freshness, coverage and how to book."},"V1NextFree":{"properties":{"start":{"type":"string","title":"Start","description":"ISO 8601, Europe/Amsterdam with offset."}},"type":"object","required":["start"],"title":"V1NextFree","description":"The practice's next free time on the site (within the board's 14 days)."},"V1Practice":{"properties":{"slug":{"type":"string","title":"Slug","description":"Stable id; the same as in https://defysioplek.nl/praktijk/{slug}."},"name":{"type":"string","title":"Name"},"branches":{"items":{"$ref":"#/components/schemas/V1Branch"},"type":"array","title":"Branches"},"specialisms":{"items":{"type":"string"},"type":"array","title":"Specialisms","description":"Complaint categories with a current free time at this practice."},"insurance":{"anyOf":[{"$ref":"#/components/schemas/V1Insurance"},{"type":"null"}],"description":"Absent knowledge is null, never a guess."},"next_free":{"anyOf":[{"$ref":"#/components/schemas/V1NextFree"},{"type":"null"}],"description":"Null when the practice has no free time in the next 14 days."},"page_url":{"type":"string","title":"Page Url","description":"The practice's page on defysioplek.nl."},"booking_url":{"type":"string","title":"Booking Url","description":"Our own booking flow on this practice's times; a person books there."}},"type":"object","required":["slug","name","branches","specialisms","page_url","booking_url"],"title":"V1Practice","description":"A practice listed on De Fysioplek, with its public facts."},"V1PracticeDetail":{"properties":{"slug":{"type":"string","title":"Slug","description":"Stable id; the same as in https://defysioplek.nl/praktijk/{slug}."},"name":{"type":"string","title":"Name"},"branches":{"items":{"$ref":"#/components/schemas/V1Branch"},"type":"array","title":"Branches"},"specialisms":{"items":{"type":"string"},"type":"array","title":"Specialisms","description":"Complaint categories with a current free time at this practice."},"insurance":{"anyOf":[{"$ref":"#/components/schemas/V1Insurance"},{"type":"null"}],"description":"Absent knowledge is null, never a guess."},"next_free":{"anyOf":[{"$ref":"#/components/schemas/V1NextFree"},{"type":"null"}],"description":"Null when the practice has no free time in the next 14 days."},"page_url":{"type":"string","title":"Page Url","description":"The practice's page on defysioplek.nl."},"booking_url":{"type":"string","title":"Booking Url","description":"Our own booking flow on this practice's times; a person books there."},"therapists":{"items":{"type":"string"},"type":"array","title":"Therapists","description":"Names of the practice's therapists as its agenda and team page publish them."},"therapies":{"items":{"type":"string"},"type":"array","title":"Therapies","description":"Catalogue therapies the practice offers (e.g. Manuele therapie)."}},"type":"object","required":["slug","name","branches","specialisms","page_url","booking_url","therapists","therapies"],"title":"V1PracticeDetail","description":"One practice: the listing's facts plus its therapists and therapies."},"V1PracticeList":{"properties":{"practices":{"items":{"$ref":"#/components/schemas/V1Practice"},"type":"array","title":"Practices"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor","description":"Pass as ?cursor= for the next page; null on the last page."}},"type":"object","required":["practices","next_cursor"],"title":"V1PracticeList","description":"A page of practices, in slug order."},"V1Slot":{"properties":{"id":{"type":"string","title":"Id","description":"Opaque, stable while the harvest keeps this time."},"start":{"type":"string","title":"Start","description":"ISO 8601, Europe/Amsterdam with offset."},"duration_min":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Duration Min","description":"Only when the agenda or the practice says so; absent otherwise."},"practice":{"$ref":"#/components/schemas/V1SlotPractice"},"branch":{"$ref":"#/components/schemas/V1SlotBranch"},"therapist":{"type":"string","title":"Therapist"},"appointment_type":{"type":"string","title":"Appointment Type","description":"The type exactly as the practice's agenda names it."},"handoff_url":{"type":"string","title":"Handoff Url","description":"Opens our booking dialog on exactly this time; a person books there. It carries the building's public address in full, so the site can match the time exactly. An assistant uses the MCP tool book_slot on /mcp once it is in the server's tool list, until then this link."}},"type":"object","required":["id","start","practice","branch","therapist","appointment_type","handoff_url"],"title":"V1Slot","description":"One free time as the site shows it, with the link that opens exactly this time on our site."},"V1SlotBranch":{"properties":{"street":{"type":"string","title":"Street"},"postcode4":{"type":"string","title":"Postcode4"},"district":{"type":"string","title":"District"}},"type":"object","required":["street","postcode4","district"],"title":"V1SlotBranch","description":"The building the time is in, without a 6-character postcode."},"V1SlotList":{"properties":{"slots":{"items":{"$ref":"#/components/schemas/V1Slot"},"type":"array","title":"Slots"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor","description":"Pass as ?cursor= for the next page; null on the last page."}},"type":"object","required":["slots","next_cursor"],"title":"V1SlotList","description":"A page of free times, soonest first."},"V1SlotPractice":{"properties":{"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"},"area":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Area","description":"The service area id, or null outside our areas."}},"type":"object","required":["slug","name","area"],"title":"V1SlotPractice","description":"The practice a free time belongs to."}}},"externalDocs":{"description":"Developer docs: the API and the MCP server, with examples","url":"https://defysioplek.nl/docs"}}