A Axenya API v1
Axenya Public API · v1

Documentação da API Axenya

A API pública da Axenya permite que a equipe de TI de uma empresa opere toda a rotina de RH de benefícios de forma programática — sem planilhas, sem portal, sem trabalho manual. Inclusões, exclusões, trocas de plano e alterações de cadastro entram por chamadas HTTP; o envio de arquivos de compliance segue o mesmo caminho.

O v1 é inbound (ingestão): sua empresa alimenta dados na Axenya. Esta documentação mostra como conectar seus sistemas de RH (ERP, folha, sistema de admissão) aos fluxos da Axenya e automatizar a operação ponta a ponta.

Como funciona

A axenya-public-api é uma camada pública de ingestão que fica na frente dos backends internos da Axenya (HR Portal e Landing Zone). Toda chamada autenticada por API key passa por cinco etapas no servidor:

                       TLS + API Key
  Sua empresa  ───────────────────────────►  axenya-public-api
   (sistema de RH)                              │ 1. autentica a API key (hash em repouso)
                                                │ 2. resolve tenant + scopes da key
                                                │ 3. valida o JSON contra o schema gerado
                                                │ 4. cria uma "submission" (recibo) — async
                                                │ 5. chama o backend interno injetando
                                                ▼    o tenant resolvido
                                ┌───────────────┼───────────────────────────┐
                                ▼               │                            ▼
                         hr-portal-api  ◄───────┘                   landing-zone backend
                    (movimentação de vidas)                     (file-types / signed URL GCS)
01

Tenant pela key

A empresa nunca vai no payload — é derivada da API key no servidor. Um cliente jamais escolhe o tenant.

02

Escrita assíncrona

Validação não é instantânea (matching de vida, janelas, antivírus). Toda escrita responde 202 com um recibo.

03

JSON canônico

Você envia JSON limpo. O schema é gerado a partir da definição do backend — sem planilha, sem mapeamento manual.

A regra de ouro do multi-tenant

O isolamento entre empresas é a garantia número 1 da API. A identidade da sua empresa (tenant) é sempre resolvida a partir da API key — nunca de um campo no corpo da requisição. Não existe unitId no payload. A única exceção são as keys de grupo (abaixo): por abrangerem várias unidades, a unidade-alvo é informada e validada contra o grupo.

Grupos e unidades — visão consolidada

Um grupo reúne várias unidades (tenants) sob a mesma gestão de TI. Além da key por unidade, a Axenya emite keys de grupo, que dão visão consolidada sobre todas as unidades do grupo — sem precisar orquestrar N keys manualmente.

Tipo de keyConsultas (GET)Escritas (movimentações)
Key de unidade (tenant) Apenas a própria unidade. Unidade resolvida pela key; sem unitId no payload.
Key de grupo Todas as unidades do grupo, com unit em cada item retornado. A unidade-alvo é informada via unitId e validada como membro do grupo antes de qualquer escrita.
Consolidação sem perder isolamento

Uma key de grupo nunca alcança unidades fora do seu grupo, e cada movimentação continua atribuída a uma única unidade-alvo. A consolidação é de visão — o isolamento entre grupos permanece a garantia número 1.

Primeiros passos

