Endpoints da API ================ Esta seção detalha os endpoints principais da API Rubrix, organizados por módulo. .. contents:: Nesta página :local: :depth: 2 Autenticação ============ .. _login: Login ----- .. http:post:: /auth/login Autentica um usuário e retorna um token JWT. **Corpo da Requisição (JSON):** .. list-table:: :header-rows: 1 :widths: 20 15 10 55 * - Campo - Tipo - Obrigatório - Descrição * - ``email`` - string - Sim - E-mail do usuário. * - ``password`` - string - Sim - Senha do usuário. * - ``tenant_id`` - uuid - Não - ID do tenant. Necessário se o usuário pertence a mais de um tenant. **Exemplo de Request:** .. code-block:: json { "email": "usuario@empresa.com", "password": "minha-senha" } **Respostas:** - ``200 OK`` — Token JWT retornado com sucesso. O campo ``expires_in`` indica o tempo de expiração em segundos. - ``400 Bad Request`` — Credenciais inválidas. .. _me: Informações do Usuário Autenticado ----------------------------------- .. http:get:: /auth/me Retorna informações do usuário autenticado e a lista de tenants aos quais pertence. **Autenticação:** Bearer Token ou API Key. **Respostas:** - ``200 OK`` — Dados do usuário retornados. .. _switch-tenant: Trocar Tenant Ativo -------------------- .. http:post:: /auth/switch-tenant Troca o tenant ativo e retorna um novo JWT vinculado ao tenant selecionado. **Autenticação:** Bearer Token ou API Key. **Corpo da Requisição (JSON):** .. list-table:: :header-rows: 1 :widths: 20 15 10 55 * - Campo - Tipo - Obrigatório - Descrição * - ``tenant_id`` - uuid - Sim - ID do tenant para o qual deseja trocar. **Exemplo de Request:** .. code-block:: json { "tenant_id": "27192214-56d9-46f0-96f4-868c49b8cf4e" } **Respostas:** - ``200 OK`` — Novo JWT retornado. - ``400 Bad Request`` — Tenant inválido ou sem acesso. API Keys ======== .. _create-api-key: Criar API Key -------------- .. http:post:: /api-keys Cria uma nova API Key para o tenant autenticado. API Keys são ideais para integrações de aplicação. **Autenticação:** Bearer Token ou API Key. **Corpo da Requisição (JSON):** .. list-table:: :header-rows: 1 :widths: 20 15 10 55 * - Campo - Tipo - Obrigatório - Descrição * - ``name`` - string - Sim - Nome identificador da API Key. * - ``expires_at`` - datetime - Não - Data de expiração (formato ISO 8601). Se omitido, a chave não expira. **Exemplo de Request:** .. code-block:: json { "name": "integracao-erp", "expires_at": "2027-12-31T23:59:59Z" } **Respostas:** - ``200 OK`` — API Key criada. O valor da chave é retornado apenas nesta resposta. - ``400 Bad Request`` — Dados inválidos. .. warning:: Guarde o valor da API Key retornado. Ele **não será exibido novamente**. Listar API Keys ---------------- .. http:get:: /api-keys Lista todas as API Keys do tenant autenticado. **Autenticação:** Bearer Token ou API Key. **Respostas:** - ``200 OK`` — Lista de API Keys. Revogar API Key ---------------- .. http:delete:: /api-keys/{id} Revoga uma API Key existente. **Autenticação:** Bearer Token ou API Key. **Parâmetros de Path:** - ``id`` (uuid, obrigatório) — ID da API Key a ser revogada. **Respostas:** - ``200 OK`` — API Key revogada. Fluxo de Assinatura (Flow) =========================== .. _flow-init: Iniciar Fluxo -------------- .. http:post:: /flow/init Inicia um novo fluxo de assinatura. O documento (PDF) deve ser enviado codificado em Base64. A API realiza o upload seguro para o storage, persiste a estrutura do fluxo e dispara automaticamente o convite por e-mail para os signatários do primeiro pool. **Autenticação:** Bearer Token ou API Key. **Corpo da Requisição (JSON):** .. list-table:: :header-rows: 1 :widths: 20 15 10 55 * - Campo - Tipo - Obrigatório - Descrição * - ``file_name`` - string - Sim - Nome do arquivo (ex: ``contrato.pdf``). * - ``document`` - string - Sim - Conteúdo do arquivo codificado em **Base64**. * - ``webhook`` - string - Sim - URL para callback de finalização. Ao concluir todas as assinaturas, a API envia o documento final via POST para esta URL. * - ``pools`` - array - Sim - Lista de pools de signatários (mínimo 1). Veja a estrutura abaixo. **Estrutura de um Pool:** .. list-table:: :header-rows: 1 :widths: 20 15 10 55 * - Campo - Tipo - Obrigatório - Descrição * - ``priority`` - integer - Não - Ordem de assinatura. Pools com menor valor assinam primeiro. Pools com mesmo ``priority`` assinam em paralelo. * - ``quorum_required`` - integer - Não - Número mínimo de assinaturas necessárias neste pool. Se omitido, todos devem assinar. * - ``alias`` - string - Não - Nome descritivo para o pool (ex: ``"Jurídico"``). * - ``config`` - object - Não - Restrições de assinatura aplicadas a todo o pool. Veja :ref:`signature-config`. * - ``signers`` - array - Sim - Lista de signatários do pool (mínimo 1). **Estrutura de um Signer:** .. list-table:: :header-rows: 1 :widths: 20 15 10 55 * - Campo - Tipo - Obrigatório - Descrição * - ``email`` - string - Sim - E-mail para notificação do signatário. * - ``document`` - string - Sim - CPF ou CNPJ do signatário. * - ``phone`` - string - Não - Telefone do signatário. * - ``config`` - object - Não - Restrições de assinatura específicas deste signatário. Sobrescreve o ``config`` do pool. Veja :ref:`signature-config`. .. _signature-config: **Estrutura de SignatureConfig:** .. list-table:: :header-rows: 1 :widths: 25 15 60 * - Campo - Tipo - Descrição * - ``allowed_signatures`` - array - Tipos de assinatura permitidos: ``QUALIFIED``, ``ADVANCED``, ``SIMPLE``. * - ``allowed_profile_types`` - array - Perfis de política permitidos: ``B-B``, ``B-T``, ``B-LT``, ``B-LTA``. * - ``allowed_providers`` - array - Provedores permitidos: ``INTEGRAICP``, ``PIXSIGN``, ``GOLDID``, ``SAFEWEB``, ``SERPRO``. **Exemplo de Request:** .. code-block:: json { "file_name": "contrato_servicos.pdf", "document": "JVBERi0xLjQK...", "webhook": "https://api.suaempresa.com/callback", "pools": [ { "alias": "Jurídico", "priority": 1, "signers": [ { "email": "advogado@empresa.com", "document": "12345678900" } ] }, { "alias": "Diretoria", "priority": 2, "signers": [ { "email": "diretor@empresa.com", "document": "98765432100" } ] } ] } **Resposta (201 Created):** .. code-block:: json { "flowId": "550e8400-e29b-41d4-a716-446655440000", "status": "WAITING", "currentSigners": [ { "document": "12345678900", "email": "advogado@empresa.com", "signUrl": "https://rubrix.lat/sign/..." } ] } **Códigos de Erro:** - ``400 Bad Request`` — PDF corrompido, Base64 inválido ou dados faltando. - ``500 Internal Server Error`` — Falha ao persistir dados ou salvar no storage. - ``502 Bad Gateway`` — Falha no serviço de e-mail. .. _flow-status: Consultar Status do Fluxo -------------------------- .. http:get:: /flow/status/{flow_id} Retorna o estado atual do fluxo, os documentos dos signatários pendentes e uma URL temporária para visualização do arquivo. **Autenticação:** Bearer Token ou API Key. **Parâmetros de Path:** - ``flow_id`` (uuid, obrigatório) — Identificador do fluxo. **Resposta (200 OK):** .. code-block:: json { "flow_id": "550e8400-e29b-41d4-a716-446655440000", "status": "WAITING", "current_signers": ["12345678900"], "document": "https://s3.rubrix.local/temp-url..." } .. list-table:: :header-rows: 1 :widths: 20 15 65 * - Campo - Tipo - Descrição * - ``flow_id`` - string - Identificador do fluxo. * - ``status`` - string - Status atual: ``CREATED``, ``WAITING`` ou ``SIGNED``. * - ``current_signers`` - array - CPF/CNPJ dos signatários do pool atual (quando ``status`` é ``WAITING``). * - ``document`` - string - URL temporária para download/visualização do documento. **Códigos de Erro:** - ``404 Not Found`` — Fluxo não encontrado. - ``500 Internal Server Error`` — Erro interno. .. _flow-sign: Assinar no Fluxo ----------------- .. http:post:: /flow/sign Aplica a assinatura de um participante em um fluxo ativo. **Autenticação:** Bearer Token ou API Key. **Corpo da Requisição (JSON):** .. list-table:: :header-rows: 1 :widths: 20 15 10 55 * - Campo - Tipo - Obrigatório - Descrição * - ``flowId`` - uuid - Sim - ID do fluxo. * - ``sessionId`` - string - Sim - ID da sessão obtida após autenticação no provedor. * - ``stampData`` - object - Sim - Posicionamento visual da assinatura (somente PDF). * - ``policyProfile`` - string - Não - Perfil da assinatura: ``B-B``, ``B-T``, ``B-LT`` ou ``B-LTA``. * - ``xmlXpath`` - string - Não - XPath para posicionamento em documentos XML. **Estrutura de StampData:** .. list-table:: :header-rows: 1 :widths: 20 15 65 * - Campo - Tipo - Descrição * - ``pageNumber`` - integer - Número da página (deve ser > 0). * - ``x`` - float - Coordenada X do posicionamento (>= 0). * - ``y`` - float - Coordenada Y do posicionamento (>= 0). **Exemplo de Request:** .. code-block:: json { "flowId": "550e8400-e29b-41d4-a716-446655440000", "sessionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "stampData": { "pageNumber": 1, "x": 100.0, "y": 700.0 }, "policyProfile": "B-T" } **Respostas:** - ``200 OK`` — Documento assinado retornado como ``application/octet-stream``. - ``400 Bad Request`` — Dados inválidos. Webhook de Finalização ----------------------- Quando todas as assinaturas de um fluxo são concluídas, a API envia automaticamente um ``POST`` para a URL de webhook configurada no ``/flow/init``. .. list-table:: :header-rows: 1 :widths: 25 75 * - Detalhe - Descrição * - **Método** - ``POST`` * - **Content-Type** - ``application/pdf`` ou ``application/xml`` * - **Header** - ``X-Flow-Id: {flowId}`` * - **Body** - Binário do arquivo assinado. Assinatura Direta (Sign) ========================= Módulo para assinaturas imediatas sem a necessidade de criar um fluxo persistente. O processo é baseado em **sessões**: ao inicializar os provedores, uma sessão é criada e deve ser autorizada antes de permitir a assinatura. .. note:: Atualmente, os endpoints deste módulo **não exigem autenticação**. Apenas documentos do tipo **CPF** e **CNPJ** com país **BR** são aceitos. .. _provider-init: Inicializar Provedores (Discovery) ----------------------------------- .. http:post:: /provider/init Descobre quais identidades digitais estão disponíveis para o CPF ou CNPJ informado. Este endpoint inicia uma **sessão de assinatura** para cada identidade encontrada. **Corpo da Requisição (JSON):** .. list-table:: :header-rows: 1 :widths: 20 15 10 55 * - Campo - Tipo - Obrigatório - Descrição * - ``documents`` - array - Sim - Lista de documentos para consulta (mínimo 1). * - ``additionalInfo`` - object - Não - Informações adicionais (chave-valor) para o provedor. **Estrutura de cada documento:** .. list-table:: :header-rows: 1 :widths: 20 15 10 55 * - Campo - Tipo - Obrigatório - Descrição * - ``type`` - string - Sim - Tipo do documento: ``CPF`` ou ``CNPJ``. * - ``number`` - string - Não - Número do documento (somente dígitos). * - ``country`` - string - Sim - País. Atualmente apenas ``BR`` é aceito. **Exemplo de Request:** .. code-block:: json { "documents": [ { "type": "CPF", "number": "12345678900", "country": "BR" } ] } **Resposta (200 OK):** .. code-block:: json { "identities": [ { "sessionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "country": "BR", "identityId": "cert-123", "productName": "Certificado A1", "providerName": "INTEGRAICP", "identityEndpoint": "https://provider.example.com/auth?session=...", "identityType": "QUALIFIED" }, { "sessionId": "f9e8d7c6-b5a4-3210-fedc-ba0987654321", "country": "BR", "identityId": "pix-456", "productName": "Assinatura via Pix", "providerName": "PIXSIGN", "identityEndpoint": "https://provider.example.com/pix?session=...", "identityType": "ADVANCED" } ] } **Campos da identidade retornada:** .. list-table:: :header-rows: 1 :widths: 20 15 65 * - Campo - Tipo - Descrição * - ``sessionId`` - string - Identificador da sessão de assinatura. Será utilizado em todos os passos seguintes. * - ``country`` - string - País do documento. * - ``identityId`` - string - Identificador da identidade no provedor. * - ``productName`` - string - Nome do produto do provedor. * - ``providerName`` - string - Nome do provedor (``INTEGRAICP``, ``PIXSIGN``, ``GOLDID``, ``SAFEWEB``, ``SERPRO``). * - ``identityEndpoint`` - string - URL para iniciar a autorização OAuth no provedor. O usuário deve ser redirecionado para esta URL. * - ``identityType`` - string - Tipo da assinatura: ``QUALIFIED``, ``ADVANCED``, ``SIMPLE``. **Códigos de Erro:** - ``204 No Content`` — Nenhuma identidade disponível para os documentos informados. - ``400 Bad Request`` — Dados inválidos. - ``500 Internal Server Error`` — Erro interno. **Próximo passo:** O usuário escolhe uma identidade e realiza a autorização: - **OAuth:** Redireciona o usuário para o ``identityEndpoint``. Após a autorização no provedor, a sessão é marcada como pronta. - **Pix:** Utiliza os endpoints ``GET /pix/init/{sessionId}`` e ``GET /pix/copiaCola/{sessionId}`` para gerar e exibir a cobrança. Após o pagamento, a sessão é marcada como pronta. .. _sign-ready: Verificar Status da Sessão ---------------------------- .. http:get:: /sign/ready?sessionId={id} Verifica se a sessão de assinatura está pronta. A sessão será ``ready: true`` somente após a conclusão bem-sucedida da autorização (OAuth ou pagamento Pix). Ideal para **polling** antes de chamar o endpoint de assinatura. **Parâmetros de Query:** - ``sessionId`` (string, obrigatório) — ID da sessão retornado pelo ``/provider/init``. **Resposta (200 OK):** .. code-block:: json { "ready": true } - ``ready: false`` — A autorização ainda não foi concluída. Continue o polling. - ``ready: true`` — A sessão está pronta. Prossiga para ``POST /sign``. **Códigos de Erro:** - ``400 Bad Request`` — Parâmetros inválidos. - ``404 Not Found`` — Sessão não encontrada. .. _sign: Assinar Documento ------------------ .. http:post:: /sign Recebe o documento, o ``sessionId`` e os dados de posicionamento via ``multipart/form-data``, aplica a assinatura e devolve o arquivo assinado. .. important:: Este endpoint só pode ser chamado quando a sessão estiver com ``ready: true`` (verificado via ``GET /sign/ready``). **Campos do Multipart Form:** .. list-table:: :header-rows: 1 :widths: 20 15 10 55 * - Campo - Tipo - Obrigatório - Descrição * - ``file`` - binary - Sim - Arquivo binário (PDF ou XML). * - ``sessionId`` - string - Sim - ID da sessão autorizada (obtido via ``/provider/init``). * - ``stampData`` - JSON - Não - Dados de posicionamento visual (``pageNumber``, ``x``, ``y``). Aplicável apenas a PDFs. * - ``policyProfile`` - string - Não - Perfil de assinatura desejado: ``B-B``, ``B-T``, ``B-LT``, ``B-LTA``. * - ``xmlXpath`` - string - Não - XPath para posicionamento em documentos XML. **Respostas:** - ``200 OK`` — Documento assinado retornado como binário (``application/pdf`` ou ``application/xml``). - ``400 Bad Request`` — Requisição inválida ou sessão não está pronta. - ``404 Not Found`` — Sessão não encontrada. - ``500 Internal Server Error`` — Erro interno. Autorização via Pix -------------------- Quando o usuário escolhe uma identidade do provedor **PIXSIGN**, a autorização é feita através do pagamento de uma cobrança Pix. Ao confirmar o pagamento, o certificado efêmero é emitido automaticamente e a sessão é marcada como pronta. .. _pix-init: **Gerar Cobrança Pix:** .. http:get:: /pix/init/{session_id} Gera uma cobrança Pix vinculada à sessão de assinatura. **Parâmetros de Path:** - ``session_id`` (string, obrigatório) — ID da sessão obtido em ``/provider/init``. **Parâmetros de Query:** - ``isPqc`` (boolean, opcional, padrão ``false``) — Se ``true``, emite certificado com algoritmo pós-quântico (PQC). **Respostas:** - ``200 OK`` — Cobrança Pix gerada. .. _pix-copiacola: **Obter Código Copia e Cola:** .. http:get:: /pix/copiaCola/{session_id} Retorna a string do Pix Copia e Cola para ser exibida ao usuário. **Parâmetros de Path:** - ``session_id`` (string, obrigatório) — ID da sessão. **Respostas:** - ``200 OK`` — String Pix Copia e Cola retornada. **Fluxo completo da autorização via Pix:** 1. Chame ``GET /pix/init/{sessionId}`` para gerar a cobrança. 2. Chame ``GET /pix/copiaCola/{sessionId}`` para obter o código e exibi-lo ao usuário. 3. O usuário efetua o pagamento Pix. 4. Monitore ``GET /sign/ready?sessionId={id}`` até receber ``ready: true``. 5. Chame ``POST /sign`` com o ``sessionId`` e o documento. Verificação (Verify) ===================== .. _verify: Verificar Assinaturas ---------------------- .. http:post:: /verify Valida as assinaturas presentes em um documento PDF ou XML. Ideal para auditoria e conformidade. **Request:** Arquivo binário via ``multipart/form-data`` no campo ``file``. **Resposta (200 OK):** .. code-block:: json { "document": { "filename": "contrato_assinado.pdf", "hash": "abc123def456...", "mimeType": "application/pdf" }, "signatures": [ { "status": "APPROVED", "policy": "PAdES", "policyType": "B-T", "signer": { "name": "João Silva", "document": "12345678900", "country": "BR" }, "authority": { "providerName": "INTEGRAICP", "authorityName": "AC VALID" }, "isPqc": false } ] } **Campos da Resposta:** .. list-table:: :header-rows: 1 :widths: 20 15 65 * - Campo - Tipo - Descrição * - ``document`` - object - Metadados do documento (nome, hash SHA, MIME type). * - ``signatures`` - array - Lista de assinaturas encontradas. * - ``signatures[].status`` - string - Resultado: ``APPROVED`` ou ``REJECTED``. * - ``signatures[].policy`` - string - Política aplicada: ``PDF``, ``PAdES``, ``XML``, ``XAdES``. * - ``signatures[].policyType`` - string - Tipo de política: ``B-B``, ``B-T``, ``B-LT``, ``B-LTA``. * - ``signatures[].signer`` - object - Dados do signatário (nome, documento, país). * - ``signatures[].authority`` - object - Dados da autoridade certificadora. * - ``signatures[].isPqc`` - boolean - ``true`` se a assinatura usa algoritmo pós-quântico (PQC — ML-DSA). **Códigos de Erro:** - ``400 Bad Request`` — Requisição inválida. - ``500 Internal Server Error`` — Erro interno. Erros Padronizados ================== Todas as respostas de erro seguem a estrutura abaixo: .. code-block:: json { "code": "INVALID_DOCUMENT", "message": "O documento enviado está corrompido ou não é um PDF válido.", "details": [ { "field": "document", "reason": "Base64 inválido" } ] } .. list-table:: :header-rows: 1 :widths: 20 15 65 * - Campo - Tipo - Descrição * - ``code`` - string - Código do erro para tratamento programático. * - ``message`` - string - Mensagem legível sobre o erro. * - ``details`` - array - Lista de detalhes adicionais (campo e motivo específicos).