# Veranstaltungen und Anmeldungen

> Die Veranstaltungen des Vereins auf Ihrer Website veröffentlichen, Mitglieder (und bei öffentlichen Veranstaltungen Gäste) sich anmelden lassen, am Einlass mit demselben Scanner wie für die Ausweise einlassen.

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

Die Veranstaltungen, die ein Verein in seiner Konsole veröffentlicht, stehen nach demselben Prinzip wie die Ausweise in der API:
**Headless-Inhalte** (Titel, Zusammenfassung, Beschreibung in Markdown, Bilder, Ort, Daten, Links) und **Live-Verfügbarkeit**
pro Anmeldeart — nie, *wer* angemeldet ist. Das Vokabular ist das des italienischen Dritten Sektors: eine
**Anmeldung** (*iscrizione*) und, wenn ein Betrag anfällt, ein **Beitrag** (*contributo*).

:::note[Bevor Sie anfangen]
Ihr Client braucht die Berechtigungen `events:read`, `registrations:read` und `registrations:write` (siehe
[Berechtigungen, Fehler und Limits](https://developers.vimine.network/de/guides/scopes-and-errors/)). Um auszuprobieren, ohne echte Daten zu berühren, verwenden Sie
die [Sandbox](https://developers.vimine.network/de/guides/sandbox/): Der Zwillingsverein kann Veranstaltungen veröffentlichen wie der echte.
:::

## Zwei Sichtbarkeiten

| `visibility` | Wer sie sieht | Wer sich anmeldet |
|---|---|---|
| `members_only` (Standard) | nur mit einem Mitglieder-Token oder dem eigenen Client des Vereins | Mitglieder mit gültigem Ausweis |
| `public` | alle, ohne Anmeldung: `GET /v1/aps/{slug}/events` | Mitglieder und — wenn die Anmeldeart keinen Ausweis verlangt — **Gäste** |

Eine öffentliche Veranstaltung zeigt den Besuchern Ihrer Website die Inhalte und die Anmeldearten mit den freien Plätzen;
Veranstaltungen nur für Mitglieder erscheinen erst nach der Anmeldung mit Vimine.

## Veranstaltungen anzeigen

```js title="öffentliche Seite, ohne Anmeldung"
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="nach Mit Vimine anmelden (einschließlich Veranstaltungen nur für Mitglieder)"
const { items } = await vimine.events.list();           // events:read
const event = await vimine.events.get('jazz-night');
```

Jede Veranstaltung trägt `registration_types[]`: `amount` (0 = kostenlos), `currency`, `remaining` (freie Plätze, `null` =
unbegrenzt), `open` und — wenn sie nicht offen ist — `reason` (`sold_out`, `registration_not_open`,
`registration_closed`). `status` ist `published`, `completed` (das Datum ist vorbei) oder `cancelled`.

Ohne Code zu schreiben: Das Element [`<vimine-events>`](https://developers.vimine.network/de/sdk/elements/) zeigt die Liste mit den
Schaltflächen zum Teilnehmen.

## Wer noch nicht Mitglied ist

Eine öffentliche Veranstaltung erreicht auch Menschen, die nicht Mitglied sind: Es ist der Moment, in dem jemand beschließt, es zu werden.
Die Beitrittsseite des Vereins auf Vimine öffnet sich **mit der Veranstaltung**, und die Person tritt bei und reserviert in einem
Schritt:

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

```js title="dieselbe Adresse, aus Ihrem Code"
import { eventEnrollUrl } from '@vimine/sdk/elements';
const url = eventEnrollUrl('https://app.vimine.network', 'your-slug', 'jazz-night', 'en');
```

Was aus dem Platz wird, hängt davon ab, wie es um die Mitgliedschaft steht, und die Seite sagt es der Person:

| Die Mitgliedschaft | Der Platz |
|---|---|
| ist sofort aktiv (kostenloser Ausweis, keine Genehmigung) | **bestätigt**, wenn die Anmeldung zur Veranstaltung kostenlos ist |
| wartet auf die Genehmigung oder den Mitgliedsbeitrag | bei einer Anmeldung nur für Mitglieder: **reserviert**, bis der Ausweis aktiv ist, und dann, wenn sie kostenlos ist, von selbst bestätigt. Bei einer Anmeldung für alle: sofort bestätigt, wie für ein Nichtmitglied |
| die Anmeldung zur Veranstaltung verlangt einen Beitrag | **reserviert** bis zu der Frist, die der Verein festgelegt hat: bestätigt, wenn er den Beitrag erfasst |
| die E-Mail-Adresse ist noch nicht bestätigt | nichts wird reserviert: Der Platz wird angefragt, wenn die Person die Adresse über den Link in der E-Mail bestätigt, und eine E-Mail sagt ihr, wie es ausgegangen ist |

Wer schon Mitglied ist, nutzt dieselbe Seite: Er meldet sich an und reserviert mit einer Schaltfläche, ohne etwas
auszufüllen (`&signin=1` öffnet sofort die Anmeldung). Das gilt für veröffentlichte `public`-Veranstaltungen, die noch
bevorstehen: Mit jedem anderen Slug ist die Seite die gewöhnliche Beitrittsseite.

Die öffentliche Seite der Veranstaltung auf Vimine (`/agenda/your-slug/jazz-night`) und `<vimine-events>` bieten Besuchern
diesen Zugang bereits an: *Dem Verein beitreten und Platz reservieren*.

## Ein Mitglied anmelden

Bevor Sie die Schaltfläche zeigen, fragen Sie die API, ob sich das Mitglied anmelden darf — die Antwort sagt, warum nicht:

```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, …
```

Dann melden Sie es an (`registrations:write`):

```js
const reg = await vimine.registrations.create('jazz-night', { registration_type: types[0].uid, note: 'Ich komme mit meiner Schwester' });
if (reg.status === 'confirmed') drawQr(reg.token);           // kostenlose Art: bestätigt, QR bereit
if (reg.status === 'reserved') show(reg.payment_instructions); // mit Beitrag: reserviert bis zur Zahlung
```

- Eine **kostenlose** Art bestätigt sofort und liefert `token`: den Inhalt des QR-Codes, den das Mitglied am Einlass vorzeigt
  (zeichnen Sie ihn selbst, mit der Bibliothek Ihrer Wahl).
- Eine Art **mit Beitrag** reserviert den Platz (`reserved_until`) und liefert die Zahlungsanweisungen des Vereins;
  das Sekretariat bestätigt, wenn es den Beitrag erfasst — das Mitglied erhält eine E-Mail, und von
  da an trägt `vimine.registrations.get(id)` das `token`. Kartenzahlungen kommen mit Stripe.
- Wartet der Ausweis des Mitglieds noch auf die Aktivierung, bleibt die Anmeldung `reserved` und bestätigt sich selbst, wenn
  der Ausweis aktiv wird.
- `422 not_eligible` trägt in `errors[]` dieselben Gründe wie die Teilnahmeprüfung.

Die Anmeldungen des Mitglieds: `vimine.registrations.list({ filter: 'upcoming' })`; Stornierung innerhalb des Fensters der
Veranstaltung (`registration.cancellation_hours` Stunden vor Beginn): `vimine.registrations.cancel(id)` — danach
`409 window_closed`.

## Gäste (öffentliche Veranstaltungen)

Ein Besucher ohne Vimine-Konto kann sich für eine **öffentliche** Veranstaltung anmelden, mit einer Anmeldeart, die keinen
Ausweis verlangt, über Ihren Server (vertraulicher Client, `registrations:write`):

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

Es wird kein Konto angelegt. Der Gast erhält eine E-Mail mit einem Bestätigungslink (24 Stunden gültig), der auf der
Seite der Veranstaltung auf Vimine landet: Bei einer kostenlosen Art wird der Platz dort bestätigt und der QR-Code sofort gezeigt; mit
Beitrag bleibt der Platz reserviert, mit den Zahlungsanweisungen. Wenn Sie die Bestätigungsseite lieber selbst
hosten, lösen Sie das Token des Links mit `api.confirmRegistration(token)` ein.

Sobald der Platz bestätigt ist — sofort bei einer kostenlosen Art, sonst wenn der Beitrag erfasst ist —, erhält der Gast
eine zweite E-Mail mit seinem eigenen Link: Er öffnet die Seite der Veranstaltung mit dem QR-Code für den Einlass und
funktioniert, bis die Veranstaltung vorbei ist (eine verschobene Veranstaltung behält ihn). Ein Gast hat keinen persönlichen Bereich: Der Link ist sein
Platz, nie der QR-Code selbst (eine weitergeleitete E-Mail ist kein Platz). Wenn Sie diese Seite selbst hosten, lesen Sie den Platz mit
`api.viewRegistration(token)` (SDK ab 0.3.2).

Die Antwort ist immer `202 { status: 'accepted' }`: Die API verrät nie, ob eine Adresse bereits
registriert ist. Probleme mit der Teilnahmeberechtigung (`sold_out`, `membership_required` bei einer Art nur für Mitglieder) sind `422`.

:::caution[Steuern]
Nach dem italienischen Kodex des Dritten Sektors sind Beiträge von **Nichtmitgliedern** gewerbliche Einnahmen: Die Konsole
weist darauf hin, wenn eine Veranstaltung öffentlich gemacht wird, und jeder Beitrag wird automatisch nach der Mitgliedschaft
eingeordnet, die die Anmeldung zum Zeitpunkt der Zahlung hatte.
:::

## Am Einlass

Der QR-Code der Anmeldung ist ein signiertes Token wie der des Ausweises: Derselbe Scanner und derselbe Aufruf akzeptieren ihn.

```js title="Server (Drehkreuz, Scanner, Kasse)"
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 beim ersten Durchgang; r.membership_verdict, wenn die Art einen Ausweis verlangt
}
```

Die öffentliche Prüfung beantwortet auch ein Anmelde-Token: `GET /v1/verify/{token}` →
`{ status, kind: 'registration', event: { slug, starts_at } }`, ohne personenbezogene Daten.

## Aus Ihrem Backoffice

Die Anmeldungen einer Veranstaltung — ID, Status, Art, Mitgliedschaft, Check-in, **keine personenbezogenen Daten** — liefert
`srv.registrations.listForEvent(slug, { status, limit, cursor })` (`registrations:read`, Tarife mit API-Listen).
Die Namen bleiben in der Konsole des Vereins.

## Verweise

- [Browser-SDK](https://developers.vimine.network/de/sdk/browser/#events) · [Server-SDK](https://developers.vimine.network/de/sdk/server/#events) ·
  [`<vimine-events>`](https://developers.vimine.network/de/sdk/elements/) · [Typen](https://developers.vimine.network/de/sdk/types/)
- HTTP-API: die Operationen mit den Tags `events` und `registrations` in der [Referenz](https://developers.vimine.network/de/api/console/).