Em menos de cinco minutos você faz a primeira consulta e a primeira movimentação. Você só precisa de uma API key do seu tenant (fornecida pela Axenya).

  1. Configure o ambiente Exporte a URL base e sua API key. A empresa é resolvida pela key — não precisa de mais nada.
    bash
    export AXENYA_API="https://api.axenya.com/v1"
    export AXENYA_KEY="axk_live_3f8a...e21"   # resolve sua empresa no servidor
  2. Encontre uma vida pelo CPF Toda operação de RH normalmente começa achando a vida. O CPF (document) é a chave natural de matching.
    bash
    curl -sS "$AXENYA_API/beneficiaries?document=39053344705" \
      -H "Authorization: Bearer $AXENYA_KEY"
    json · 200
    {
      "data": [
        {
          "id": "ben_01HZX...",
          "name": "Maria Silva",
          "document": "390.533.447-05",
          "subscriberType": "HOLDER",
          "status": "ACTIVE"
        }
      ],
      "meta": { "totalItems": 1 }
    }
  3. Envie sua primeira movimentação Escritas exigem o header Idempotency-Key e respondem 202 com um recibo. Acompanhe o processamento depois.
    bash
    curl -sS -X POST "$AXENYA_API/movements" \
      -H "Authorization: Bearer $AXENYA_KEY" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: adm-2026-0001-maria" \
      -d '{
        "movementType": "INSERT",
        "effectiveDate": "2026-07-01",
        "policyId": "pol_saude_123",
        "planId": "plan_premium",
        "beneficiary": {
          "subscriberType": "HOLDER",
          "name": "Maria Silva",
          "document": "39053344705",
          "birthDate": "1990-04-12",
          "gender": "FEMALE"
        }
      }'
  4. Acompanhe o recibo Use o submissionId retornado para checar o status — ou receba um webhook quando processar.
    bash
    curl -sS "$AXENYA_API/movements/mov_01J2K..." \
      -H "Authorization: Bearer $AXENYA_KEY"

Autenticação

A autenticação é máquina-a-máquina (M2M) por API keys por tenant. Cada chamada leva o header Authorization: Bearer <sua-key>.

Formato da key

As keys têm prefixo de ambiente e são exibidas uma única vez no momento da criação. Guarde-as em um cofre de segredos (Secret Manager, Vault) — a Axenya armazena apenas o hash.

PrefixoAmbienteUso
axk_live_… Produção Movimentações reais que afetam vidas e apólices.
axk_test_… Teste Integração e validação sem efeitos no cadastro real.

Uma key pode ser de unidade (um único tenant) ou de grupo (várias unidades do grupo, com visão consolidada). O tipo é definido na emissão da key, não no payload.

Scopes

Cada key carrega um conjunto de scopes. Use o princípio do menor privilégio.

ScopePermite
movements:writeSubmeter movimentações de beneficiários.
files:writeEnviar arquivos para a Landing Zone.
submissions:readConsultar vidas, apólices, templates e status de recibos.
Escopos de máquina ≠ perfis de portal

Os scopes acima são permissões máquina-a-máquina da API. Os perfis humanos (médico, RH, analista) e o login via SSO (Entra ID) pertencem ao portal da Axenya e são documentados à parte — não se confundem com os scopes de uma key.

Boas práticas de segurança

  • Rotação sem downtime: até 2 keys ativas por tenant. Crie a nova, migre, revogue a antiga.
  • Revogação imediata e expiresAt por key; lastUsedAt para auditoria.
  • TLS 1.2+ obrigatório; IP allowlist opcional por key.
  • Rate limit e quota aplicados por key.
  • Nunca registre a key em logs, URLs ou repositórios.
Key vazada?

Revogue imediatamente no painel (ou peça à Axenya) e gere uma nova. Como o tenant é vinculado à key, uma key comprometida só afeta a própria empresa — mas revogue mesmo assim.

Modelo de operação de RH

Não existe um endpoint por tarefa de RH. Toda a operação se reduz a 4 primitivas de movimentação, combinadas com consultas (GET) para encontrar a vida e o plano certos.

INSERT

Inclusão

Admissão de titular ou inclusão de dependente em uma apólice.

DELETE

Exclusão

Desligamento de titular ou cancelamento de dependente.

UPDATE

Alteração de plano

Troca de plano/produto de uma vida (de → para).

REGISTRATION_UPDATE

Alteração de cadastro

Endereço, centro de custo e demais campos cadastrais.

A chave de matching é sempre CPF (document) + apólice — sua empresa não conhece o identificador interno (bid) da Axenya, e não precisa. Os campos válidos de cada primitiva vêm do schema gerado daquele movementType.

Multi-benefício num único fluxo

