Reserve a Doctolib appointment slot for the logged-in user (UNTESTED draft).
UNTESTED until recorded logged in. Selects an exact slot (from doctolib.de/get-slots) in Doctolib's booking funnel for the user's own logged-in account, after an explicit Allow. Returns the practice's notices, which the user must read, and the next booking page to finish in the browser. It does not accept practice notices or confirm the appointment on its own.
- Site
- Doctolib, Germany
- Version
- v1
- Runs, last 7 days
- No reports yet
- sha256
- f26b3e5d5082…
Requests
sent from your browser, in order- 1POST/online_booking/api/slot_selection_funnel/v1/select_slotOBSERVED anonymously only (spikes/doctolib.md). Logged out, Doctolib answers with redirection to /auth/patient_de, which is reported as login_required. Logged in, the response and the following funnel calls are unknown: record them with tools/har2recipe before shipping.
Before it writes, the extension shows you UNTESTED recipe. Reserve the Doctolib slot {{params.start_date}} (visit type {{params.visit_motive_id}}, practice {{params.practice_id}}, {{params.insurance_sector}} insurance) for your logged-in Doctolib account. You finish the booking yourself in Doctolib. and waits for Allow.
Parameters
from your agentReturns
to your agentWhere it can send
- www.doctolib.de
Anything else is blocked by the extension.
Reads from your session
- csrf from meta
Used only in requests to the addresses on the left. Never sent to wield.run or your agent.
Checks
a run passes when- output.status == 'slot_selected_unconfirmed'
Raw recipe
Served as canonical JSON from /api/v1/recipes/doctolib.de/book-slot, so its sha256 matches the ETag and the index.
curl -s https://wield.run/api/v1/recipes/doctolib.de/book-slot | shasum -a 256 # f26b3e5d5082951dd4ce99b9bcf4505d31bf56916883cda4f61808af6720c96a
{ "auth": { "derive": [ { "attr": "content", "from": "meta", "name": "csrf", "selector": "meta[name=\"csrf-token\"]" } ] }, "confirm": { "summary": "UNTESTED recipe. Reserve the Doctolib slot {{params.start_date}} (visit type {{params.visit_motive_id}}, practice {{params.practice_id}}, {{params.insurance_sector}} insurance) for your logged-in Doctolib account. You finish the booking yourself in Doctolib." }, "description": "UNTESTED until recorded logged in. Selects an exact slot (from doctolib.de/get-slots) in Doctolib's booking funnel for the user's own logged-in account, after an explicit Allow. Returns the practice's notices, which the user must read, and the next booking page to finish in the browser. It does not accept practice notices or confirm the appointment on its own.", "effect": "write", "id": "doctolib.de/book-slot", "keywords": [ "doctolib", "termin buchen", "arzttermin buchen", "book appointment", "booking" ], "output": { "schema": { "properties": { "continue_url": { "description": "Doctolib page to finish the booking", "type": [ "string", "null" ] }, "practice_notices": { "description": "Practice notices (HTML) the user must read and accept in Doctolib before the booking is final", "items": { "type": "string" }, "type": "array" }, "status": { "const": "slot_selected_unconfirmed" } }, "type": "object" }, "value": "{practice_notices: steps.select_slot.notices, continue_url: steps.select_slot.redirection && (starts_with(steps.select_slot.redirection, 'http') && steps.select_slot.redirection || join('', ['https://www.doctolib.de', steps.select_slot.redirection])) || `null`, status: 'slot_selected_unconfirmed'}" }, "params": { "additionalProperties": false, "properties": { "agenda_ids": { "items": { "type": "integer" }, "minItems": 1, "type": "array" }, "insurance_sector": { "enum": [ "public", "private" ], "type": "string" }, "practice_id": { "type": "integer" }, "profile_id": { "description": "From search-practitioners", "type": "integer" }, "start_date": { "description": "Exact slot timestamp from get-slots, e.g. 2026-11-09T15:45:00.000+01:00", "pattern": "^\\d{4}-\\d{2}-\\d{2}T", "type": "string" }, "visit_motive_id": { "type": "integer" } }, "required": [ "profile_id", "visit_motive_id", "agenda_ids", "practice_id", "insurance_sector", "start_date" ], "type": "object" }, "provenance": { "method": "browser-inspect", "notes": "UNTESTED. Only select_slot was seen, anonymously, in the UI (spikes/doctolib.md); the anonymous response carried draft_rules (a practice notice to accept) and redirection to /auth/patient_de. CSRF: the UI sends x-csrf-token from meta[name=csrf-token] (Rails). Unknown until Victor records the logged-in flow (tools/har2recipe): the appointment-creation and confirm calls, whether accepting the notice is its own request, patient selection (self or relative), 2FA, and whether select_slot holds the slot. The final confirm step must be added as another write:true step.", "recorded_at": "2026-11-07T12:13:00+01:00", "recorded_by": "C4" }, "requires_login": true, "schema": "https://wield.run/schema/recipe/v1.json", "site": { "country": "DE", "id": "doctolib.de", "language": "de", "login_url": "https://www.doctolib.de/auth/patient_de", "name": "Doctolib", "origin": "https://www.doctolib.de", "origins": [ "https://www.doctolib.de" ] }, "steps": [ { "description": "OBSERVED anonymously only (spikes/doctolib.md). Logged out, Doctolib answers with redirection to /auth/patient_de, which is reported as login_required. Logged in, the response and the following funnel calls are unknown: record them with tools/har2recipe before shipping.", "expect": { "content_type": "json", "login_required_if": { "assert": "contains(body.redirection || '', '/auth/')", "status": [ 401, 403 ] }, "status": [ 200, 201 ] }, "extract": { "json": { "notices": "draft_rules[].body || `[]`", "redirection": "redirection || `null`", "visit_motive_id": "visit_motive_id || `null`" } }, "id": "select_slot", "request": { "body": { "type": "json", "value": { "agenda_ids": "{{params.agenda_ids}}", "insurance_sector": "{{params.insurance_sector}}", "practice_ids": [ "{{params.practice_id}}" ], "profile_id": "{{params.profile_id}}", "source_action": "profile", "start_date": "{{params.start_date}}", "visit_motive_ids": [ "{{params.visit_motive_id}}" ] } }, "headers": { "Accept": "application/json", "Content-Type": "application/json; charset=utf-8", "X-CSRF-Token": "{{vars.csrf}}" }, "method": "POST", "url": "/online_booking/api/slot_selection_funnel/v1/select_slot" }, "write": true } ], "task": "Reserve a Doctolib appointment slot for the logged-in user (UNTESTED draft)", "tos": { "notes": "Booking acts on the user's own Doctolib account and only after an explicit Allow per run. Never auto-accept practice notices; the user reads them. One booking per user request, no retries that could double-book.", "reviewed": false }, "verify": { "checks": [ "output.status == 'slot_selected_unconfirmed'" ], "example_params": { "agenda_ids": [ 2359956 ], "insurance_sector": "public", "practice_id": 723928, "profile_id": 1534568, "start_date": "2026-11-09T15:45:00.000+01:00", "visit_motive_id": 14928354 } }, "version": 1 }