Pular para o conteúdo

Associados sem código fiscal

Ver como Markdown

Associar-se a uma associação não exige um código fiscal italiano (codice fiscale). O que exige é que a pessoa esteja identificada, e no Vimine ela está de uma de duas formas:

  • por um código fiscal, ou
  • pelos seus dados de nascimento: dob + birthplace + birth_country (ISO 3166-1 alpha-2).

Nunca por nenhum dos dois. O resto deste guia é o que muda, campo por campo, para uma integração que faz a adesão de pessoas — estudantes de intercâmbio, voluntários recém-chegados, associados que moram no exterior.

POST /v1/enroll e POST /v1/signup recebem os mesmos campos:

Campo
codicefiscale opcional. Quando presente, é validado e conferido com os nomes, a data e o local de nascimento
dob data de nascimento, YYYY-MM-DD
birthplace o comune (o município italiano) para quem nasceu na Itália; a cidade, em texto livre, para quem nasceu no exterior
birth_country país de nascimento, duas letras (IT, FR, SN…)
gender só estatístico: não é mais conferido com o código
// Sem código fiscal: data, local e país de nascimento
await vimineServer.enroll({
email: 'marie.dupont@example.org',
first_name: 'Marie',
last_name: 'Dupont',
dob: '1985-03-10',
birthplace: 'Lyon',
birth_country: 'FR',
accept_statuto: { version: statuto.version, sha256: statuto.sha256 }
});

Em /v1/enroll, sem um código, cada dado de nascimento que falta é um 422 validation_failed com uma entrada em errors[]:

{ "code": "validation_failed", "errors": [{ "field": "birth_country", "code": "required" }] }

/v1/signup cria só a conta: ali os dados de nascimento continuam opcionais, e serão necessários quando a pessoa pedir uma carteirinha.

O código fiscal de quem nasceu na Itália traz o comune de nascimento; o de quem nasceu no exterior traz só o país. Por isso, para essas pessoas, a conferência compara birth_country e trata birthplace — a cidade — como texto livre. Enviar birth_country é o que faz passar uma pessoa nascida no exterior com um código válido: sem ele, “Lyon” seria procurada entre os comuni italianos e o código sairia incoerente. (Um formulário que até agora enviava o nome italiano do país como local de nascimento — birthplace: 'Francia' — continua passando; birth_country é a forma preferível.)

O mesmo vale para a verificação pública, que agora também diz o que o código traz:

const r = await publicApi().validateFiscalCode({
code: 'DPNMRA85C50Z110U', first_name: 'Marie', last_name: 'Dupont', date: '1985-03-10', place: 'Lyon', country: 'FR'
});
// { valid: true, error: null, mismatches: [], hints: [], birth_date: '1985-03-10', birth_country: 'FR' }

birth_date e birth_country são lidos do próprio código: você pode usá-los para preencher o formulário. Este endpoint ainda compara gender, quando você o envia; a adesão e o perfil, não.

Um código digitado errado (estrutura ou caractere de controle) é invalid_codicefiscale: ele precisa ser corrigido, nunca pode ser confirmado. Um código bem formado que não confere com os dados informados responde, em vez disso, 422 com uma entrada mais rica:

{
"code": "validation_failed",
"errors": [{
"field": "codicefiscale",
"code": "codicefiscale_mismatch",
"mismatches": ["place"],
"hints": [],
"confirmable": true
}]
}
  • mismatches — o que não confere: lastName, firstName, date, place;
  • hints — names_swapped quando o código confere trocando sobrenome e nome: oferecer a troca costuma bastar;
  • confirmable — se a pessoa pode confirmar que esse é o código do seu cartão de saúde italiano. Acontece: comuni que não existem mais, transliterações, nomes registrados em outra ordem.

Quando confirmable é true, pergunte à pessoa e repita o pedido com codicefiscale_confirmed: true. Quando os dois nomes e a data não conferem, nada mais liga aquele código àquela pessoa: confirmable é false e o único caminho é corrigi-lo.

import { VimineError } from '@vimine/sdk/server';
try {
await vimineServer.enroll(input);
} catch (err) {
const entry = err instanceof VimineError && err.errors?.find((e) => e.code === 'codicefiscale_mismatch');
if (!entry) throw err;
if (entry.confirmable && (await askThePerson(entry.mismatches, entry.hints))) {
await vimineServer.enroll({ ...input, codicefiscale_confirmed: true });
}
}

Não envie codicefiscale_confirmed por iniciativa própria: é uma declaração da pessoa, e é registrada como tal.

Quem se associou sem um código pode adicioná-lo quando tiver um, pelo próprio perfil:

const me = await vimine.me.update({ codicefiscale: 'DPNMRA85C50Z110U' });
me.codicefiscale_check; // 'matched'

PATCH /v1/me aceita birth_country e codicefiscale_confirmed, só de escrita; codicefiscale também pode voltar a null. GET /v1/me diz como a pessoa está identificada:

codicefiscale_check
matched um código fiscal que confere com os dados de nascimento da pessoa
mismatch_confirmed um código que não confere, confirmado pela pessoa
absent nenhum código: data, local e país de nascimento a identificam
null ainda não identificada: não pode pedir uma carteirinha