Saúde, odontológico e vida são apólices distintas (policyId) sobre a mesma vida. Não existe API separada por benefício: as 4 primitivas operam qualquer linha de benefício, e uma admissão pode aderir a várias apólices na mesma rotina — uma movimentação por apólice, todas com o mesmo document. A operadora de cada apólice é transparente para você (o schema é o mesmo, provider-agnostic).

Coparticipação e permanência (parâmetros de acordo)

Termos negociados por acordo/convenção entram como parâmetros da movimentação, não exigem endpoint próprio:

  • coparticipation na adesão/troca de plano — define o rateio de custo do beneficiário (ex.: integral, parcial ou percentual).
  • deactivationDelayDays no desligamento — dias de permanência após a data efetiva antes da desativação valer.

Ambos são opcionais e validados pelo schema do movementType.

Os 7 cenários de RH

Estes são os fluxos do dia a dia de um time de benefícios. Cada um é uma combinação das 4 primitivas com as consultas necessárias.

#CenárioPrimitivaConsultas antes
1Admissão + adesãoINSERT (titular)/policies
2Inclusão de dependenteINSERT (dependente)/beneficiaries/dependents
3Alteração de endereçoREGISTRATION_UPDATE/beneficiaries/{id}
4Mudança de centro de custoREGISTRATION_UPDATE/beneficiaries/{id}
5Troca de planoUPDATE/contract-history + /policies
6Cancelamento de dependenteDELETE (dependente)/dependents
7DesligamentoDELETE (titular)/beneficiaries/dependents
1

Admissão com adesão ao plano

INSERT · titular

Cria a vida do titular já com o plano. Consulte /policies antes para obter o policyId e o planId. Para aderir a mais de um benefício (saúde, odonto, vida), repita a movimentação por apólice. coparticipation é opcional.

bash
curl -sS -X POST "$AXENYA_API/movements" \
  -H "Authorization: Bearer $AXENYA_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: adm-2026-0001-maria" \
  -d '{
    "movementType": "INSERT",
    "effectiveDate": "2026-07-01",
    "policyId": "pol_saude_123",
    "planId": "plan_premium",
    "coparticipation": { "mode": "PARCIAL" },
    "beneficiary": {
      "subscriberType": "HOLDER",
      "name": "Maria Silva", "document": "39053344705",
      "enrollmentNumber": "0012345", "birthDate": "1990-04-12",
      "admissionDate": "2026-07-01", "gender": "FEMALE",
      "maritalStatus": "SOLTEIRO", "phone": "+5511999998888"
    }
  }'
2

Inclusão de dependente

INSERT · dependente

Referencia o titular pelo CPF em holder.document e informa o dependencyRelation.

bash
curl -sS -X POST "$AXENYA_API/movements" \
  -H "Authorization: Bearer $AXENYA_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: dep-2026-0001-joao" \
  -d '{
    "movementType": "INSERT",
    "effectiveDate": "2026-07-01",
    "policyId": "pol_saude_123",
    "beneficiary": {
      "subscriberType": "DEPENDENT",
      "holder": { "document": "39053344705" },
      "dependencyRelation": "CONJUGE",
      "name": "João Silva", "document": "12345678909",
      "birthDate": "1989-02-03", "gender": "MALE"
    }
  }'
3

Alteração de endereço

REGISTRATION_UPDATE

Os campos de registration são definidos pelo schema gerado da versão — não é um objeto livre.

bash
curl -sS -X POST "$AXENYA_API/movements" \
  -H "Authorization: Bearer $AXENYA_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: end-2026-0001-maria" \
  -d '{
    "movementType": "REGISTRATION_UPDATE",
    "effectiveDate": "2026-07-01",
    "beneficiary": { "document": "39053344705" },
    "registration": {
      "address": {
        "zipCode": "01310100", "street": "Av. Paulista", "number": "1000",
        "complement": "Conj. 51", "neighborhood": "Bela Vista",
        "city": "São Paulo", "state": "SP"
      }
    }
  }'
4

Mudança de centro de custo

REGISTRATION_UPDATE

