# Integrações de servidor

> Clientes confidenciais para os sistemas da própria associação, client_credentials, status da carteirinha, rotação do segredo.

URL: https://developers.vimine.network/pt/guides/server/

Para os sistemas **da própria associação** — um software de gestão, uma catraca, um plugin de CMS — um cliente
**confidencial** com `client_id` + `client_secret`. O segredo é mostrado uma vez só e nunca deve chegar a um
navegador.

## Autenticação

```js title="Node"
import { VimineServer } from '@vimine/sdk/server';

const vimineServer = new VimineServer({
    clientId: 'vmc_…',
    clientSecret: process.env.VIMINE_SECRET,
    scopes: ['memberships:read']
});
const token = await vimineServer.token();      // client_credentials — token de 1 hora, renovado sozinho
```

Sem o SDK: `POST /v1/oauth/token` com `grant_type=client_credentials` e HTTP Basic
`client_id:client_secret` (ou `client_id`/`client_secret` no corpo):

```sh
curl -u "vmc_…:vms_…" -d "grant_type=client_credentials&scope=memberships:read" \
     https://api.vimine.network/v1/oauth/token
```

Nos endpoints de leitura (`/v1/memberships/{id}/status`, `/v1/memberships`) o HTTP Basic também é aceito
**diretamente**, sem passar por um token, para hardware e plataformas low-code — nunca a partir de um navegador.

## Status de uma carteirinha

```js
const s = await vimineServer.memberships.status('membership-uuid');
// { id, status: 'active', verdict: 'valid', valid_until: '2027-…', membership_type: { cod: 'ORD' } }
```

Nenhum dado pessoal: só status e validade. O `id` é o que o associado vê na própria carteirinha
(`membership.id` via *Entrar com Vimine*) ou o que o seu sistema recebeu quando a registrou.

