# Événements et inscriptions

> Publiez les événements de l’association sur votre site, laissez les membres s’inscrire (et les invités, pour les événements publics), contrôlez les entrées avec le même scanner que pour les cartes.

URL: https://developers.vimine.network/fr/guides/events/

Les événements qu’une association publie depuis sa console sont sur l’API selon le même principe que les cartes :
**un contenu headless** (titre, résumé, description en markdown, images, lieu, dates, liens) et la **disponibilité en
temps réel** par type d’inscription — jamais *qui* est inscrit. Le vocabulaire est celui du tiers secteur italien : une
**inscription** (*iscrizione*) et, quand il y a un montant, une **contribution** (*contributo*).

:::note[Avant de commencer]
Votre client a besoin des autorisations `events:read`, `registrations:read` et `registrations:write` (voir
[Autorisations, erreurs et limites](https://developers.vimine.network/fr/guides/scopes-and-errors/)). Pour faire des essais sans toucher aux données
réelles, utilisez la [sandbox](https://developers.vimine.network/fr/guides/sandbox/) : l’association jumelle peut publier des événements comme la vraie.
:::

## Deux visibilités

| `visibility` | Qui le voit | Qui s’inscrit |
|---|---|---|
| `members_only` (par défaut) | seulement avec un jeton de membre ou le client de l’association | les membres avec une carte valable |
| `public` | tout le monde, sans connexion : `GET /v1/aps/{slug}/events` | les membres et — quand le type d’inscription n’exige pas de carte — les **invités** |

Un événement public montre aux visiteurs de votre site le contenu et les types d’inscription avec les places restantes ;
les événements réservés aux membres n’apparaissent qu’après la connexion.

## Afficher les événements

```js title="page publique, sans connexion"
import { publicApi } from '@vimine/sdk';
const api = publicApi();
const { items } = await api.events.list('your-slug', { filter: 'upcoming' });
const event = await api.events.get('your-slug', 'jazz-night');
```

```js title="après Se connecter avec Vimine (événements réservés aux membres compris)"
const { items } = await vimine.events.list();           // events:read
const event = await vimine.events.get('jazz-night');
```

Chaque événement porte `registration_types[]` : `amount` (0 = gratuit), `currency`, `remaining` (places restantes,
`null` = illimitées), `open` et — quand il n’est pas ouvert — `reason` (`sold_out`, `registration_not_open`,
`registration_closed`). `status` vaut `published`, `completed` (la date est passée) ou `cancelled`.

Sans écrire de code : l’élément [`<vimine-events>`](https://developers.vimine.network/fr/sdk/elements/) affiche la liste avec les boutons
d’inscription.

## Une personne qui n’est pas encore membre

Un événement public atteint aussi des personnes qui ne sont pas membres : c’est le moment où une personne décide de le
devenir. La page d’adhésion de l’association sur Vimine s’ouvre **avec l’événement**, et la personne adhère et réserve
en une seule étape :

```
https://app.vimine.network/enroll/your-slug?event=jazz-night
```

```js title="la même adresse, depuis votre code"
import { eventEnrollUrl } from '@vimine/sdk/elements';
const url = eventEnrollUrl('https://app.vimine.network', 'your-slug', 'jazz-night', 'en');
```

Ce que devient la place dépend de l’état de l’adhésion, et la page le dit à la personne :

| L’adhésion | La place |
|---|---|
| est active tout de suite (carte gratuite, sans approbation) | **confirmée**, quand l’inscription à l’événement est gratuite |
| attend l’approbation ou la cotisation | pour une inscription réservée aux membres : **retenue** jusqu’à ce que la carte soit active, puis, si elle est gratuite, confirmée d’elle-même. Pour une inscription ouverte à tous : confirmée tout de suite, comme pour un non-membre |
| l’inscription à l’événement demande une contribution | **retenue** jusqu’à l’échéance fixée par l’association : confirmée quand celle-ci enregistre la contribution |
| l’adresse e-mail n’est pas encore confirmée | rien n’est retenu : la place est demandée quand la personne confirme son adresse depuis le lien reçu par e-mail, et un e-mail lui dit comment cela s’est passé |

Une personne déjà membre utilise la même page : elle se connecte et réserve d’un seul bouton, sans rien remplir
(`&signin=1` ouvre tout de suite la connexion). Cela s’applique aux événements `public` publiés et encore à venir :
avec tout autre slug, la page est la page d’adhésion ordinaire.

La page publique de l’événement sur Vimine (`/agenda/your-slug/jazz-night`) et `<vimine-events>` offrent déjà aux
visiteurs cette porte d’entrée : *Adhérer à l’association et réserver*.

## Inscrire un membre

Avant d’afficher le bouton, demandez à l’API si le membre peut s’inscrire — la réponse dit pourquoi il ne le peut pas :

```js
const { can_register, types } = await vimine.events.eligibility('jazz-night');
// types[i].reasons: membership_required, membership_not_active, membership_not_yet_valid, sold_out, max_per_user, registration_closed, …
```

Puis inscrivez-le (`registrations:write`) :

```js
const reg = await vimine.registrations.create('jazz-night', { registration_type: types[0].uid, note: 'Je viens avec ma sœur' });
if (reg.status === 'confirmed') drawQr(reg.token);           // type gratuit : confirmée, QR prêt
if (reg.status === 'reserved') show(reg.payment_instructions); // contribution : réservée jusqu’au paiement
```

- Un type **gratuit** confirme tout de suite et renvoie `token` : le contenu du QR que le membre présente à l’entrée
  (dessinez-le vous-même, avec la bibliothèque que vous préférez).
- Un type **avec contribution** réserve la place (`reserved_until`) et renvoie les instructions de paiement de
  l’association ; le secrétariat confirme quand il enregistre la contribution — le membre reçoit un e-mail et, à partir
  de là, `vimine.registrations.get(id)` porte le `token`. Les paiements par carte bancaire arrivent avec Stripe.
- Si la carte du membre attend encore son activation, l’inscription reste `reserved` et se confirme d’elle-même quand
  la carte devient active.
- `422 not_eligible` porte dans `errors[]` les mêmes raisons que l’appel d’éligibilité.

Les inscriptions du membre : `vimine.registrations.list({ filter: 'upcoming' })` ; l’annulation dans la fenêtre de
l’événement (`registration.cancellation_hours` heures avant le début) : `vimine.registrations.cancel(id)` — plus tard,
`409 window_closed`.

## Invités (événements publics)

Un visiteur sans compte Vimine peut s’inscrire à un événement **public**, sur un type d’inscription qui n’exige pas de
carte, depuis votre serveur (client confidentiel, `registrations:write`) :

```js title="server"
await srv.registrations.guest('jazz-night', { email, first_name, last_name, registration_type });
// → { status: 'accepted' }, toujours
```

Aucun compte n’est créé. L’invité reçoit un e-mail avec un lien de confirmation (valable 24 heures) qui mène à la page
de l’événement sur Vimine : avec un type gratuit, la place y est confirmée et le QR affiché tout de suite ; avec une
contribution, la place reste réservée avec les instructions de paiement. Si vous préférez héberger vous-même la page de
confirmation, consommez le jeton du lien avec `api.confirmRegistration(token)`.

Une fois la place confirmée — tout de suite avec un type gratuit, quand la contribution est enregistrée sinon —
l’invité reçoit un second e-mail avec son propre lien : il ouvre la page de l’événement avec le QR à présenter à
l’entrée, et il fonctionne jusqu’à la fin de l’événement (un événement reporté le conserve). Un invité n’a pas
d’espace personnel : le lien est sa place, jamais le QR lui-même (un e-mail transféré n’est pas une place). Si vous
hébergez vous-même cette page, lisez la place avec `api.viewRegistration(token)` (SDK depuis 0.3.2).

La réponse est toujours `202 { status: 'accepted' }` : l’API ne révèle jamais si une adresse est déjà inscrite. Les
problèmes d’éligibilité (`sold_out`, `membership_required` pour un type réservé aux membres) sont des `422`.

:::caution[Fiscalité]
Selon le Code du tiers secteur italien, les contributions des **non-membres** sont des recettes commerciales : la
console le signale quand un événement est rendu public, et chaque contribution est classée automatiquement d’après
l’adhésion qu’avait l’inscription au moment du paiement.
:::

## À l’entrée

Le QR d’une inscription est un jeton signé comme celui de la carte : le même scanner et le même appel l’acceptent.

```js title="server (tourniquet, scanner, accueil)"
const r = await srv.checkins.create(scannedToken);
if (r.kind === 'registration') {
    // r.verdict: valid | already_checked_in | not_confirmed | cancelled | event_cancelled | membership_invalid
    // r.first : true au premier passage ; r.membership_verdict quand le type exige une carte
}
```

La vérification publique répond aussi pour un jeton d’inscription : `GET /v1/verify/{token}` →
`{ status, kind: 'registration', event: { slug, starts_at } }`, sans données personnelles.

## Depuis votre back-office

Les inscriptions d’un événement — identifiant, état, type, adhésion, entrée, **sans données personnelles** — sont
`srv.registrations.listForEvent(slug, { status, limit, cursor })` (`registrations:read`, formules avec listes via
l’API). Les noms restent dans la console de l’association.

## Références

- [SDK navigateur](https://developers.vimine.network/fr/sdk/browser/#events) · [SDK serveur](https://developers.vimine.network/fr/sdk/server/#events) ·
  [`<vimine-events>`](https://developers.vimine.network/fr/sdk/elements/) · [Types](https://developers.vimine.network/fr/sdk/types/)
- API HTTP : les opérations étiquetées `events` et `registrations` dans la [référence](https://developers.vimine.network/fr/api/console/).