Mesmo tipo de movimentação, outro campo de cadastro confirmado pela definição do template.

bash
curl -sS -X POST "$AXENYA_API/movements" \
  -H "Authorization: Bearer $AXENYA_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: cc-2026-0001-maria" \
  -d '{
    "movementType": "REGISTRATION_UPDATE",
    "effectiveDate": "2026-07-01",
    "beneficiary": { "document": "39053344705" },
    "registration": { "costCenter": "CC-OPS-2026" }
  }'
5

Troca de plano

UPDATE

Mapeia 1:1 com UPDATE. Informe fromPlanId e toPlanId.

bash
curl -sS -X POST "$AXENYA_API/movements" \
  -H "Authorization: Bearer $AXENYA_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: plan-2026-0001-maria" \
  -d '{
    "movementType": "UPDATE",
    "effectiveDate": "2026-08-01",
    "policyId": "pol_saude_123",
    "beneficiary": { "document": "39053344705" },
    "fromPlanId": "plan_basic", "toPlanId": "plan_premium"
  }'
6

Cancelamento de dependente

DELETE · dependente

Exclui apenas a vida do dependente. Identifique-o pelo próprio CPF.

bash
curl -sS -X POST "$AXENYA_API/movements" \
  -H "Authorization: Bearer $AXENYA_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: del-dep-2026-0001-joao" \
  -d '{
    "movementType": "DELETE",
    "effectiveDate": "2026-07-31",
    "beneficiary": { "document": "12345678909" },
    "reason": "EXCLUSAO_DEPENDENTE"
  }'
7

Desligamento do titular

DELETE · titular

Use cascadeDependents para excluir também os dependentes vinculados e deactivationDelayDays para honrar a permanência prevista em acordo/convenção (desativar N dias após a data efetiva).

bash
curl -sS -X POST "$AXENYA_API/movements" \
  -H "Authorization: Bearer $AXENYA_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: deslig-2026-0001-maria" \
  -d '{
    "movementType": "DELETE",
    "effectiveDate": "2026-07-31",
    "beneficiary": { "document": "39053344705" },
    "reason": "DESLIGAMENTO",
    "deactivationDelayDays": 30,
    "cascadeDependents": true
  }'
Cascata e permanência pós-desligamento

No desligamento do titular, cascadeDependents: true exclui também os dependentes vinculados na mesma data; false mantém os dependentes ativos. deactivationDelayDays programa a desativação para N dias após a effectiveDate (ex.: 30 = mais 30 dias de cobertura). Sem o campo, a desativação é imediata na data informada.

Sync de folha de pagamento (reconciliação)

Tudo que vimos até aqui é imperativo: você diz a movimentação ("exclua o CPF X"). A folha de pagamento é o oposto — é declarativa. Você envia o retrato de quem deve estar ativo e a Axenya calcula as movimentações pela diferença contra o estado atual. É o mesmo padrão de reconciliação por estado desejado do Kubernetes: você não manda o delta, manda o alvo, e o motor deriva o delta.

Folha (estado desejado)  ─┐
                          ├─► motor de diff ─► plano de reconciliação ─► (aprova) ─► /movements
Estado atual na Axenya   ─┘   (desired vs current)   (preview das mov.)              (pipeline existente)
A folha não cria nada novo

Ela alimenta o mesmo pipeline de movimentações, só que de forma derivada. As 4 primitivas continuam sendo o destino — a folha apenas as calcula para você.

O motor de diff → as 4 primitivas

A diferença entre folha e estado atual (chave = CPF) gera exatamente as primitivas que já existem:

Situação (chave = CPF)Movimentação derivada
Na folha, não existe na AxenyaINSERT (admissão/adesão)
Existe na Axenya, ausente na folhaDELETE (desligamento) ⚠️
Em ambos, plano diferenteUPDATE (troca de plano)
Em ambos, cadastro diferenteREGISTRATION_UPDATE
Em ambos, idênticono-op (não gera nada)

A armadilha crítica: exclusão por omissão

