# Permessi, errori e limiti

> La tabella degli scope, il formato degli errori (RFC 9457) con i codici stabili, i rate limit.

URL: https://developers.vimine.network/guides/scopes-and-errors/

## Permessi (scope)

Un client chiede i permessi al momento della registrazione; il socio li vede sulla pagina di consenso.

| Scope | Chi | Cosa |
|---|---|---|
| `profile:read` | socio | `GET /v1/me` — nome, e-mail, contatti, dati di nascita, codice fiscale se c'è, e come la persona è identificata (`codicefiscale_check`) |
| `profile:write` | socio | `PATCH /v1/me` — telefono, genere, e l'identificazione: data, luogo e Stato di nascita, codice fiscale (facoltativo, si può aggiungere più tardi; rivalidato) |
| `membership:read` | socio | `GET /v1/me/membership`, `/events`, `/statuto`, `/card` |
| `membership:request` | socio | `POST /v1/me/membership` — richiesta di tesseramento |
| `statuto:accept` | socio | `POST /v1/me/membership/statuto/accept` |
| `network:manage` | socio | consenso del socio ai circuiti (prossimamente) |
| `memberships:read` | client | `GET /v1/memberships/{id}/status` |
| `verify:read` | client | verifica tessere oltre la quota anonima |
| `identity:signup` | client | `POST /v1/signup` — creare account per conto dei soci ([integrazioni server](https://developers.vimine.network/guides/server/#registrare-soci-dal-tuo-sistema)) |
| `enroll:write` | client | `POST /v1/enroll` — inviare richieste di tesseramento, con o senza codice fiscale ([guida](https://developers.vimine.network/guides/members-without-cf/)) |
| `events:read` | socio | `GET /v1/events`, `/v1/events/{slug}`, `/eligibility` — anche gli eventi riservati ai soci ([guida](https://developers.vimine.network/guides/events/)) |
| `registrations:read` | socio, client | `GET /v1/me/registrations` (socio); `GET /v1/events/{slug}/registrations` (client, senza dati personali) |
| `registrations:write` | socio, client | `POST /v1/events/{slug}/registrations` e `DELETE /v1/me/registrations/{id}` (socio); `POST …/registrations/guest` (client) |
| `checkins:write` | client | `POST /v1/checkins` — accessi all'ingresso da tessera o iscrizione |
| `webhooks:manage` | client | prossimamente |

Un client pubblico o nativo può chiedere solo permessi del socio; i permessi «client» richiedono un client
riservato. Chi non è ancora socio può concedere solo i permessi di iscrizione (`profile:*`, `membership:read`,
`membership:request`, `statuto:accept`).

## Errori

Le risposte d'errore sono `application/problem+json` (RFC 9457):

```json
{
  "type": "https://developers.vimine.network/errors/insufficient_scope",
  "title": "Forbidden",
  "status": 403,
  "code": "insufficient_scope",
  "detail": "Missing scope: profile:write",
  "request_id": "…"
}
```

`code` è stabile: usa quello. `errors[]` accompagna `validation_failed` e `identification_required`
(`{ field, code }`). Una voce `codicefiscale_mismatch` — un codice fiscale che non concorda con i dati della persona —
porta anche `mismatches`, `hints` e `confirmable`: quando `confirmable` è `true` la persona può confermare il codice e
la richiesta si ripete con `codicefiscale_confirmed: true` (vedi
[Soci senza codice fiscale](https://developers.vimine.network/guides/members-without-cf/#un-codice-che-non-torna-e-la-conferma)). Gli endpoint OAuth
(`/v1/oauth/token`, `/revoke`) rispondono nel formato OAuth (`{ error, error_description }`).

| `code` | Significato |
|---|---|
| `missing_token`, `invalid_token`, `token_expired` | 401 — accedi di nuovo (l'SDK rinnova e ritenta da solo) |
| `insufficient_scope` | 403 — il token non ha quel permesso |
| `api_disabled` | 403 — l'associazione non ha abilitato l'API o non accetta richieste |
| `plan_limit` | 403 — il piano dell'associazione non ammette un altro socio (controlla `aps.accepting_requests` prima di mostrare il modulo) |
| `not_available` | 403 — l'associazione non accoglie richieste adesso: non ha ancora accettato gli accordi della piattaforma o registrato lo statuto, non è pronta, oppure accoglie solo le persone che ha invitato ([la beta privata](#la-beta-privata)); `detail` dice quale. Su `POST /v1/signup`: durante la beta gli account nascono su invito |
| `not_found` | 404 — anche per risorse di altre associazioni |
| `validation_failed` | 422 — vedi `errors[]` (`required`, `invalid`, `invalid_codicefiscale`, `codicefiscale_mismatch` con `confirmable`…) |
| `identification_required` | 422 su `POST /v1/me/membership`, 409 su `POST /v1/enroll/confirm` — la persona non è identificata: serve un codice fiscale oppure data, luogo e Stato di nascita; `errors[]` nomina ciò che manca |
| `statuto_outdated`, `statuto_required` | 422 — indica la versione dello statuto in vigore (`detail`) |
| `rate_limited` | 429 — attendi `Retry-After` |
| `unavailable` | 503 — riprova a breve |

OAuth: `invalid_grant` (codice o refresh token non valido, scaduto o riusato), `invalid_client`,
`invalid_scope`, `unauthorized_client` (client in attesa di attivazione), `access_denied` (il socio ha
annullato).

Nell'SDK tutto questo è un [`VimineError`](https://developers.vimine.network/sdk/errors/) con lo stesso `code`.

## La beta privata

Vimine è in beta privata: persone e associazioni entrano **su invito**. Per un client cambia questo:

- `POST /v1/signup` risponde `403 not_available` e non crea nulla, a meno che Vimine abbia aperto l'iscrizione
  pubblica della tua associazione;
- un'associazione che accoglie solo le persone che ha invitato ha `aps.invitation_only: true` e
  `aps.accepting_requests: false` nel profilo pubblico ([`association(slug)`](https://developers.vimine.network/sdk/public/)); `POST /v1/enroll` e
  `POST /v1/me/membership` rispondono `403 not_available`. Chi ha un invito si iscrive dal link che riceve per posta;
- le [sandbox](https://developers.vimine.network/guides/sandbox/) restano aperte: i client di test lavorano come sempre.

Controlla `aps.accepting_requests` prima di mostrare un modulo di iscrizione — vale per la beta come per il resto;
`<vimine-events>` e `<vimine-enroll>` lo fanno già.

## Limiti

- Per indirizzo IP: 60 richieste/minuto sugli endpoint sensibili (verifica tessere, codice fiscale, token),
  120/minuto sul resto; `RateLimit-*` e `Retry-After` nelle risposte.
- `POST /v1/me/membership` accetta `Idempotency-Key`: la stessa chiave entro 24 ore restituisce la stessa
  risposta (l'SDK ne genera una per chiamata).
- Le risposte autenticate sono `Cache-Control: no-store`.
- Ogni risposta porta un `request_id`: citalo quando segnali un problema.