matched quer dizer coerente, não verificado no cadastro tributário: um código fiscal continua sendo um dado declarado.

Uma conta pode existir sem estar identificada — alguém que se cadastrou só para entrar, por exemplo. Quando essa pessoa pede uma carteirinha, a API diz isso e indica o que falta:

  • POST /v1/me/membership → 422 identification_required, com errors[] = os dados de nascimento que faltam ({ field: 'birthplace', code: 'required' }…). Mande a pessoa completar o perfil com PATCH /v1/me (permissão profile:write) e repita o pedido.
  • POST /v1/enroll/confirm — o link “confirme o seu pedido” que o dono de uma conta existente recebe → 409 identification_required, mesmos errors[]. Peça os dados de nascimento na página e envie o token de novo com identification:
await publicApi().confirmEnrollment(token, { dob: '1985-03-10', birthplace: 'Lyon', birth_country: 'FR' });
// POST /v1/enroll/confirm { token, identification: { dob, birthplace, birth_country, codicefiscale?, codicefiscale_confirmed? } }

Os dados de nascimento viajam no corpo da requisição, nunca no link: nada pessoal vai no link. identification só completa os campos vazios do perfil, não sobrescreve o que já existe; se os dados não conferirem, a resposta é um 422 validation_failed como acima.

A admissão não muda: os pending_reasons são os que o modelo de admissão da associação determina, para todos (veja Admissão e ativação).

Um código fiscal que confere com os dados de nascimento pode ser verificado com eles; os dados de nascimento sozinhos, ou um código que a pessoa confirmou, não. Para esses associados a associação olha um documento uma vez, na primeira vez que a pessoa vem. Quem integra um leitor vê isso em POST /v1/checkins (permissão checkins:write), nas respostas para uma carteirinha:

const r = await vimineServer.checkins.create('vmt_…');
// { kind: 'card', verdict: 'valid', …, identity_check: 'pending' }
if (r.identity_check === 'pending') show('Primeira entrada: peça um documento');
identity_check
pending o associado não tem um código fiscal verificável e ninguém da associação olhou um documento dele ainda: mostre isso a quem cuida da entrada
verified alguém da associação olhou um documento
flagged alguém olhou um e ele não conferia: a secretaria da associação assume a partir daí
null nada a verificar

É uma observação, não faz parte do verdict e não restringe nada: uma carteirinha valid com identity_check: 'pending' entra. O resultado é registrado pelo console da associação, não pela API. A verificação pública GET /v1/verify/{card_token} nunca o traz: quem verifica uma carteirinha de fora vê só status e vencimento.

Algumas associações guardam o endereço dos seus associados no livro de associados, outras não. A escolha é da associação e vale para todos os associados ou para nenhum; o perfil público a declara:

GET https://api.vimine.network/v1/aps/{slug}
→ { "aps": { …, "member_address": "optional" } }
member_address
none não pergunte: um address enviado mesmo assim não é guardado
optional pergunte, sem torná-lo obrigatório
required sem um address, a adesão responde 422 com { field: 'address', code: 'required' }
await vimineServer.enroll({
…,
address: { kind: 'residence', line: 'Via Roma 1', postal_code: '20121', city: 'Milano', province: 'MI', country: 'IT' }
});

line e city são obrigatórios dentro de address; kind é residence (o padrão) ou domicile, quando difere da residência; country é IT quando omitido; province diz respeito só aos endereços italianos. /v1/signup não tem address: o endereço pertence à carteirinha, não à conta.

Não existe uma configuração “código fiscal obrigatório”. Uma associação não pode exigir um código fiscal de todos os que pedem a adesão: quem não tem é identificado pelos dados de nascimento, em todo lugar. Se o seu formulário o torna obrigatório, essa é uma escolha do seu formulário — e ela deixa de fora pessoas que a associação poderia receber.

Tudo aditivo: um formulário que sempre envia um código fiscal continua funcionando sem mudanças. O que uma integração existente pode notar:

  • codicefiscale não é mais obrigatório em POST /v1/enroll; sem um código, são necessários dob, birthplace e birth_country (422 required em cada um que falta);
  • novos campos opcionais birth_country, codicefiscale_confirmed (enroll, signup, PATCH /v1/me) e address (enroll);
  • gender não é mais conferido com o código: um 422 só sobre o sexo não acontece mais;
  • um código que não confere continua respondendo codicefiscale_mismatch, agora com hints e confirmable ao lado de mismatches; um código malformado continua sendo invalid_codicefiscale;
  • GET/PATCH /v1/me agora têm um schema declarado (Me), com birth_country e codicefiscale_check;
  • um novo erro identification_required: 422 em POST /v1/me/membership, 409 em POST /v1/enroll/confirm (que aceita identification no corpo);
  • POST /v1/validate/fiscal-code aceita country e também responde hints, birth_date, birth_country; error é invalid, mismatch ou null;
  • POST /v1/checkins adiciona identity_check às respostas para uma carteirinha; GET /v1/verify/{card_token} continua como estava;
  • o perfil público adiciona aps.member_address.