# API pubblica

> publicApi() — verifica tessere, profilo pubblico di un'associazione, codice fiscale, chiavi pubbliche. Nessuna credenziale.

URL: https://developers.vimine.network/sdk/public/

```js
import { publicApi } from '@vimine/sdk';
const api = publicApi();                       // oppure vimine.public / vimineServer.public
```

Gli endpoint che non richiedono né credenziali né accesso. Usabili da qualsiasi pagina, da uno scanner, da un
server. `publicApi({ apiUrl?, fetch? })` accetta le stesse opzioni di rete delle altre classi.

| Metodo | Endpoint | |
|---|---|---|
| `verifyCard(cardToken)` | `GET /v1/verify/{card_token}` | «questa tessera è attiva adesso?» — solo stato e fine validità |
| `association(slug, { locale }?)` | `GET /v1/aps/{slug}` | profilo pubblico: grafica, tipi di tessera con le quote, statuto in vigore, come ammette i soci, se ne raccoglie l'indirizzo (`member_address`) |
| `validateFiscalCode(input)` | `POST /v1/validate/fiscal-code` | struttura e carattere di controllo; con i dati anagrafici anche la coerenza — e ciò che il codice contiene (`birth_date`, `birth_country`). Per chi è nato all'estero invia `country` |
| `cardKeys()` | `GET /v1/card-keys` | le chiavi pubbliche (JWKS, Ed25519) per verificare i token offline |
| `confirmEnrollment(token, identification?, address?)` | `POST /v1/enroll/confirm` | consuma il token del link «conferma la richiesta» inviato quando un sistema iscrive un account esistente; dopo un `409 identification_required` si ripete con `identification`, dopo un `409 address_required` con `address` |
| `events.list(slug, params?)` · `events.get(slug, event, { locale }?)` | `GET /v1/aps/{slug}/events[/{event}]` | gli eventi **pubblici** di un'associazione, con i posti rimanenti per tipo ([guida](https://developers.vimine.network/guides/events/)) |
| `confirmRegistration(token)` | `POST /v1/registrations/confirm` | consuma il token del link «conferma l'iscrizione» di un ospite: l'iscrizione, con il `token` del QR se confermata |
| `viewRegistration(token)` | `POST /v1/registrations/view` | legge il posto del link personale di un ospite (la mail che conferma il posto): lo stato e, finché è confermato, il `token` del QR; vale fino alla fine dell'evento (dalla 0.3.2) |

```js
const { status, valid_until } = await api.verifyCard('vmt_…');
// { status: 'active', valid_until: '2027-03-31T22:59:59.000Z' } | { status: 'inactive', reason: 'expired' }

const { aps, membership_types, statuto } = await api.association('tuo-slug');

const check = await api.validateFiscalCode({ code: 'RSSMRA80A01H501U', first_name: 'Mario', last_name: 'Rossi', date: '1980-01-01', place: 'Roma', country: 'IT' });
// { valid: true, error: null, mismatches: [], hints: [], birth_date: '1980-01-01', birth_country: 'IT' }
// | { valid: false, error: 'mismatch', mismatches: ['date'], hints: [], birth_date: '1980-01-01', birth_country: 'IT' }

const { keys } = await api.cardKeys();   // [{ kty: 'OKP', crv: 'Ed25519', x, kid, use: 'sig', alg: 'EdDSA' }]

const { status, already, association } = await api.confirmEnrollment(token);   // dal link ricevuto per e-mail
// { status: 'pending', already: false, association: { name, slug } } — 400 invalid_token se scaduto, 409 statuto_outdated

// 409 identification_required: l'account non è identificato; err.errors nomina ciò che manca. Chiedilo e ripeti:
await api.confirmEnrollment(token, { dob: '1985-03-10', birthplace: 'Lyon', birth_country: 'FR' });

// 409 address_required: l'associazione chiede l'indirizzo a tutti i soci. Chiedilo e ripeti (con l'identificazione, se già data):
await api.confirmEnrollment(token, undefined, { line: 'Via Roma 1', postal_code: '20100', city: 'Milano', province: 'MI' });
```

Il codice fiscale è facoltativo: `error` vale `invalid`, `mismatch` o `null`, e `hints` contiene `names_swapped` quando
il codice torna scambiando nome e cognome. I dati di `identification` e l'indirizzo viaggiano nel corpo della
richiesta, mai nel link. Vedi [Soci senza codice fiscale](https://developers.vimine.network/guides/members-without-cf/).

Le chiavi cambiano di rado: mettile in cache e ricaricale una volta al giorno, o quando incontri un `kid`
sconosciuto. Il resto della verifica offline è in [Embed e verifica tessere](https://developers.vimine.network/guides/embed-and-verify/).

Questi endpoint hanno un limite per indirizzo IP (60 richieste al minuto su verifica e codice fiscale): per
volumi maggiori usa un client riservato con `verify:read`.