Para verificar uma carteirinha **mostrada na entrada**, use em vez disso o token do QR com
[`/v1/verify/{card_token}`](https://developers.vimine.network/pt/guides/embed-and-verify/): ele não precisa de nenhuma autenticação.

## Fazer a adesão de associados pelo seu sistema

Com `identity:signup` e `enroll:write` o seu back office pode criar contas e enviar pedidos de adesão
**sem que a pessoa passe pelo Vimine**: ela recebe por e-mail o link para confirmar o endereço e escolher uma
senha.

```js
// Só a conta (a pessoa ainda não é associada)
await vimineServer.signup({ email: 'mario.rossi@example.org', first_name: 'Mario', last_name: 'Rossi' });

// Conta + pedido de adesão pendente, aprovado pela secretaria no back office do Vimine
const { statuto, membership_types } = await vimineServer.public.association('your-slug');
await vimineServer.enroll({
    email: 'mario.rossi@example.org',
    first_name: 'Mario',
    last_name: 'Rossi',
    codicefiscale: 'RSSMRA80A01H501U',      // opcional: sem ele, são necessários dob + birthplace + birth_country
    dob: '1980-01-01', birthplace: 'Roma', birth_country: 'IT',
    gender: 'M',                              // só estatístico: não é conferido com o código
    membership_type: membership_types[0].uid, // opcional quando existe exatamente um tipo
    accept_statuto: { version: statuto.version, sha256: statuto.sha256 },
    privacy_notice: privacy_notice && { version: privacy_notice.version, sha256: privacy_notice.sha256 } // obrigatório quando a associação publica um
});
```

A resposta é **sempre** `202 { status: 'accepted' }`, seja o que for que exista por trás do endereço: você não tem como
saber se um e-mail já tem uma conta Vimine (só o dono dele é avisado, por e-mail). Em detalhe:

- **endereço novo** → conta criada e, com `enroll`, um pedido de adesão *pendente*; e-mail de boas-vindas com a
  confirmação do endereço;
- **endereço já cadastrado** → com `enroll` nada é gravado: o dono recebe um link "confirme o seu pedido
  a *<associação>*" válido por 24 horas, e o pedido só é criado quando ele o usa. Se ele já é associado,
  nada acontece;
- os erros `422` dizem respeito só ao *seu* payload (`validation_failed` com `errors[].field`, `statuto_outdated`,
  `invalid_type`); `403 api_disabled` quando a associação não aceita pedidos; `403 not_available` durante o
  [beta privado](https://developers.vimine.network/pt/guides/scopes-and-errors/#o-beta-privado), enquanto as contas só são criadas por convite.

Uma pessoa é identificada por um **código fiscal ou** pela data, local e país de nascimento (`dob`, `birthplace`,
`birth_country`) — nunca por nenhum dos dois: sem um código, cada dado de nascimento que falta é uma entrada `required`
em `errors[]`. Para uma pessoa nascida no exterior, envie sempre `birth_country`: o código dela só traz o país. Um código
que não confere com os dados de nascimento responde `422` com uma entrada `codicefiscale_mismatch` que traz
`mismatches`, `hints` e `confirmable`: quando `confirmable` é `true` a pessoa pode confirmá-lo, e você repete a chamada
com `codicefiscale_confirmed: true`. Quando a associação coleta o endereço dos seus associados (`aps.member_address` no
perfil público), adicione `address`. Quando ela coleta os dados de quem exerce o poder familiar
(`aps.collects_guardian_data`) e a pessoa é menor de idade pelo `dob`, `guardian` é obrigatório — `first_name`,
`last_name`, `relation`, opcionalmente `codicefiscale`, `email`, `phone` — senão `422` com `guardian: required`. O
caminho completo está em [Associados sem código fiscal](https://developers.vimine.network/pt/guides/members-without-cf/).

`accept_statuto` precisa indicar o statuto **em vigor**: mostre-o à pessoa no seu site (ele está em
[`association(slug)`](https://developers.vimine.network/pt/sdk/public/); o texto e o documento, em `GET /v1/aps/{slug}/statuto`) e passe a
versão que ela aceitou. Uma associação que não registrou nenhum statuto legível responde `accepting_requests: false`, e
o pedido, `403 not_available`. O mesmo vale para o **aviso de privacidade aos associados** da associação
(`privacy_notice` em `association(slug)`, o texto em `GET /v1/aps/{slug}/privacy-notice`):
quando a associação publica um, o pedido precisa indicar a versão que a pessoa leu, senão `422` (`privacy_notice`
ausente ou `privacy_notice_outdated`); a ciência fica registrada em nome da pessoa, com o seu cliente indicado.
Opcionais, mesma regra: `accept_terms` e `acknowledge_privacy` (as condições de uso da conta e o aviso de privacidade da
plataforma, `GET /v1/legal/{kind}`) quando a pessoa os aceitou no seu site. As chamadas são idempotentes: o SDK
gera uma `Idempotency-Key` por chamada, ou passe a sua (`{ idempotencyKey: 'order-42' }`) para repetir com segurança
depois de um timeout. Os e-mails têm um limite (3 por endereço por dia) e nunca são enviados a partir do sandbox.

## Check-ins na entrada

Com `checkins:write` um dispositivo na entrada registra a passagem de um associado enviando **o token lido no QR
da carteirinha** (não um identificador): a resposta é só o veredito, sem dados pessoais. O HTTP Basic é aceito
diretamente, para hardware e plataformas low-code.

```js
const r = await vimineServer.checkins.create('vmt_…');   // { verdict: 'valid' | 'expired' | 'not_yet_valid' | 'statuto_required' | 'inactive', status, membership_id, valid_until, identity_check, checked_in_at }
```

```sh
curl -u "vmc_…:vms_…" -H "Content-Type: application/json" -d '{"token":"vmt_…"}' https://api.vimine.network/v1/checkins
```

O corpo é `{ "token": "vmt_…" }` — o token lido no QR, de uma carteirinha ou de uma inscrição em evento; só para as carteirinhas, `card` é aceito como alias.

Um token malformado ou falsificado é um `422 invalid_card`; a carteirinha de outra associação é "não encontrada".

`identity_check: 'pending'` é uma observação para quem cuida da entrada: o associado não tem um código fiscal
verificável e ninguém da associação olhou um documento dele ainda. Mostre-a; ela não faz parte do `verdict` e não
restringe nada (veja [a verificação de identidade](https://developers.vimine.network/pt/guides/members-without-cf/#na-entrada-a-verificação-de-identidade)).

## Listar as carteirinhas (planos Pro e Network)

`vimineServer.memberships.list({ status?, updated_since?, limit?, cursor? })` devolve ids, status e datas — **nunca
dados pessoais** — em páginas (`next_cursor`). Com `updated_since` você sincroniza só o que mudou. Nos planos que não
o incluem, a resposta é `403 plan_limit`.

## Rotação do segredo

No console (*Rotacionar segredo*): o novo segredo é mostrado uma vez, **o anterior continua funcionando por
24 horas**, para que você possa atualizar os seus sistemas sem interrupção. Se suspeitar de um comprometimento, revogue
o cliente: todas as sessões dele terminam na hora.

## Segurança

- Um segredo errado, repetido, bloqueia o cliente por 15 minutos.
- Cada token está vinculado à associação do cliente: uma carteirinha de outra associação é simplesmente "não encontrada".
- Um `401` com credenciais recém-rotacionadas é repetido uma vez pelo SDK com um token novo.
- As respostas usam `application/problem+json` (veja [Permissões, erros e limites](https://developers.vimine.network/pt/guides/scopes-and-errors/)).
