nextmotion
nextmotion.
The Nextmotion clinics the API key's user belongs to — start here: every
setup & usage
⚠ your nextmotion api key
log in to the Nextmotion web app, then Settings → API Keys → generate a key and copy it: it is not shown again afterwards. paste it into your oto connector keys under nextmotion.
▸ calendar, catalogue, sales, leads, patients, statistics, stock and aggregates
start with nextmotion_clinic(): every other tool asks for a clinic_id.
nextmotion_practitioner(op="list", clinic_id=…)nextmotion_appointment(op="list", clinic_id=…, date="YYYY-MM-DD")nextmotion_availability(clinic_id=…, start_date=…, end_date=…)nextmotion_availability, then nextmotion_appointment(op="reschedule", appointment_id=…, visit_type_opening_hour_id=<slot id>, time_slot=<slot time_slot>)nextmotion_catalog(kind="visit_type"|"treatment_type"|"treatment_pricing"|…, clinic_id=…)nextmotion_quote(op="list", clinic_id=…), nextmotion_invoice(op="list", clinic_id=…)nextmotion_invoice(op="list", clinic_id=…, invoiced_from="2026-01-01", invoiced_to="2026-01-31")nextmotion_product(op="list", clinic_id=…, expiring_within_days=30) or stock_state="low"|"out"nextmotion_calendar(kind="room"|"device"|"opening_hour"|"absence", clinic_id=…) (show_all=True for the whole clinic, not only the key's user)nextmotion_calendar(kind="appointment_request", clinic_id=…, request_status="new")nextmotion_journey(clinic_id=…, start_date="YYYY-MM-DD", end_date="YYYY-MM-DD")nextmotion_catalog(kind="treatment_package"|"accounting_distribution"|"global_product", clinic_id=…); a package's treatments → op="items", a pricing's or package's per-practitioner distribution → op="distributions"nextmotion_payment(op="list", clinic_id=…) or invoice_id=… for one invoicenextmotion_statistics(kind="appointment_income"|"treatment_types"|"treatment_types_income", clinic_id=…, period_type="month")nextmotion_patient_stats(patient_id=…) with the id served by an appointment, a quote or an invoicenextmotion_lead(op="list", clinic_id=…), and the source or status labels → nextmotion_setting(kind="object_label", clinic_id=…, label_types=["lead_source"])nextmotion_patient_demographics(clinic_id=…, by=["department","age_band"]) — headcounts only; a municipality's socio-demographic profile (population, income) is read in open data: urba_socio(code_insee)nextmotion_device_usage(clinic_id=…, start_date=…, end_date=…, period_type="month") — 93 days at most per callnextmotion_setting(kind="feature"|"payment_medium"|"communication_template"|"document_template"|"survey_form"|"webhook", clinic_id=…)nextmotion_patient(op="get", patient_id=…) with the id served by an appointment, a quote, an invoice; "find Mrs X" → nextmotion_patient(op="list", clinic_id=…, search="X")nextmotion_patient(op="create", clinic_id=…, data={"email": …, "first_name": …, "last_name": …, "gender": …}) or op="update", patient_id=…nextmotion_calendar(kind=…, op="create", clinic_id=…, data={…}); edit / delete → op="update"|"delete", item_id=…nextmotion_appointment(op="update", appointment_id=…, data={"calendar_event": {"start_time": …, "end_time": …}})nextmotion_catalog(kind="treatment_type"|"treatment_package"|…, op="create"|"update", …, data={…}); a package's lines → op="add_item"|"set_items", per-practitioner distribution → op="set_distributions"nextmotion_quote(op="validate", quote_id=…), nextmotion_invoice(op="pay", invoice_id=…, data={"card": "100.00"}), nextmotion_invoice(op="credit_note", clinic_id=…, data={"patient": …, "items": [...]})nextmotion_lead(op="create", clinic_id=…, data={…}), nextmotion_lead(op="convert", lead_id=…)nextmotion_communication(kind="call"|"message", clinic_id=…, data={…})· invoices by period: a complete, bounded walk
invoiced_time falls within the period, bounds includedmax_pages (20 by default, 100 at most); the response gives pages_lues, factures_parcourues and completcomplet: false = partial result: rerun with offset=<offset_suivant> and the same period to read the restlimit is refused and offset is the starting point of the walk· product stock: no link to invoices
nextmotion_product reads the clinic's stock (one batch per line: batch number, expiry, stock levels, unit price, product and brand); a batch can be created, edited (levels, expiry) and deleted· patient base and devices: aggregates, never a row
nextmotion_patient_demographics reads the whole patient list to count: by postal code, department, city, country, gender or age band; no row, no id, no name comes out, and a cell of fewer than 10 patients is masked (only the masked total is returned) — crossing many dimensions masks a lot: start broadnextmotion_device_usage counts, per device, the appointments held, their minutes and those not held, by reading the calendar day by day: it is the booked usage, not the machine's real usage (shots, actual duration), which Nextmotion does not know; no occupancy rate, the API does not give a device's capacity· health data: what is not served
fields=["*"] returns the default view, never the rawdoctor_comments is refused on writedry_run previews included); when the identity is useful, this id is resolved with nextmotion_patient(op="get", patient_id=…). nextmotion_patient_stats returns its financial totals and its visit dates· sales: full lines, statistics, settings
markup), VAT and its sub-pricings (subpricing: nature, price, VAT, accounting code, clinic or practitioner share)nextmotion_invoicetitle, labels, datasets); the API's meta block, undescribed, is not served· writes: a preview first
data, re-reads the targeted object and returns what would go out, without writing anything. pass dry_run=False to actdata, checked against the fields the Nextmotion spec accepts for THIS op: an unknown field is refused, by name, even in nested objects — never ignored; a missing required field toosub_visit_types, a treatment type's pricings, a package's op="set_items", op="set_distributions" — an omitted element is deletednull value is not sent: a field cannot be emptied through this toolnextmotion_communication(kind="message") sends an email, SMS or WhatsApp to the patient, for a quote, an invoice or an administrative document only — never a prescription, a consent or a medical documentsend_appointment_modified_email|sms are true in the spec); the tool sends them as false unless you pass them as true, and the preview says who would be notified (notifie_le_patient)pay and credit_note validate the document by default on the Nextmotion side (do_validate: true); pass do_validate: false to keep a draft⚙ multiple comptes
this connector accepts multiple comptes: each stored credential becomes a named account (one name per compte), at your level, your team's or your org's.
_account="<name>" on the tool; list them: oto_identity(op='list', connector='nextmotion') (scope='org' or scope='group' for the org's or team's)oto_identity(op='set', connector='nextmotion', identity_id='<name>'); rename: op='rename' with new_name_account) and adding upoutils
chargement…
utilisation
claude code — installe le plugin oto —
claude plugin marketplace add otomata-tech/oto-plugin — mcp + skill configurés.cli —
pipx install oto-cli puis oto nextmotion …