> ## Documentation Index
> Fetch the complete documentation index at: https://docs-platform.services-valid.com.br/llms.txt
> Use this file to discover all available pages before exploring further.

# Preparar assinatura com certificado local

> Prepara a assinatura com um certificado A1/A3 no computador, obtendo um token para o plugin Web PKI.

Prepara a assinatura com um certificado local (A1 ou A3), obtendo um token que o plugin Web PKI do navegador usa para assinar diretamente. A chave privada **nunca sai do computador do signatário**.

**Autenticação**: use apenas o `sessionToken` na URL — nenhum header de autenticação é necessário.

## Parâmetros

<ParamField path="sessionToken" type="string" required>
  Token único da sessão do signatário.
</ParamField>

<ParamField body="certificate" type="string" required>
  Certificado em formato Base64 (DER ou PEM), lido pelo plugin Web PKI no navegador do signatário.
</ParamField>

<ParamField body="fileUuid" type="string" optional>
  UUID do arquivo a assinar (obtido em [`GET /signer/v1/sign/:sessionToken`](/plataforma/assinatura-digital/api/get-sign-session)). Se omitido, usa o primeiro arquivo do envelope.
</ParamField>

## Respostas

<ResponseField name="token" type="string">
  Token opaco usado pelo plugin Web PKI para `pki.signWithRestPki({ token, thumbprint })`. O plugin envia este token ao RestPKI junto com a assinatura realizada localmente.
</ResponseField>

<ResponseField name="certificateHolder" type="string">
  Nome do titular do certificado.
</ResponseField>

<ResponseField name="certificateIdentifier" type="string">
  CPF ou CNPJ do titular, só dígitos.
</ResponseField>

<ResponseField name="expiresAt" type="string">
  Timestamp (ISO 8601) de quando o preparo expira. O signatário precisa assinar antes desse momento.
</ResponseField>

## Erros

Veja [Autenticação e erros](/plataforma/assinatura-digital/api/erros-e-autenticacao).

* **400**: Certificado ilegível ou em formato inválido.
* **403**: Certificado não pertence ao signatário (quando o envelope restringe a assinatura).
* **409**: Não é a vez do signatário, ou já assinou este arquivo. Ou preparo anterior ainda ativo.
* **410**: Session token expirado.
* **502**: RestPKI recusou o preparo da assinatura.

<ResponseExample>
  ```json theme={"theme":"catppuccin-latte"}
  HTTP/1.1 200 OK
  Content-Type: application/json

  {
    "token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
    "certificateHolder": "Maria da Silva Santos",
    "certificateIdentifier": "98765432109",
    "expiresAt": "2025-07-27T15:30:00Z"
  }
  ```

  ```json theme={"theme":"catppuccin-latte"}
  HTTP/1.1 403 Forbidden
  Content-Type: application/json

  {
    "statusCode": 403,
    "message": "Certificate does not belong to signer"
  }
  ```

  ```json theme={"theme":"catppuccin-latte"}
  HTTP/1.1 409 Conflict
  Content-Type: application/json

  {
    "statusCode": 409,
    "message": "Not signer's turn or already signed"
  }
  ```

  ```json theme={"theme":"catppuccin-latte"}
  HTTP/1.1 410 Gone
  Content-Type: application/json

  {
    "statusCode": 410,
    "message": "Session expired"
  }
  ```
</ResponseExample>

## Exemplo

```bash theme={"theme":"catppuccin-latte"}
curl -X POST "https://api.valid.com/signer/v1/sign/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.../web-pki/start" \
  -H "Content-Type: application/json" \
  -d '{
    "certificate": "MIIDXTCCAkWgAwIBAgIIODUXcDrNpwkwDQYJ...",
    "fileUuid": "6ba7b811-9dad-11d1-80b4-00c04fd430c8"
  }'
```

## Fluxo completo

1. Obtenha as configurações: [`GET .../web-pki/settings`](/plataforma/assinatura-digital/api/get-web-pki-settings)
2. Inicialize o plugin no navegador: `pki.init({ license })`
3. Liste certificados do computador: `pki.listCertificates()`
4. Deixe o signatário escolher um certificado
5. Leia o certificado: `pki.readCertificate(thumbprint)` → recebe Base64
6. **Prepare a assinatura** (esta chamada): envia o certificado, recebe `token`
7. Assine no navegador: `pki.signWithRestPki({ token, thumbprint })` → o plugin assina e envia ao RestPKI
8. Finalize no backend: [`POST /signer/v1/sign/:sessionToken/sign`](/plataforma/assinatura-digital/api/post-sign)

## Importante

* **Sem rota de "finish"**: o fechamento da assinatura é o `POST /signer/v1/sign` comum — o sistema detecta automaticamente que há um preparo Web PKI aberto e usa o token do preparo.
* **Certificado local**: a chave privada nunca sai do computador — o plugin assina localmente e só envia a assinatura resultado para o RestPKI.
* **A1 e A3**: ambos são aceitos (A1 instalado no SO, A3 em token/smartcard). Ambos têm o mesmo valor jurídico como assinatura qualificada ICP-Brasil.
* **Titularidade**: se o envelope restringe a assinatura (`restrictSigner: true`), o CPF/CNPJ do certificado deve ser o do signatário — validação ocorre nesta chamada.
* **Validade**: o certificado é validado duas vezes — no preparo (agora) e no fechamento (porque meia-noite do último dia válido pode passar entre uma e outra).

## Relacionado

* [`GET .../web-pki/settings`](/plataforma/assinatura-digital/api/get-web-pki-settings) — obter licença e URL do RestPKI
* [`GET /signer/v1/sign/:sessionToken`](/plataforma/assinatura-digital/api/get-sign-session) — obter dados da sessão e arquivos
* [`POST /signer/v1/sign/:sessionToken/sign`](/plataforma/assinatura-digital/api/post-sign) — finalizar a assinatura
* [`GET /signer/v1/sign/:sessionToken/integraicp/clearances`](/plataforma/assinatura-digital/api/get-integraicp-clearances) — alternativa: certificado em nuvem


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.