# Permisos, errores y límites

> La tabla de scopes, el formato de los errores (RFC 9457) con códigos estables, los límites de frecuencia.

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

## Permisos (scopes)

Un cliente solicita los permisos al registrarse; el socio los ve en la página de consentimiento.

| Scope | Quién | Qué |
|---|---|---|
| `profile:read` | socio | `GET /v1/me` — nombre, correo, datos de contacto, datos de nacimiento, el código fiscal cuando lo hay, y cómo está identificada la persona (`codicefiscale_check`) |
| `profile:write` | socio | `PATCH /v1/me` — teléfono, sexo, y la identificación: fecha, lugar y país de nacimiento, código fiscal (opcional, se puede añadir más tarde; se vuelve a validar) |
| `membership:read` | socio | `GET /v1/me/membership`, `/events`, `/statuto`, `/card` |
| `membership:request` | socio | `POST /v1/me/membership` — solicitud de inscripción |
| `statuto:accept` | socio | `POST /v1/me/membership/statuto/accept` |
| `network:manage` | socio | el consentimiento del socio a los circuitos (próximamente) |
| `memberships:read` | cliente | `GET /v1/memberships/{id}/status` |
| `verify:read` | cliente | verificación de carnés por encima de la cuota anónima |
| `identity:signup` | cliente | `POST /v1/signup` — crear cuentas en nombre de los socios ([integraciones de servidor](https://developers.vimine.network/es/guides/server/#inscribir-socios-desde-tu-sistema)) |
| `enroll:write` | cliente | `POST /v1/enroll` — enviar solicitudes de inscripción, con o sin código fiscal ([guía](https://developers.vimine.network/es/guides/members-without-cf/)) |
| `events:read` | socio | `GET /v1/events`, `/v1/events/{slug}`, `/eligibility` — incluidos los eventos solo para socios ([guía](https://developers.vimine.network/es/guides/events/)) |
| `registrations:read` | socio, cliente | `GET /v1/me/registrations` (socio); `GET /v1/events/{slug}/registrations` (cliente, sin datos personales) |
| `registrations:write` | socio, cliente | `POST /v1/events/{slug}/registrations` y `DELETE /v1/me/registrations/{id}` (socio); `POST …/registrations/guest` (cliente) |
| `checkins:write` | cliente | `POST /v1/checkins` — check-in en la entrada a partir de un carné o de una inscripción |
| `webhooks:manage` | cliente | próximamente |

Un cliente público o nativo solo puede solicitar permisos de socio; los permisos de «cliente» requieren un cliente
confidencial. Quien todavía no es socio solo puede conceder los permisos de inscripción (`profile:*`,
`membership:read`, `membership:request`, `statuto:accept`).

## Errores

Las respuestas de error son `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` es estable: ramifica tu lógica sobre él. `errors[]` acompaña a `validation_failed` y a
`identification_required` (`{ field, code }`). Una entrada `codicefiscale_mismatch` — un código fiscal que no coincide
con los datos de nacimiento de la persona — lleva además `mismatches`, `hints` y `confirmable`: cuando `confirmable`
es `true`, la persona puede confirmar el código y la solicitud se repite con `codicefiscale_confirmed: true` (consulta
[Socios sin código fiscal](https://developers.vimine.network/es/guides/members-without-cf/#un-código-que-no-coincide-y-la-confirmación)). Los
endpoints OAuth (`/v1/oauth/token`, `/revoke`) responden con el formato OAuth (`{ error, error_description }`).

| `code` | Significado |
|---|---|
| `missing_token`, `invalid_token`, `token_expired` | 401 — vuelve a iniciar sesión (el SDK renueva y repite por sí solo) |
| `insufficient_scope` | 403 — al token le falta ese permiso |
| `api_disabled` | 403 — la asociación no ha activado la API o no acepta solicitudes |
| `plan_limit` | 403 — el plan de la asociación no tiene sitio para un socio más (comprueba `aps.accepting_requests` antes de mostrar el formulario) |
| `not_available` | 403 — la asociación no acepta solicitudes en este momento: todavía no ha aceptado los acuerdos de la plataforma o no ha registrado su estatuto, no está lista, o solo admite a las personas que ha invitado ([la beta privada](#la-beta-privada)); `detail` dice cuál de los casos. En `POST /v1/signup`: durante la beta, las cuentas se crean por invitación |
| `not_found` | 404 — también para recursos de otras asociaciones |
| `validation_failed` | 422 — consulta `errors[]` (`required`, `invalid`, `invalid_codicefiscale`, `codicefiscale_mismatch` con `confirmable`…) |
| `identification_required` | 422 en `POST /v1/me/membership`, 409 en `POST /v1/enroll/confirm` — la persona no está identificada: hace falta un código fiscal, o la fecha, el lugar y el país de nacimiento; `errors[]` indica lo que falta |
| `statuto_outdated`, `statuto_required` | 422 — indica la versión del estatuto en vigor (`detail`) |
| `rate_limited` | 429 — espera `Retry-After` |
| `unavailable` | 503 — vuelve a intentarlo dentro de poco |

OAuth: `invalid_grant` (código o refresh token no válido, caducado o reutilizado), `invalid_client`,
`invalid_scope`, `unauthorized_client` (cliente pendiente de activación), `access_denied` (el socio ha cancelado).

En el SDK todo esto es un [`VimineError`](https://developers.vimine.network/es/sdk/errors/) con el mismo `code`.

## La beta privada

Vimine está en beta privada: las personas y las asociaciones entran **por invitación**. Para un cliente, esto
significa:

- `POST /v1/signup` responde `403 not_available` y no crea nada, salvo que Vimine haya abierto la inscripción pública
  de tu asociación;
- una asociación que solo admite a las personas que ha invitado tiene `aps.invitation_only: true` y
  `aps.accepting_requests: false` en su perfil público ([`association(slug)`](https://developers.vimine.network/es/sdk/public/)); `POST /v1/enroll` y
  `POST /v1/me/membership` responden `403 not_available`. Quien tiene una invitación se une desde el enlace que recibe
  por correo;
- los [sandbox](https://developers.vimine.network/es/guides/sandbox/) siguen abiertos: los clientes de prueba funcionan como siempre.

Comprueba `aps.accepting_requests` antes de mostrar un formulario de inscripción — tanto para la beta como para todo
lo demás; `<vimine-events>` y `<vimine-enroll>` ya lo hacen.

## Límites

- Por dirección IP: 60 peticiones/minuto en los endpoints sensibles (verificación de carnés, código fiscal, token),
  120/minuto en los demás; `RateLimit-*` y `Retry-After` en las respuestas.
- `POST /v1/me/membership` acepta `Idempotency-Key`: la misma clave en un plazo de 24 horas devuelve la misma
  respuesta (el SDK genera una por llamada).
- Las respuestas autenticadas son `Cache-Control: no-store`.
- Cada respuesta lleva un `request_id`: indícalo cuando informes de un problema.
