L’API aperta
La stessa API di Terapeutbooking — al vostro indirizzo
Un programma di contabilità, un sito o qualsiasi altro sistema che già dialoga con Terapeutbooking/EasyPractice deve cambiare solo indirizzo e chiave. Le rotte, i campi e gli errori sono gli stessi.
Per iniziare
Una chiamata e siete dentro
L’indirizzo è quello della clinica: https://clinica.anotera.clinic/api/v1 — o il vostro dominio, se la clinica gira su quello. La chiave va come Bearer token. JSON in entrata, JSON in uscita, UTF-8, orari in ISO 8601 con il fuso della clinica.
curl https://klinik.anotera.clinic/api/v1/clients?active \ -H "Authorization: Bearer an_…" \ -H "Accept: application/json"
Le liste arrivano paginate come da loro: data, links e meta, con page e page_size (al massimo 100) nella query.
{
"data": [
{ "id": "k-3f9a1c2b7d10", "name": "Anna Berg",
"email": "anna@eksempel.dk", "phone": "+45 20 00 00 00",
"address": "Gammelvej 1", "zip": "2000", "city": "Frederiksberg",
"status": "active", "tags": [],
"created_at": "2026-09-01T10:12:00+02:00" }
],
"links": { "first": "…?page=1", "last": "…?page=1", "prev": null, "next": null },
"meta": { "current_page": 1, "per_page": 15, "total": 1 }
}
C’è spazio per 60 chiamate al minuto per chiave. La risposta porta X-RateLimit-Limit e X-RateLimit-Remaining; oltre il limite si riceve 429 con Retry-After.
L’API qui serve ai programmi che devono dialogare con Anotera. Se a dover passare dal vecchio sistema sono i clienti, gli appuntamenti e le note della clinica, è un’altra pagina: Trasferire i dati da Terapeutbooking.
La chiave
Personale, con esattamente i permessi che le date
La chiave si crea nel banco di lavoro sotto Altro → Integrazioni → L’API aperta. Viene mostrata una volta sola e da noi resta solo un’impronta. Può fare ciò che può il clinico — e solo nelle aree spuntate:
clients-read·clients-readwrite— schede cliente, etichette e inviibookings-read·bookings-readwrite— appuntamenti, orari liberi e prestazionicalendars-read·calendars-readwrite— calendari, orari di apertura e pausejournals-read·journals-readwrite— note cliniche — leggere, o scrivere nuove bozzejournal-files-read— file sulla cartella, sola letturainvoices-read·invoices-readwrite— fatture, segna come pagata, invia, scarica il PDF
Una chiamata fuori dai permessi riceve 403 con il nome del permesso mancante. Una chiave si revoca nella stessa schermata; smette di funzionare subito.
La forma
I campi hanno gli stessi nomi
Un appuntamento si crea come da loro: start, end, client_id, products, facoltativi calendar_id, heading, notes, status e type (client_booking, blocked, other).
POST /api/v1/bookings
{
"start": "2026-10-02T10:00:00+02:00",
"end": "2026-10-02T10:50:00+02:00",
"client_id": "k-3f9a1c2b7d10",
"products": [{ "id": "individuel" }],
"notes": "Første samtale"
}
Un errore in ciò che si invia riceve 422 con il campo e la spiegazione — nella lingua della clinica:
HTTP 422
{
"error": { "message": "The given data was invalid.",
"status_code": 422 },
"data": { "start": ["Tiden ligger uden for åbningstiden"] }
}
Stato di un appuntamento: pending, confirmed, finished, no_show, cancelled. Ciò che non esiste è un 404; ciò che non si può fare (una nota bloccata, un cliente con cartella) è un 409.
Le rotte
Tutte le rotte
La terza colonna è il permesso che la chiave deve avere. Tutti i percorsi stanno sotto /api/v1.
La chiave
- GET
/me—Chi è la chiave, e cosa può fare
Clienti
- GET
/clientsclients-readLa lista. Filtri:active,inactive,has_email,has_phone,email,cpr,tag_id,search,order_by_created|updated|email - POST
/clientsclients-readwriteCrea.nameè obbligatorio;email,phone,address,zip,city,cpr,date_of_birth,notes,tags,ean - GET
/clients/{id}clients-readUna scheda cliente - PUT
/clients/{id}clients-readwriteModifica. Cambiano solo i campi inviati - DELETE
/clients/{id}clients-readwriteElimina — solo un cliente senza cartella; altrimenti 409 - GET
/client-tagsclients-readLe etichette della clinica - GET
/client-vouchersclients-readInvii e percorsi con sedute rimaste - GET
/client-custom-attributesclients-readCampi personalizzati (lista vuota — non ne abbiamo)
Calendario
- GET
/calendarscalendars-readI clinici della clinica come calendari - GET
/calendars/{id}calendars-readUn calendario - GET
/calendars/{id}/opening-timescalendars-readLa settimana:monday_start,monday_end,monday_closed… e la pausa dopo ogni seduta - PUT
/calendars/{id}/opening-timescalendars-readwriteModifica la settimana — solo il proprio calendario - GET
/calendars/{id}/pausescalendars-readChiusure: ferie, corso, un giorno libero - POST
/calendars/{id}/pausescalendars-readwriteNuova chiusura:date,start_time,end_time,reason - DELETE
/calendars/{id}/pauses/{pause}calendars-readwriteRimuovi una chiusura - GET
/servicesbookings-readPrestazioni con durata e prezzo (funziona anche/products)
Appuntamenti
- GET
/bookingsbookings-readAppuntamenti in una finestra:start,end; filtriclient_id,calendar_id,product_id,status - POST
/bookingsbookings-readwriteNuovo appuntamento — vedi la forma sopra - POST
/bookings/bulkbookings-readwritePiù di uno insieme; ognuno riceve la sua risposta - GET
/bookings/{id}bookings-readUn appuntamento, convideo_linkse è una videoseduta - PUT
/bookings/{id}bookings-readwriteSposta (start/end), cambia stato, modifica titolo e note - DELETE
/bookings/{id}bookings-readwriteAnnulla — l’appuntamento resta comecancelled - GET
/online-booking/available-datesbookings-readGiorni con tempo libero:product_id,from,to - GET
/online-booking/available-timesbookings-readOrari liberi in un giorno:product_id,date
Cartella
- GET
/clients/{id}/journalsjournals-readNote del cliente; filtrilocked,draft - POST
/clients/{id}/journalsjournals-readwriteNuova nota:content,date,draft. Senzadraftviene bloccata subito - GET
/clients/{id}/journals/{journal}journals-readUna nota - PUT
/clients/{id}/journals/{journal}journals-readwriteModifica una bozza — o bloccala conlocked: true. Una nota bloccata non si modifica: 409 - DELETE
/clients/{id}/journals/{journal}journals-readwriteElimina una bozza. Una nota bloccata non si elimina: 409 - GET
/clients/{id}/journal-filesjournal-files-readFile sulla cartella - GET
/clients/{id}/journal-files/{file}journal-files-readUn file: nome, tipo, dimensione - GET
/clients/{id}/journal-files/{file}/downloadjournal-files-readIl file stesso
Fatture
- GET
/invoicesinvoices-readFatture; filtriclient_id,paid,unpaid,number,include_credit_notes - GET
/invoices/{id}invoices-readUna fattura con righe e totali - POST
/invoices/{id}/mark-as-paidinvoices-readwriteSegna come pagata:date,payment_type, facoltativoamount(altrimenti il residuo) - POST
/invoices/{id}/sendinvoices-readwriteInvia per email al destinatario:subject,text - GET
/invoices/{id}/pdfinvoices-readLa fattura in PDF
Le differenze
Ciò che è diverso — di proposito
- Gli id sono stringhe, non interi.
k-3f9a1c2b7d10, non4711. Un sistema che presume interi deve usare una stringa. - La cartella è cifrata con la chiave del clinico. Una nota scritta dall’esterno sta nella cartella come ogni altra — e una nota bloccata non si può né modificare né eliminare, chiunque lo chieda. È la norma danese sulla tenuta delle cartelle, non un limite tecnico.
- Non c’è EasyPay.
/easypay/*risponde 404 con una spiegazione. I pagamenti passano dalle fatture. - I calendari non si creano tramite l’API. Un calendario è un clinico, e i clinici entrano dal banco di lavoro.
- Un appuntamento non si elimina — si annulla. Resta come
cancelled, così i numeri e la cartella tornano anche dopo.
Manca una rotta che usate da loro? Scrivete a kontakt@anoteraclinic.com con la chiamata, e la esaminiamo.