O quadrante perigoso é "ausente na folha → DELETE". Uma folha truncada, um arquivo parcial ou um erro de export poderiam desligar gente em massa. Sem proteção, isso é um incidente. Por isso os controles abaixo são obrigatórios.

Controles de segurança da reconciliação
  • mode: full | partial — o controle mais importante. Em full, a folha é o retrato completo e a omissão significa exclusão; em partial (delta), a omissão não faz nada.
  • Escopo = titulares. Folha lista funcionários, não dependentes. Nunca inferir exclusão de dependente por ausência — senão toda folha sem dependentes zeraria os dependentes.
  • Guardrails por limiar: se as exclusões derivadas passarem de X% da base (ou N absoluto), o plano é bloqueado e exige confirmação explícita.
  • Dry-run obrigatório: sempre gerar o plano (preview) antes de aplicar — ao menos nas primeiras execuções.
  • Idempotência natural: reenviar a mesma folha gera diff vazio (nada acontece).

Quais dos 7 cenários derivam da folha?

Honestidade importante: depende das colunas que a folha carrega.

#CenárioDerivável da folha?
1Admissão + adesão✅ Sim (admissão); adesão só se a folha trouxer o plano
3Alteração de endereço✅ Se a folha trouxer endereço
4Mudança de centro de custo✅ Forte — folha quase sempre tem
5Troca de plano⚠️ Só se a folha trouxer a elegibilidade/plano
7Desligamento✅ Sim (ausência em mode: full ou data explícita)
2Inclusão de dependente❌ Só se for censo com dependentes
6Cancelamento de dependente❌ Idem — e nunca por omissão

Em resumo: a folha resolve muito bem admissão, desligamento, centro de custo e cadastro de titulares; plano e dependentes dependem do conteúdo do arquivo.

Fluxo: preview → apply

Dois passos, pela segurança. Primeiro você envia a folha e revisa o plano derivado; só então aplica.

  1. Abra o sync e envie a folha Mesmo padrão de signed URL — o arquivo não passa pela API.
    bash
    curl -sS -X POST "$AXENYA_API/payroll-syncs:initiate" \
      -H "Authorization: Bearer $AXENYA_KEY" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: folha-2026-07" \
      -d '{
        "referenceMonth": "2026-07",
        "effectiveDate": "2026-07-01",
        "mode": "full",
        "scope": "HOLDERS"
      }'
    # -> { "syncId": "pyr_01J...", "uploadUrl": "https://storage.googleapis.com/...",
    #      "requiredHeaders": { ... } }

    Depois, faça o PUT do arquivo na uploadUrl (como em qualquer fluxo de arquivo).

  2. Consulte o plano derivado (dry-run) Quando status = planned, o sync devolve o plano completo com summary e guardrails.
    bash
    curl -sS "$AXENYA_API/payroll-syncs/pyr_01J..." \
      -H "Authorization: Bearer $AXENYA_KEY"
    json · 200
    {
      "syncId": "pyr_01J...",
      "status": "planned",
      "mode": "full", "scope": "HOLDERS",
      "summary": {
        "inserts": 12, "deletes": 3, "planChanges": 5,
        "registrationUpdates": 8, "noops": 940, "unmatched": 2
      },
      "guardrails": { "deleteRatio": 0.003, "blocked": false },
      "movements": [
        { "movementType": "INSERT", "beneficiary": { "document": "111...", "name": "..." }, "source": { "row": 14 } },
        { "movementType": "DELETE", "beneficiary": { "document": "222...", "name": "..." }, "reason": "ABSENT_IN_PAYROLL" },
        { "movementType": "UPDATE", "beneficiary": { "document": "333..." }, "fromPlanId": "basic", "toPlanId": "premium" }
      ],
      "unmatched": [ { "row": 87, "document": "999...", "issue": "CPF inválido" } ]
    }
  3. Aplique o plano Depois de revisar (ou automaticamente se os guardrails estiverem ok). Cada movimentação vira um submission rastreável.
    bash
    curl -sS -X POST "$AXENYA_API/payroll-syncs/pyr_01J...:apply" \
      -H "Authorization: Bearer $AXENYA_KEY" \
      -H "Content-Type: application/json" \
      -d '{ "confirm": true, "acknowledgeDeletes": 3 }'
    # -> status: applying -> completed

    O campo acknowledgeDeletes precisa bater com o número de exclusões do plano — uma trava extra contra desligamento acidental em massa.

