{"openapi":"3.1.0","info":{"title":"AutoviaTest Partner API","version":"1.0.0","description":"Read a driving school's prices, instructors, vehicles, free slots, calendar and student progress, and send it lesson requests, cancellations, waiting-list entries and new enquiries. Built for voice assistants and phone systems. Writes never book directly: they land in the school's dashboard for staff to approve."},"servers":[{"url":"https://school.autoviatest.com/api"}],"security":[{"apiKey":[]}],"tags":[{"name":"Setup","description":"Checking a key."},{"name":"School","description":"What the school offers: contact details, prices, instructors, vehicles."},{"name":"Scheduling","description":"Free slots and the booked calendar."},{"name":"Students","description":"Finding a caller and reading their lessons, progress and balance."},{"name":"Requests","description":"Changes the school approves: lesson requests, cancellations, waiting list, new enquiries."}],"paths":{"/v1/me":{"get":{"operationId":"me","summary":"Check your key","description":"Which school and key a request is authenticated as. `mode` is `test` while the school holds sample data and `live` once it runs on real records. Call it once when a partner saves a key.\n\nTypical question: Setup: confirm the key a school pasted in works and belongs to the right school.","tags":["Setup"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"key":{"name":"Voice assistant","preview":"av_live_3f9a","mode":"live"},"school":{"id":"jd7f3kq9m2n8p4r6t1v5w0x3y","name":"Autoescuela Sol","timezone":"Europe/Madrid"}}}}},"400":{"description":"invalid_request: A parameter is missing or malformed. `message` says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized: Missing, wrong or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited: More than 120 requests a minute for this key (bursts of 60 allowed), or too many bad keys from one IP. Wait for the `Retry-After` header's seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal_error: Unexpected failure. Safe to retry reads.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/school":{"get":{"operationId":"school","summary":"School profile","description":"Contact details, time zone, currency and booking rules for the school the key belongs to.\n\nTypical question: \"Where are you?\" · \"How far ahead do I need to book?\" · \"What's your cancellation policy?\"","tags":["School"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"name":"Autoescuela Sol","phone":"+34 910 000 000","email":"hola@autoescuelasol.es","address":"Calle Mayor 12, 28013, Madrid, ES","timezone":"Europe/Madrid","currency":"EUR","defaultLessonDuration":60,"bookingLeadTimeHours":24,"cancellationPolicy":"Free cancellation up to 24 hours before the lesson."}}}},"400":{"description":"invalid_request: A parameter is missing or malformed. `message` says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized: Missing, wrong or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited: More than 120 requests a minute for this key (bursts of 60 allowed), or too many bad keys from one IP. Wait for the `Retry-After` header's seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal_error: Unexpected failure. Safe to retry reads.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/pricing":{"get":{"operationId":"pricing","summary":"Prices","description":"Active lesson packages, cheapest first unless the school set an order. Prices are in major units of `currency`.\n\nTypical question: \"How much are lessons?\" · \"Do you have an intensive course?\"","tags":["School"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"currency":"EUR","packages":[{"id":"k57a1bq3h2m0v8c9x4r6t5y7z","name":"10 lessons","description":"Flexible scheduling, pickup included","lessonCount":10,"pricePerLesson":38,"totalPrice":380,"validityDays":90,"lessonType":null}]}}}},"400":{"description":"invalid_request: A parameter is missing or malformed. `message` says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized: Missing, wrong or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited: More than 120 requests a minute for this key (bursts of 60 allowed), or too many bad keys from one IP. Wait for the `Retry-After` header's seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal_error: Unexpected failure. Safe to retry reads.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/instructors":{"get":{"operationId":"instructors","summary":"Instructors","description":"Active instructors with their regular weekly hours (`dayOfWeek` 0 = Sunday, times in the school's zone). `phone` is the instructor's own number; it is null unless the school turns on \"Share instructor phone numbers\" in its API key settings, or the instructor hasn't added one.\n\nTypical question: \"Who are the teachers?\" · \"Does Marta work on Saturdays?\" · \"Can I have Marta's number?\"","tags":["School"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"instructors":[{"id":"j97c2mf8n1p4q6r3s5t7v9w0x","name":"Marta Ruiz","phone":"+34 611 222 333","specializations":["automatic","nervous drivers"],"bio":null,"averageRating":4.8,"weeklyHours":[{"dayOfWeek":1,"start":"09:00","end":"14:00"},{"dayOfWeek":1,"start":"16:00","end":"20:00"}]}]}}}},"400":{"description":"invalid_request: A parameter is missing or malformed. `message` says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized: Missing, wrong or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited: More than 120 requests a minute for this key (bursts of 60 allowed), or too many bad keys from one IP. Wait for the `Retry-After` header's seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal_error: Unexpected failure. Safe to retry reads.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/vehicles":{"get":{"operationId":"vehicles","summary":"Vehicles","description":"The fleet a student can learn in. Registration, VIN and location are never returned. `inService` is false while a car is in the workshop.\n\nTypical question: \"Do you have automatic cars?\" · \"What car will I drive?\"","tags":["School"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"vehicles":[{"id":"n45b7cd9f1h3k5m7p9r1t3v5x","make":"Seat","model":"Ibiza","year":2023,"transmission":"automatic","fuelType":"petrol","color":"white","inService":true}]}}}},"400":{"description":"invalid_request: A parameter is missing or malformed. `message` says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized: Missing, wrong or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited: More than 120 requests a minute for this key (bursts of 60 allowed), or too many bad keys from one IP. Wait for the `Retry-After` header's seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal_error: Unexpected failure. Safe to retry reads.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/availability":{"get":{"operationId":"availability","summary":"Free slots","description":"Bookable start times per day, after removing existing lessons, approved time off and the school's booking lead time. Slots start every 30 minutes.\n\nTypical question: \"Is there anything Thursday afternoon?\" · \"When's the next free lesson with Marta?\"","tags":["Scheduling"],"parameters":[{"name":"date","in":"query","required":true,"description":"First day, YYYY-MM-DD in the school's time zone.","schema":{"type":"string","format":"date"}},{"name":"days","in":"query","required":false,"description":"Number of days to return, 1–14. Default 1.","schema":{"type":"integer"}},{"name":"duration","in":"query","required":false,"description":"Lesson length in minutes, 30–240. Default 60.","schema":{"type":"integer"}},{"name":"instructorId","in":"query","required":false,"description":"Only this instructor's slots.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"timezone":"Europe/Madrid","duration":60,"days":[{"date":"2026-10-08","slots":[{"start":"2026-10-08T16:00:00+02:00","end":"2026-10-08T17:00:00+02:00","instructorId":"j97c2mf8n1p4q6r3s5t7v9w0x","instructorName":"Marta Ruiz"}]}]}}}},"400":{"description":"invalid_request: A parameter is missing or malformed. `message` says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized: Missing, wrong or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found: `instructorId` is not an active instructor of this school.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited: More than 120 requests a minute for this key (bursts of 60 allowed), or too many bad keys from one IP. Wait for the `Retry-After` header's seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal_error: Unexpected failure. Safe to retry reads.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/calendar":{"get":{"operationId":"calendar","summary":"Lesson calendar","description":"Every lesson booked across the school (or one instructor) for a date range, cancelled lessons left out. Students appear as first name and initial. Returns up to 500 lessons; `truncated` is true when there were more, so ask for fewer days.\n\nTypical question: \"Is Marta teaching this afternoon?\" · A receptionist agent checking who's out on the road.","tags":["Scheduling"],"parameters":[{"name":"date","in":"query","required":true,"description":"First day, YYYY-MM-DD in the school's time zone.","schema":{"type":"string","format":"date"}},{"name":"days","in":"query","required":false,"description":"Number of days, 1–14. Default 1.","schema":{"type":"integer"}},{"name":"instructorId","in":"query","required":false,"description":"Only this instructor's lessons.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"timezone":"Europe/Madrid","lessons":[{"id":"q34f6hj8l0n2p4r6t8v0x2z4d","start":"2026-10-06T10:00:00+02:00","end":"2026-10-06T11:00:00+02:00","status":"scheduled","type":"standard","instructorId":"j97c2mf8n1p4q6r3s5t7v9w0x","instructorName":"Marta Ruiz","student":"Lucía G.","studentId":"m12d4hf6k8n0p2r4t6v8x0z2b","pickupLocation":"Atocha station"}],"truncated":false}}}},"400":{"description":"invalid_request: A parameter is missing or malformed. `message` says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized: Missing, wrong or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found: `instructorId` is not an instructor of this school.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited: More than 120 requests a minute for this key (bursts of 60 allowed), or too many bad keys from one IP. Wait for the `Retry-After` header's seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal_error: Unexpected failure. Safe to retry reads.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/students/lookup":{"get":{"operationId":"lookup","summary":"Find the caller","description":"Students whose own or parent's phone number matches. International and local formats match each other (+34 612 345 678 = 612345678). Returns up to 5.\n\nTypical question: Greet a known caller by name, tell them how many lessons they have left and when the next one is.","tags":["Students"],"parameters":[{"name":"phone","in":"query","required":true,"description":"Caller ID, any format. At least 7 digits.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"students":[{"id":"m12d4hf6k8n0p2r4t6v8x0z2b","firstName":"Lucía","lastName":"García","status":"active","matchedOn":"student_phone","lessonsRemaining":6,"nextLesson":{"id":"q34f6hj8l0n2p4r6t8v0x2z4d","start":"2026-10-06T10:00:00+02:00","duration":60,"instructorName":"Marta Ruiz","pickupLocation":"Atocha station"}}]}}}},"400":{"description":"invalid_request: A parameter is missing or malformed. `message` says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized: Missing, wrong or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited: More than 120 requests a minute for this key (bursts of 60 allowed), or too many bad keys from one IP. Wait for the `Retry-After` header's seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal_error: Unexpected failure. Safe to retry reads.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/students":{"get":{"operationId":"students","summary":"Student directory","description":"All students with their phone numbers, a page at a time. Pass `nextCursor` back as `cursor` until it is null; every page is full except the last. Use it to keep a phone system's contact list in step so staff see who's calling.\n\nTypical question: Nightly sync of caller names into the PBX phonebook.","tags":["Students"],"parameters":[{"name":"limit","in":"query","required":false,"description":"Page size, 1–100. Default 50.","schema":{"type":"integer"}},{"name":"cursor","in":"query","required":false,"description":"`nextCursor` from the previous page.","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"description":"Only active, inactive, completed or suspended students.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"students":[{"id":"m12d4hf6k8n0p2r4t6v8x0z2b","firstName":"Lucía","lastName":"García","phone":"612 345 678","parentPhone":null,"status":"active"}],"nextCursor":"eyJpZCI6Im0xMmQ0aGY2..."}}}},"400":{"description":"invalid_request: A parameter is missing or malformed. `message` says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized: Missing, wrong or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited: More than 120 requests a minute for this key (bursts of 60 allowed), or too many bad keys from one IP. Wait for the `Retry-After` header's seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal_error: Unexpected failure. Safe to retry reads.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/students/{id}":{"get":{"operationId":"student","summary":"Student progress and balance","description":"One student's contact numbers, progress (lessons done, hours, theory and practical test), active packages with lessons left, and any amount still owed. `parentPhone` is set for younger students whose parent handles bookings. `testReadiness` is 0–100 when the school tracks it.\n\nTypical question: \"How many lessons do I have left?\" · \"Have I paid everything?\" · \"Am I ready for the test?\"","tags":["Students"],"parameters":[{"name":"id","in":"path","required":true,"description":"Student id from lookup or the directory.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"id":"m12d4hf6k8n0p2r4t6v8x0z2b","firstName":"Lucía","lastName":"García","phone":"612 345 678","parentPhone":null,"status":"active","preferredInstructor":{"id":"j97c2mf8n1p4q6r3s5t7v9w0x","name":"Marta Ruiz"},"progress":{"completedLessons":14,"drivingHours":14,"theoryTestPassed":true,"practicalTestPassed":false,"testReadiness":72},"lessonsRemaining":6,"packages":[{"name":"20 lessons","lessonsTotal":20,"lessonsRemaining":6,"expiresAt":"2026-12-31T23:00:00.000Z"}],"balance":{"currency":"EUR","amountDue":120,"pendingPayments":1}}}}},"400":{"description":"invalid_request: A parameter is missing or malformed. `message` says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized: Missing, wrong or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found: No such student in this school.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited: More than 120 requests a minute for this key (bursts of 60 allowed), or too many bad keys from one IP. Wait for the `Retry-After` header's seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal_error: Unexpected failure. Safe to retry reads.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/lessons":{"get":{"operationId":"lessons","summary":"A student's upcoming lessons","description":"The next 20 lessons for a student, soonest first.\n\nTypical question: \"When are my lessons this week?\"","tags":["Students"],"parameters":[{"name":"studentId","in":"query","required":true,"description":"From the lookup endpoint.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"lessons":[{"id":"q34f6hj8l0n2p4r6t8v0x2z4d","start":"2026-10-06T10:00:00+02:00","duration":60,"status":"scheduled","type":"standard","instructorName":"Marta Ruiz","pickupLocation":"Atocha station","cancellationRequested":false}]}}}},"400":{"description":"invalid_request: A parameter is missing or malformed. `message` says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized: Missing, wrong or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found: No such student in this school.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited: More than 120 requests a minute for this key (bursts of 60 allowed), or too many bad keys from one IP. Wait for the `Retry-After` header's seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal_error: Unexpected failure. Safe to retry reads.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/lesson-requests":{"post":{"operationId":"lessonRequests","summary":"Request a lesson","description":"Sends a booking request to the school's Lesson Requests inbox for staff to approve. Nothing is booked until they do, so the agent should say \"I've passed your request to the school\", not \"you're booked\". Same rules as the student portal: the student needs lessons left in a package, up to 3 options within the next 90 days, at most 5 requests waiting.\n\nTypical question: \"Can I have Thursday at 4 with Marta?\"","tags":["Requests"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["studentId","preferredTimes"],"properties":{"studentId":{"type":"string","description":"From the lookup endpoint."},"preferredTimes":{"type":"array","items":{"type":"string"},"description":"1–3 start times within 90 days, ISO 8601 with an offset. Use `start` values from /v1/availability. Duplicates are merged."},"instructorId":{"type":"string","description":"Preferred instructor."},"duration":{"type":"integer","description":"Minutes, 30–240. Default 60."},"lessonType":{"type":"string","description":"Free text such as standard, motorway, test_prep, up to 40 characters. Default standard."},"notes":{"type":"string","description":"Anything the caller added. Up to 500 characters."}}},"example":{"studentId":"m12d4hf6k8n0p2r4t6v8x0z2b","preferredTimes":["2026-10-08T16:00:00+02:00","2026-10-09T16:00:00+02:00"],"instructorId":"j97c2mf8n1p4q6r3s5t7v9w0x","duration":60,"notes":"Pickup at Atocha station, please."}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"example":{"lessonRequest":{"id":"s56h8jl0n2p4r6t8v0x2z4b6f","status":"pending"}}}}},"400":{"description":"invalid_request: A parameter is missing or malformed. `message` says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized: Missing, wrong or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"school_not_writable: Write calls only: the school's trial ended or its account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found: Unknown student, or an instructor who isn't active at this school.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"no_lessons_remaining: No lessons left in an active package. Offer one from /v1/pricing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited: More than 120 requests a minute for this key (bursts of 60 allowed), or too many bad keys from one IP. Wait for the `Retry-After` header's seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal_error: Unexpected failure. Safe to retry reads.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"operationId":"listLessonRequests","summary":"A student's lesson requests","description":"The student's 20 most recent requests, newest first: `pending`, `approved`, `scheduled` (with the lesson that was booked), `rejected` (with the reason) or `cancelled`.\n\nTypical question: \"Did the school confirm my Thursday lesson?\"","tags":["Requests"],"parameters":[{"name":"studentId","in":"query","required":true,"description":"From the lookup endpoint.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"lessonRequests":[{"id":"s56h8jl0n2p4r6t8v0x2z4b6f","status":"scheduled","preferredTimes":["2026-10-08T16:00:00+02:00"],"duration":60,"lessonType":"standard","createdAt":"2026-10-01T12:04:00+02:00","rejectionReason":null,"scheduledLesson":{"id":"w90m2pr4t6v8x0z2b4d6f8h0k","start":"2026-10-08T16:00:00+02:00"}}]}}}},"400":{"description":"invalid_request: A parameter is missing or malformed. `message` says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized: Missing, wrong or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found: No such student in this school.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited: More than 120 requests a minute for this key (bursts of 60 allowed), or too many bad keys from one IP. Wait for the `Retry-After` header's seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal_error: Unexpected failure. Safe to retry reads.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/lesson-requests/{id}/cancel":{"post":{"operationId":"cancelLessonRequest","summary":"Withdraw a lesson request","description":"Withdraws a request the school hasn't answered yet. No body.\n\nTypical question: \"Actually, forget Thursday.\"","tags":["Requests"],"parameters":[{"name":"id","in":"path","required":true,"description":"Lesson request id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"lessonRequest":{"id":"s56h8jl0n2p4r6t8v0x2z4b6f","status":"cancelled"}}}}},"400":{"description":"invalid_request: A parameter is missing or malformed. `message` says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized: Missing, wrong or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"school_not_writable: Write calls only: the school's trial ended or its account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found: No such request in this school.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"request_not_pending: The school already answered it. Use /v1/cancellation-requests for a booked lesson.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited: More than 120 requests a minute for this key (bursts of 60 allowed), or too many bad keys from one IP. Wait for the `Retry-After` header's seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal_error: Unexpected failure. Safe to retry reads.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/cancellation-requests":{"post":{"operationId":"cancellationRequests","summary":"Ask to cancel a lesson","description":"Flags an upcoming lesson for cancellation. Staff confirm it in the dashboard, where the school's cancellation policy applies. Safe to retry: a second call returns 200 and keeps the first reason.\n\nTypical question: \"I'm ill, can I cancel tomorrow's lesson?\"","tags":["Requests"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["lessonId"],"properties":{"lessonId":{"type":"string","description":"From /v1/lessons or `nextLesson` in the lookup."},"reason":{"type":"string","description":"Up to 500 characters."}}},"example":{"lessonId":"q34f6hj8l0n2p4r6t8v0x2z4d","reason":"Caller is ill."}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"example":{"cancellationRequest":{"id":"q34f6hj8l0n2p4r6t8v0x2z4d","cancellationRequested":true,"alreadyRequested":false}}}}},"400":{"description":"invalid_request: A parameter is missing or malformed. `message` says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized: Missing, wrong or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"school_not_writable: Write calls only: the school's trial ended or its account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found: No such lesson in this school.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"lesson_not_cancellable: The lesson was cancelled, has started or is in the past.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited: More than 120 requests a minute for this key (bursts of 60 allowed), or too many bad keys from one IP. Wait for the `Retry-After` header's seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal_error: Unexpected failure. Safe to retry reads.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/waiting-list":{"post":{"operationId":"waitingList","summary":"Join the waiting list","description":"Adds a caller to the school's waiting list with their preferred days and times, for when availability comes back empty. Send `studentId` for a known student, or `firstName` and `phone` for a new caller.\n\nTypical question: \"Nothing this week? Put me down for evenings, automatic.\"","tags":["Requests"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":[],"properties":{"studentId":{"type":"string","description":"Known student. Name and phone are taken from their record."},"firstName":{"type":"string","description":"Required without `studentId`."},"phone":{"type":"string","description":"Required without `studentId`. At least 7 digits."},"lastName":{"type":"string","description":"Caller's last name."},"email":{"type":"string","description":"If the caller gave one."},"preferredDays":{"type":"array","items":{"type":"integer"},"description":"Weekdays as numbers, 0 = Sunday … 6 = Saturday."},"preferredTimeSlots":{"type":"array","items":{"type":"string"},"description":"Any of morning, afternoon, evening."},"transmission":{"type":"string","description":"manual or automatic."},"instructorId":{"type":"string","description":"Preferred instructor."},"notes":{"type":"string","description":"Up to 500 characters."}}},"example":{"firstName":"Ana","phone":"+34 600 111 222","preferredDays":[1,3],"preferredTimeSlots":["evening"],"transmission":"automatic"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"example":{"waitingListEntry":{"id":"y12p4rt6v8x0z2b4d6f8h0k2m","status":"waiting","position":4}}}}},"400":{"description":"invalid_request: A parameter is missing or malformed. `message` says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized: Missing, wrong or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"school_not_writable: Write calls only: the school's trial ended or its account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found: Unknown student or instructor.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"already_on_waiting_list: This student or phone number is already waiting or being contacted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited: More than 120 requests a minute for this key (bursts of 60 allowed), or too many bad keys from one IP. Wait for the `Retry-After` header's seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal_error: Unexpected failure. Safe to retry reads.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/leads":{"post":{"operationId":"leads","summary":"Record a new enquiry","description":"Adds a caller who isn't a student yet to the school's Leads pipeline, optionally with a callback time. Safe to retry: if the number already has an open lead, that lead gets the new notes and callback time and the call returns 200 instead of 201.\n\nTypical question: \"I'd like to sign up, can someone call me back tomorrow morning?\"","tags":["Requests"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["firstName","phone"],"properties":{"firstName":{"type":"string","description":"Caller's first name."},"phone":{"type":"string","description":"At least 7 digits."},"lastName":{"type":"string","description":"Caller's last name."},"email":{"type":"string","description":"If the caller gave one. Must look like an email."},"packageIds":{"type":"array","items":{"type":"string"},"description":"Up to 20 package ids from /v1/pricing the caller asked about."},"callbackAt":{"type":"string","format":"date-time","description":"When to call back: a future ISO 8601 time with an offset, within a year."},"notes":{"type":"string","description":"Summary of the call. Up to 1000 characters."},"source":{"type":"string","description":"Shown in the pipeline. Default api; voice_ai is a good choice."}}},"example":{"firstName":"Pablo","phone":"+34 699 000 111","packageIds":["k57a1bq3h2m0v8c9x4r6t5y7z"],"callbackAt":"2026-10-07T10:00:00+02:00","notes":"Wants an intensive course before December. Has no theory test yet.","source":"voice_ai"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"example":{"lead":{"id":"u78k0mn2p4r6t8v0x2z4b6d8h","status":"new","duplicate":false}}}}},"400":{"description":"invalid_request: A parameter is missing or malformed. `message` says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized: Missing, wrong or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"school_not_writable: Write calls only: the school's trial ended or its account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found: A `packageIds` entry isn't a package of this school.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited: More than 120 requests a minute for this key (bursts of 60 allowed), or too many bad keys from one IP. Wait for the `Retry-After` header's seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal_error: Unexpected failure. Safe to retry reads.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"A school's API key from Settings → Integrations → API keys."}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}