Aller au contenu

VimineServer

Afficher en Markdown
import { VimineServer } from '@vimine/sdk/server';
const vimineServer = new VimineServer({ clientId: 'vmc_…', clientSecret: process.env.VIMINE_SECRET });

Pour les systèmes propres à l’association : un client confidentiel qui s’authentifie avec client_credentials, lit l’état des cartes et pilote sa sandbox. Node ≥ 18. Le secret ne doit jamais atteindre un navigateur.

Option Type Par défaut
clientId string — obligatoire
clientSecret string — obligatoire ; vms_… ou vms_test_…
scopes Scope[] tous ceux enregistrés un sous-ensemble à demander
apiUrl string https://api.vimine.network
fetch typeof fetch globalThis.fetch

Un jeton d’accès client (client_credentials, HTTP Basic), mis en cache jusqu’à 30 secondes avant son expiration (1 heure) ; une seule requête même en cas d’appels concurrents.

Un appel authentifié avec Authorization: Bearer ; JSON en entrée et en sortie ; erreurs sous forme de VimineError. Un 401 (identifiants régénérés ou révoqués) est réessayé une fois avec un nouveau jeton.

État d’une adhésion de l’association, sans données personnelles (memberships:read) :

const s = await vimineServer.memberships.status('membership-uuid');
// { id, status: 'active', verdict: 'valid', valid_until: '2027-03-31T22:59:59.000Z', membership_type: { cod: 'ORD' } }

Crée un compte Vimine pour une personne (identity:signup) : elle reçoit l’e-mail pour confirmer son adresse et choisir un mot de passe. Répond toujours { status: 'accepted' } — que l’adresse ait déjà eu un compte ne vous est pas révélé (son titulaire en est informé, par e-mail). opts.idempotencyKey (générée si elle est absente).

await vimineServer.signup({ email: 'mario.rossi@example.org', first_name: 'Mario', last_name: 'Rossi', phone: '+39 …' });

Envoie une demande d’adhésion pour une personne (enroll:write) : une nouvelle adresse obtient un compte et une demande en attente ; le titulaire d’un compte existant reçoit plutôt un lien de confirmation (rien n’est écrit tant qu’il ne l’utilise pas). accept_statuto (la version en vigueur) est obligatoire ; privacy_notice aussi quand l’association publie une notice d’information à ses membres (association(slug).privacy_notice) : la personne la lit sur votre site et vous passez la version affichée. Voir Intégrations serveur.

La personne est identifiée par codicefiscale ou par dob + birthplace + birth_country — jamais ni l’un ni l’autre (422, une entrée required pour chaque donnée manquante). Un code en désaccord avec les données de naissance est une entrée codicefiscale_mismatch dans err.errors, avec mismatches, hints et confirmable : quand confirmable vaut true et que la personne confirme, répétez avec codicefiscale_confirmed: true. address (MemberAddress) quand l’association recueille l’adresse de ses membres (aps.member_address). Voir Membres sans code fiscal.

// avec un code fiscal
await vimineServer.enroll({ ...person, codicefiscale: 'RSSMRA80A01H501U', accept_statuto: { version: 3 }, privacy_notice: { version: 2 } }, { idempotencyKey: 'order-42' });
// sans : date, lieu et pays de naissance
await vimineServer.enroll({ ...person, dob: '1985-03-10', birthplace: 'Lyon', birth_country: 'FR', accept_statuto: { version: 3 }, privacy_notice: { version: 2 } });

Enregistre un passage à l’entrée à partir du jeton lu sur le QR (checkins:write). Une carte répond { kind: 'card', verdict, status, membership_id, valid_until, valid_from, identity_check, checked_in_at } — identity_check: 'pending' est une indication à afficher à la personne qui tient l’entrée, elle ne fait pas partie de verdict et ne restreint rien (guide) ; le QR d’une inscription à un événement répond { kind: 'registration', verdict, registration_id, event, first, membership_verdict, … } (voir Événements et inscriptions).

events.list(params?) · events.get(slug) — les événements publiés de l’association, y compris ceux réservés aux membres (n’importe quel jeton client).

registrations.listForEvent(slug, { status?, limit?, cursor? }) les inscriptions d’un événement : identifiant, état, type, adhésion, entrée — sans données personnelles (registrations:read, formules avec listes via l’API)
registrations.guest(slug, { email, first_name, last_name, registration_type, note? }, opts?) inscrit un invité sans compte à un événement public ; toujours { status: 'accepted' } ; Idempotency-Key générée (voir invités)

Les adhésions de l’association (memberships:read, formules avec listes) : { items: [{ id, status, verdict, membership_type, issued_at, valid_until, updated_at }], next_cursor } ; params : status, updated_since, limit, cursor.

Clients de test seulement : les membres synthétiques de la sandbox et la réinitialisation (nouveau mot de passe commun, renvoyé une fois). Un client de production reçoit 403.

Les endpoints publics, sans identifiants : voir publicApi.

express.js
import express from 'express';
import { VimineServer, VimineError } from '@vimine/sdk/server';
const vimineServer = new VimineServer({ clientId: process.env.VIMINE_CLIENT_ID, clientSecret: process.env.VIMINE_SECRET });
const app = express();
app.get('/cards/:id/status', async (req, res) => {
try {
const { status, verdict, valid_until } = await vimineServer.memberships.status(req.params.id);
res.json({ status, verdict, valid_until });
} catch (err) {
if (err instanceof VimineError && err.code === 'not_found') return res.status(404).end();
throw err;
}
});