Endpoints

POST /payroll-syncs:initiate Abre um sync e devolve signed URL p/ a folha
GET /payroll-syncs/{id} Plano derivado + summary + guardrails (dry-run)
POST /payroll-syncs/{id}:apply Aplica o plano (confirmação/guardrails) → gera submissions

Como a folha é mapeada

Aqui aparece o único ponto que exige mais do que o template canônico: toda folha/ERP exporta diferente. Duas saídas:

Template canônico de folha

Cliente preenche uma planilha padrão, derivada da mesma máquina de definição dos templates. Mais simples — recomendado para começar.

Perfil de mapeamento por tenant

Colunas nativas do ERP do cliente → canônicas. Melhor DX, mais setup. Fica para uma fase 2.

Classificações que exigem cuidado

  • CPF novo pode ser re-admissão de alguém INACTIVE → reativação, não inclusão nova (checar status atual).
  • CPF ausente pode ser afastamento, não desligamento → por isso mode + limiares.
  • Mesmo CPF com nome diferente → correção cadastral, não pessoa nova.

Recibos & status

Como a ingestão é assíncrona, toda escrita responde 202 Accepted com um objeto submission — o recibo. Guarde o id para acompanhar.

json · 202
{
  "submission": {
    "id": "mov_01J2K...",
    "movementType": "INSERT",
    "schemaVersion": "2026-06-01",
    "status": "received",
    "createdAt": "2026-06-04T13:20:00Z"
  }
}

Ciclo de vida do status

StatusSignificado
receivedRecibo criado, na fila para processar.
validatingValidando contra schema e regras de negócio.
processingBackend aplicando a movimentação.
completedTudo aceito.
partially_completedParte aceita, parte rejeitada (ver result.errors).
rejectedNada aplicado; veja os erros.

Consultar o status

bash
curl -sS "$AXENYA_API/movements/mov_01J2K..." \
  -H "Authorization: Bearer $AXENYA_KEY"
json · 200 (rejeitado)
{
  "id": "mov_01J2K...",
  "status": "rejected",
  "schemaVersion": "2026-06-01",
  "result": {
    "accepted": 0,
    "rejected": 1,
    "errors": [
      {
        "row": 1,
        "field": "beneficiary.document",
        "code": "BENEFICIARY_NOT_FOUND",
        "message": "Nenhuma vida ativa com este CPF na apólice."
      }
    ]
  }
}
Erros no seu vocabulário

O backend valida por coluna/linha (modelo de planilha). Como o transform é determinístico, a camada pública reverte o erro para o campo JSON que você enviou (ex.: cpfbeneficiary.document) antes de devolver.

Webhooks

Em vez de fazer polling no status, registre um endpoint para receber eventos quando uma movimentação for processada. Os webhooks são assinados via HMAC e têm retry com backoff.

EventoQuando dispara
movement.processedMovimentação concluída (total ou parcial).
movement.failedMovimentação rejeitada.
file.validatedArquivo da Landing Zone validado.

Verificando a assinatura

Cada entrega traz um header com a assinatura HMAC-SHA256 do corpo. Recompute com seu segredo de webhook e compare em tempo constante antes de confiar no payload.

bash
# pseudo-verificação
expected=$(printf '%s' "$RAW_BODY" \
  | openssl dgst -sha256 -hmac "$WEBHOOK_SECRET" -binary \
  | base64)
# compare 'expected' com o header X-Axenya-Signature

Convenções

Regras transversais que valem para toda a API.

