> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dentalspace.ai/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Documentazione di dentalspace. Il testo completo, incluso il riferimento API, è in /llms-full.txt. Per endpoint, campi e codici di errore la fonte di verità è openapi.json: non usare endpoint o campi non documentati.

# Autenticazione

> Chiavi API, header, scope per area, sedi, chiavi di prova, creazione, rigenerazione e revoca.

Ogni richiesta porta una chiave API nell'header `Authorization`, con schema `Bearer`. Fanno eccezione `GET /health` e `GET /openapi.json`, che non chiedono la chiave.

```bash theme={null}
curl "https://api.dentalspace.ai/v1/me" \
  -H "Authorization: Bearer $DS_KEY"
```

`GET /me` restituisce la clinica, gli scope, le sedi, la scadenza e i limiti della chiave che chiama.

## Header

| Header | Valore | Obbligatorio |
| - | - | - |
| `Authorization` | `Bearer <chiave>` | Sì, tranne `GET /health` e `GET /openapi.json` |
| `Content-Type` | `application/json` | Sì, sulle richieste con corpo |
| `Idempotency-Key` | Stringa scelta da te, al massimo 255 caratteri | Su alcune creazioni è obbligatoria. Vedi [Idempotenza](/api/idempotenza) |
| `If-Match` | L'`ETag` ricevuto leggendo la risorsa | No. Sulle modifiche: passa solo se nessuno ha cambiato la risorsa |

## Formato della chiave

| Prefisso | Tipo |
| - | - |
| `dsk_live_` | Chiave della clinica |
| `dsk_test_` | Chiave di una clinica di prova. Vedi [Chiavi di prova](#chiavi-di-prova) |

Dopo il prefisso seguono 64 caratteri esadecimali. La chiave è segreta: usala solo da un server, mai nel codice di una pagina web o di un'app.

## Una chiave vede una clinica

La chiave appartiene alla clinica in cui è stata creata e vede solo i suoi dati. Una risorsa di un'altra clinica risponde `404 not_found`, mai `403`: dall'esterno non si capisce nemmeno se esiste.

Una chiave può essere **limitata ad alcune sedi**. In quel caso vede le righe di quelle sedi e quelle senza sede, e scrive solo nelle sue sedi. Una risorsa di un'altra sede risponde `404 not_found`.

## Scope

Ogni endpoint chiede uno o più scope, indicati nella sua pagina come `Scope: <nome>`. Una chiave senza lo scope richiesto riceve `403 insufficient_scope` prima che la richiesta legga qualunque dato; gli scope mancanti sono in `details.requiredScopes`.

Nell'app gli scope si scelgono per area, con tre livelli: **Nessuno**, **Leggi**, **Scrivi**. **Scrivi** comprende **Leggi**.

| Area nell'app | Leggi | Scrivi | Cosa apre |
| - | - | - | - |
| Pazienti | `patients:read` | `patients:write` | Anagrafica e contatti, ricerca per telefono e per nome |
| Dati clinici | `clinical:read` | `clinical:write` | Allergie, farmaci, condizioni, note cliniche. Spenti di default. Vedi [Dati clinici](/api/dati-clinici) |
| Agenda | `appointments:read` | `appointments:write` | Appuntamenti, orari liberi, prenotazioni |
| Studio | `clinic:read` | — | Sedi, poltrone, medici, calendari, listino. Solo lettura |
| Preventivi e piani di cura | `treatment_plans:read` | `treatment_plans:write` | Preventivi e loro voci |
| Fatture e pagamenti | `billing:read` | `billing:write` | Fatture, incassi, piani di pagamento, link di pagamento |
| Documenti | `documents:read` | `documents:write` | Documenti da firmare dei pazienti |
| Attività | `tasks:read` | `tasks:write` | Le cose da fare dello studio |
| Contatti commerciali | `leads:read` | `leads:write` | Persone interessate che non sono ancora pazienti |
| Messaggi WhatsApp | `messages:read` | `messages:write` | Conversazioni, messaggi, stato del bot |
| Telefonate | `calls:read` | `calls:write` | Registro delle telefonate dell'agente vocale |
| Avvisi automatici | `webhooks:read` | `webhooks:write` | Webhook, consegne e storico degli eventi |

Una chiave non può fare più di chi la crea: nell'app si possono dare solo i permessi che si hanno.

### Modelli pronti

Nella finestra di creazione, **Parti da:** riempie i livelli con un modello.

| Modello | Livelli |
| - | - |
| **Agente vocale** | Pazienti, Agenda, Attività e Telefonate in scrittura; Studio in lettura. Niente dati clinici |
| **Gestionale esterno** | Tutte le aree in lettura, tranne i dati clinici |

## Creare una chiave

<Steps>
  <Step title="Apri Chiavi API">
    Nell'app apri **Impostazioni → Chiavi API**. Serve il permesso di gestire le integrazioni e il piano **Clinic**.
  </Step>

  <Step title="Clicca Crea chiave">
    Si apre la finestra **Nuova chiave API**. Dai un nome che dica quale programma la userà, per esempio `Agente vocale`.
  </Step>

  <Step title="Scegli cosa può fare">
    In **Cosa può fare** scegli il livello di ogni area, oppure parti da un modello. Accendi **Solo alcune sedi** per limitarla. **Scadenza** è facoltativa: vuota, la chiave non scade.
  </Step>

  <Step title="Copia la chiave">
    Clicca **Crea chiave**. La chiave compare una volta sola: copiala subito e conservala in un posto sicuro.
  </Step>
</Steps>

<Warning>
  dentalspace conserva solo l'impronta della chiave, non la chiave. Una chiave persa non si recupera: creane un'altra e revoca quella vecchia.
</Warning>

## Rigenerare una chiave

**Rigenera** dà una chiave nuova con gli stessi permessi. Scegli quando la vecchia smette di funzionare: **Subito**, **Fra 24 ore** o **Fra 7 giorni**. Nel frattempo funzionano tutte e due, così aggiorni il programma collegato senza interruzioni. Una chiave già rigenerata non si rigenera di nuovo: si rigenera quella nuova.

## Revocare una chiave

**Revoca** spegne la chiave subito e per sempre. Le richieste successive ricevono `401 api_key_revoked`. Una chiave scaduta risponde `401 api_key_revoked` con `details.reason: "expired"`.

## Chiavi di prova

Una clinica di prova ha chiavi `dsk_test_`. Le richieste funzionano come con una chiave vera, con queste differenze:

* `GET /me` restituisce `livemode: false`;
* nessun messaggio parte verso l'esterno: WhatsApp, email, Sistema TS e fatturazione elettronica non vengono chiamati;
* `POST /payment-links` controlla tutto ma non crea il link: risponde `201` con `url: null`;
* `POST /webhook-endpoints/{id}/test` non spedisce niente.

La clinica di prova la attiva l'assistenza di dentalspace.

## Errori di autenticazione e di permesso

| Status | `code` | Causa |
| - | - | - |
| `401` | `unauthenticated` | Header `Authorization` assente o senza `Bearer` |
| `401` | `api_key_invalid` | Chiave sconosciuta o malformata |
| `401` | `api_key_revoked` | Chiave revocata, sostituita o scaduta (`details.reason: "expired"`) |
| `403` | `plan_required` | La clinica non ha il piano **Clinic** attivo |
| `403` | `insufficient_scope` | La chiave non ha lo scope dell'endpoint |
| `404` | `not_found` | La risorsa non esiste o non è visibile alla chiave |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.