# Public API

> publicApi() — card verification, an association's public profile, fiscal code, public keys. No credentials.

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

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

The endpoints that need neither credentials nor a sign-in. Usable from any page, from a scanner, from a
server. `publicApi({ apiUrl?, fetch? })` takes the same network options as the other classes.

| Method | Endpoint | |
|---|---|---|
| `verifyCard(cardToken)` | `GET /v1/verify/{card_token}` | "is this card active right now?" — status and validity end only |
| `association(slug, { locale }?)` | `GET /v1/aps/{slug}` | public profile: branding, membership types with fees, in-force statuto, how it admits members, whether it collects their address (`member_address`) |
| `validateFiscalCode(input)` | `POST /v1/validate/fiscal-code` | structure and check character; with personal data, their consistency too — and what the code holds (`birth_date`, `birth_country`). For a person born abroad send `country` |
| `cardKeys()` | `GET /v1/card-keys` | the public keys (JWKS, Ed25519) that verify tokens offline |
| `confirmEnrollment(token, identification?, address?)` | `POST /v1/enroll/confirm` | consumes the token of the "confirm your request" link sent when a system enrols an existing account; after a `409 identification_required` it is repeated with `identification`, after a `409 address_required` with `address` |
| `events.list(slug, params?)` · `events.get(slug, event, { locale }?)` | `GET /v1/aps/{slug}/events[/{event}]` | an association's **public** events, with the places left per type ([guide](https://developers.vimine.network/en/guides/events/)) |
| `confirmRegistration(token)` | `POST /v1/registrations/confirm` | consumes the token of a guest's "confirm your registration" link: the registration, with the QR `token` when confirmed |
| `viewRegistration(token)` | `POST /v1/registrations/view` | reads the place behind a guest's own link (the mail that confirms the place): its status and, while it is confirmed, the QR `token`; it works until the event is over (since 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('your-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);   // from the link received by e-mail
// { status: 'pending', already: false, association: { name, slug } } — 400 invalid_token when expired, 409 statuto_outdated

// 409 identification_required: the account is not identified; err.errors names what is missing. Ask for it and repeat:
await api.confirmEnrollment(token, { dob: '1985-03-10', birthplace: 'Lyon', birth_country: 'FR' });

// 409 address_required: the association asks every member for an address. Ask for it and repeat (with the identification, if already given):
await api.confirmEnrollment(token, undefined, { line: 'Via Roma 1', postal_code: '20100', city: 'Milano', province: 'MI' });
```

The fiscal code is optional: `error` is `invalid`, `mismatch` or `null`, and `hints` holds `names_swapped` when the
code matches once surname and given name are exchanged. The particulars of `identification` and the address travel in
the request body, never in the link. See [Members without a fiscal code](https://developers.vimine.network/en/guides/members-without-cf/).

Keys change rarely: cache them and reload once a day, or when you meet an unknown `kid`. The rest of offline
verification is in [Embed and card verification](https://developers.vimine.network/en/guides/embed-and-verify/).

These endpoints have a per-IP limit (60 requests per minute on verification and fiscal code): for higher
volumes use a confidential client with `verify:read`.