TemaConvenção
Base URLhttps://api.axenya.com/v1
VersionamentoPrefixo /v1 próprio, independente do versionamento interno.
AutenticaçãoAuthorization: Bearer <key> em toda chamada.
TenantDerivado da key. Nunca no payload.
IdempotênciaHeader Idempotency-Key obrigatório em toda escrita.
ErrosRFC 7807 (application/problem+json) + errors[] por item.
SchemaschemaVersion ecoado no recibo; mudança aditiva não quebra.
AuditoriaToda chamada atribuída a keyId + tenant.

Idempotência

Reenviar uma requisição com a mesma Idempotency-Key retorna o mesmo recibo, sem duplicar a movimentação. Use uma chave estável e única por operação (ex.: adm-2026-0001-maria). Isso torna seus retries seguros.

Consultas (GET)

Endpoints de leitura para encontrar vidas, planos e templates antes de movimentar. Requerem o scope submissions:read.

GET /beneficiaries/{id} Detalhe + cadastro atual
GET /beneficiaries/{id}/dependents Dependentes de um titular
GET /beneficiaries/{id}/contract-history Plano/contrato vigente
GET /policies · /policies/{id} Planos/apólices disponíveis
GET /movement-templates/{movementType} JSON Schema canônico (?format=xlsx gera a planilha)

Movimentações (HR Portal)

Escrita de movimentações de beneficiários. Requer o scope movements:write (exceto a consulta de status).

POST /movements Submete movimentação JSON (async)
POST /movements:initiate Solicita signed URL p/ envio por arquivo
GET /movements/{submissionId} Status/recibo da movimentação

Tipos de movimentação

movementTypeDescrição
INSERTInclusão (titular ou dependente).
DELETEExclusão (titular ou dependente).
UPDATEAlteração de plano.
REGISTRATION_UPDATEAlteração de cadastro.

Alternativa por arquivo

Para volumes grandes, use o fluxo de upload nativo do backend. O template canônico vem do mesmo schema (veja Templates).

  1. Peça a URL de upload
    bash
    curl -sS -X POST "$AXENYA_API/movements:initiate" \
      -H "Authorization: Bearer $AXENYA_KEY" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: file-2026-0001" \
      -d '{
        "movementType": "INSERT",
        "contentType": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
      }'
  2. Envie o arquivo direto ao GCS (não passa pela API)
    bash
    curl -sS -X PUT "<uploadUrl>" \
      -H "Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" \
      -H "x-goog-meta-movementtype: INSERT" \
      --upload-file inclusoes-julho.xlsx
  3. Acompanhe com GET /movements/{submissionId}.

Arquivos (Landing Zone)

Submissão de arquivos de compliance por fileType + período. Requer files:write.

POST /files:initiate Solicita signed URL (fileType + período)
POST /files/{submissionId}:complete Confirma upload concluído
GET /files/{submissionId} Status/validação do arquivo

O fluxo é o mesmo padrão de signed URL: você pede a URL, envia o arquivo direto ao storage e confirma. A validação (incluindo antivírus) acontece de forma assíncrona — acompanhe pelo status ou pelo webhook file.validated.

Templates & schema

O cliente B2B nunca mantém um template à mão. O hr-portal-api expõe a definição estruturada de cada movementType (colunas, tipos, obrigatórios, enums, versão); a camada pública consome e gera o JSON Schema canônico. Coluna nova no backend aparece sozinha no schema — sem drift, sem variante por operadora.

hr-portal-api                       axenya-public-api                       cliente
─────────────                       ─────────────────                       ───────
definição estruturada ─(fetch+cache)─► gera JSON Schema ─(serve)─► GET /movement-templates/{type}
do template (por tipo)                 canônico + versão
                                            │
POST /movements (JSON) ─────────────────────┤ valida o JSON contra o schema
                                            │ transforma JSON → colunas/linhas
       upload existente ◄────────────────────┤ alimenta o fluxo de upload
       valida (autoritativo)                 │
       failed-rows (coluna/linha) ──────────►│ reverte p/ o caminho JSON e devolve no recibo

