> ## Documentation Index
> Fetch the complete documentation index at: https://docs.judit.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Digital Certificate Registration

> Register an A1 digital certificate (.pfx / .p12) as a credential in the vault. This is the only route that accepts certificate upload.

<Warning>
  The certificate **cannot** be sent through the `POST /credentials` route. Certificate fields inside `custom_data` are rejected with the `CERTIFICATE_FIELDS_NOT_ALLOWED` error.
</Warning>

<ParamField body="file_base64" type="string" required>
  Content of the `.pfx` / `.p12` (PKCS#12) file converted to Base64, on a **single line**, with no breaks. File must be at most 64 KB.
</ParamField>

<ParamField body="password" type="string" required>
  Password of the `.pfx` file. Not the court portal password.
</ParamField>

<ParamField body="system_name" type="string">
  System and court where the certificate will be used, for example `ESAJ - TJSP - 1º grau`. Use `*` to register it as a wildcard credential.
</ParamField>

<ParamField body="customer_key" type="string">
  Credential identifier defined by you. If omitted, the default value `*` is used.
</ParamField>

<ParamField body="custom_data" type="object">
  Extra credential data. Only send it when the court also requires two-factor authentication.

  <Expandable title="properties">
    <ParamField body="secret" type="string">
      2FA secret (`secret`) — the **fixed** setup key of the authenticator app, never the temporary 6-digit code.
    </ParamField>
  </Expandable>
</ParamField>

<RequestExample>
  ```bash cURL theme={null}
  curl --location 'https://crawler.prod.judit.io/credentials/certificate' \
  --header 'api-key: <api-key>' \
  --header 'Content-Type: application/json' \
  --data '{
    "customer_key": "teste",
    "system_name": "ESAJ - TJSP - 1º grau",
    "file_base64": "<pfx-content-in-base64>",
    "password": "123456"
  }'
  ```

  ```bash cURL with 2FA theme={null}
  curl --location 'https://crawler.prod.judit.io/credentials/certificate' \
  --header 'api-key: <api-key>' \
  --header 'Content-Type: application/json' \
  --data '{
    "customer_key": "teste",
    "system_name": "ESAJ - TJSP - 1º grau",
    "file_base64": "<pfx-content-in-base64>",
    "password": "123456",
    "custom_data": {
      "secret": "JBSWY3DPEHPK3PXP"
    }
  }'
  ```
</RequestExample>

<ResponseExample>
  ```json theme={null}
  {
  	"message": "CERTIFICATE_CREATED",
  	"customer_key": "teste",
  	"subject_cn": "HOLDER NAME:12345678909",
  	"not_after": "2027-01-01T00:00:00.000Z",
  	"uploaded_at": "2026-07-31T17:00:00.000Z"
  }
  ```
</ResponseExample>

**If a certificate for the same holder already exists in that credential, the message will be `CERTIFICATE_UPDATED` and the previous certificate is discarded.**

<Accordion title="Possible errors">
  | Code                          | HTTP | When it happens                                                                                      |
  | :---------------------------- | :--- | :--------------------------------------------------------------------------------------------------- |
  | `PFX_MALFORMED`               | 400  | Invalid Base64 or corrupted PFX file                                                                 |
  | `PFX_PASSWORD_INVALID`        | 400  | Wrong file password                                                                                  |
  | `PFX_NO_PRIVATE_KEY`          | 400  | File has no private key                                                                              |
  | `PFX_NO_CERTIFICATE`          | 400  | File has no certificate                                                                              |
  | `PFX_EXPIRED`                 | 400  | Certificate expired                                                                                  |
  | `PFX_NOT_YET_VALID`           | 400  | Certificate not valid yet                                                                            |
  | `PFX_TOO_LARGE`               | 400  | File larger than 64 KB                                                                               |
  | `CERTIFICATE_HOLDER_MISMATCH` | 409  | New certificate belongs to a different holder (CPF/CN)                                               |
  | `CREDENTIAL_TYPE_CONFLICT`    | 409  | A username/password credential already exists for the same credential and `customer_key` combination |
</Accordion>

Full guide, including converting the file to Base64 and the Postman walkthrough: [Credentials Vault — digital certificate](/en/essentials/cofre-de-credenciais#registering-a-credential-with-a-digital-certificate-a1).


## OpenAPI

````yaml openapi/vault.json POST /credentials/certificate
openapi: 3.0.3
info:
  title: JUDIT - Credentials Vault API
  description: >-
    OpenAPI description for the credentials vault routes, used to register and
    inspect per-tribunal system credentials. Mirrored locally so this page's
    playground exposes exactly one base URL (no other Judit service host).
    Transcribed from the fields already documented on the vault/vault and
    vault/vaultcreate pages.
  version: 1.0.0
servers:
  - url: https://crawler.prod.judit.io
    description: Production server
security:
  - ApiKeyAuth: []
tags:
  - name: Credentials
    description: Register and inspect tribunal system credentials stored in the vault
paths:
  /credentials/certificate:
    post:
      tags:
        - Credentials
      summary: Register or update a digital certificate credential
      description: >-
        Uploads an A1 digital certificate (PKCS#12 `.pfx` / `.p12`, max 64 KB)
        as a credential in the vault. This is the only route that accepts
        certificate upload — sending certificate fields to `POST /credentials`
        returns `CERTIFICATE_FIELDS_NOT_ALLOWED`. When the court also requires
        two-factor authentication, send the 2FA setup key in
        `custom_data.secret` in this same payload.
      operationId: postCredentialsCertificate
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - file_base64
                - password
              properties:
                file_base64:
                  type: string
                  description: PFX/P12 file content encoded as a single-line Base64 string
                password:
                  type: string
                  description: Password of the PKCS#12 file (not the court portal password)
                system_name:
                  type: string
                  description: e.g. "ESAJ - TJSP - 1º grau" or `*` (wildcard)
                customer_key:
                  type: string
                  description: >-
                    Client-defined identifier for the credential. Defaults to
                    `*`
                custom_data:
                  type: object
                  description: >-
                    Extra credential data. Only required when the court also
                    enforces two-factor authentication.
                  properties:
                    secret:
                      type: string
                      description: >-
                        2FA secret — the fixed authenticator setup key, never
                        the temporary 6-digit code
            example:
              customer_key: teste
              system_name: ESAJ - TJSP - 1º grau
              file_base64: MIIK...
              password: '123456'
              custom_data:
                secret: JBSWY3DPEHPK3PXP
      responses:
        '200':
          description: Certificate created or updated
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    enum:
                      - CERTIFICATE_CREATED
                      - CERTIFICATE_UPDATED
                  customer_key:
                    type: string
                  subject_cn:
                    type: string
                    description: Certificate holder (CN)
                  not_after:
                    type: string
                    format: date-time
                    description: Certificate expiration date
                  uploaded_at:
                    type: string
                    format: date-time
              example:
                message: CERTIFICATE_CREATED
                customer_key: teste
                subject_cn: NOME DO TITULAR:12345678909
                not_after: '2027-01-01T00:00:00.000Z'
                uploaded_at: '2026-07-31T17:00:00.000Z'
        '400':
          description: >-
            Invalid certificate file. Possible codes: `PFX_MALFORMED`,
            `PFX_PASSWORD_INVALID`, `PFX_NO_PRIVATE_KEY`, `PFX_NO_CERTIFICATE`,
            `PFX_EXPIRED`, `PFX_NOT_YET_VALID`, `PFX_TOO_LARGE`
        '409':
          description: >-
            Conflict. Possible codes: `CERTIFICATE_HOLDER_MISMATCH`,
            `CREDENTIAL_TYPE_CONFLICT`
components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: api-key
      description: API key for authentication

````