Uma definição, três usos

A mesma definição alimenta:

  • O JSON Schema da API (validação e DX);
  • O XLSX canônico (?format=xlsx, para o modo arquivo);
  • A planilha em branco da própria UI da Axenya.

Obtendo o schema de um tipo

bash
# JSON Schema canônico
curl -sS "$AXENYA_API/movement-templates/INSERT" \
  -H "Authorization: Bearer $AXENYA_KEY"

# Planilha XLSX equivalente
curl -sS "$AXENYA_API/movement-templates/INSERT?format=xlsx" \
  -H "Authorization: Bearer $AXENYA_KEY" --output insert.xlsx

Definição estruturada (contrato interno)

Exemplo do que o backend devolve por tipo — fonte da verdade de colunas, tipos, obrigatórios e enums:

json
{
  "movementType": "INSERT",
  "version": "2026-06-01",
  "columns": [
    { "key": "cpf",              "type": "string", "required": true,  "pattern": "^\\d{11}$" },
    { "key": "nome",             "type": "string", "required": true },
    { "key": "dataNascimento",   "type": "date",   "required": true },
    { "key": "dataAdmissao",     "type": "date",   "required": false },
    { "key": "sexo",             "type": "enum",   "required": true,  "enum": ["M", "F"] },
    { "key": "tipoBeneficiario", "type": "enum",   "required": true,  "enum": ["TITULAR", "DEPENDENTE"] },
    { "key": "cpfTitular",       "type": "string", "required": false },
    { "key": "grauParentesco",   "type": "enum",   "required": false, "enum": ["CONJUGE", "FILHO", "..."] }
  ]
}

Regras de geração

  • key do backend → camelCase no JSON, com um dicionário enxuto de apelidos (ex.: dataNascimento → birthDate).
  • Agrupamento por convenção: cpf/nome/… → beneficiary.*, cep/rua/… → registration.address.*.
  • required/type/enum/pattern viram restrições do JSON Schema.
  • version propaga para o schema e é ecoada como schemaVersion no recibo.
Versionamento & cache

A camada pública cacheia a definição por version (refetch por TTL ou webhook). Você pode pinar uma versão; mudanças aditivas não quebram, rename/remoção geram nova versão.

Erros

Erros de protocolo seguem RFC 7807 (application/problem+json). Erros por item de uma movimentação vêm em result.errors[] no recibo.

HTTPSignificado
202Escrita aceita — recibo criado (async).
400JSON inválido ou falha de schema.
401API key ausente ou inválida.
403Scope insuficiente para a operação.
404Recurso (submission, vida) não encontrado.
409Conflito de idempotência (mesma key, payload diferente).
422Regra de negócio violada.
429Rate limit/quota da key excedido.
json · problem+json
{
  "type": "https://docs.axenya.com/errors/insufficient-scope",
  "title": "Scope insuficiente",
  "status": 403,
  "detail": "A API key não possui o scope movements:write.",
  "instance": "/v1/movements"
}

Glossário

TermoDefinição
TenantSua empresa. Resolvido a partir da API key, nunca do payload.
Beneficiário / vidaPessoa coberta — titular (HOLDER) ou dependente (DEPENDENT).
MovimentaçãoOperação de RH expressa em uma das 4 primitivas.
SubmissionRecibo de uma escrita assíncrona, com id e status.
Apólice (policy)Contrato com a operadora ao qual a vida é vinculada.
DocumentCPF — a chave natural de matching de uma vida.
Landing ZoneDomínio de envio de arquivos de compliance.
GrupoConjunto de unidades (tenants) com visão consolidada via key de grupo.
UnidadeEmpresa/tenant individual dentro de um grupo. Resolvida pela key ou informada via unitId por uma key de grupo.
CoparticipaçãoRateio de custo do beneficiário no plano (coparticipation).
Permanência pós-desligamentoDias de cobertura após a data efetiva (deactivationDelayDays).
schemaVersionVersão da definição de template ecoada no recibo.