API + Connector JS

Complete PDF and XML signing documentation

Official 4signer integration standard. API requests/responses use snake_case and Connector JS uses camelCase. This page covers authentication, Desktop Agent, PDF/XML signing flows, parameters, and production-ready examples.

Authentication

Every API call requires your account token in the Authorization header using the Bearer format.

Where to get your account token

  1. Access the 4signer dashboard with an administrator user.
  2. Open API Access.
  3. Create or copy the account token.
  4. Use on backend when applicable or in Connector JS for client-side signing flows, always with account/environment scope control.
Header Required Description
Authorization Yes Bearer ACCOUNT_TOKEN
Accept Yes application/json
X-Account-Slug Optional Use when your operation requires explicit account context.
Authorization: Bearer TOKEN_DA_ACCOUNT
Accept: application/json
X-Account-Slug: optional-account

Security: treat the token as a secret, store it in environment variables, and rotate immediately if exposed.

Desktop Agent

The Desktop Agent is installed on the signer's machine. It connects to local certificates (A3 token/card and OS certificate stores), performs signing on the local device and returns only cryptographic proof to the API to finalize PDF/XML.

Agent UI preview

4signer Desktop Agent

● ONLINE Local API: http://127.0.0.1:9876

certificates: A3 Token SafeNet (2 encontrados)

provider: pkcs11 / windows_store

last_action: XML diploma signing completed

  1. Frontend calls Connector with certificateMode: 'local'.
  2. Connector creates an API session and requests local bootstrap.
  3. Agent signs locally and returns proof to the API.
  4. API finalizes status and makes the signed file available.

PDF

Endpoint base: POST /api/v1/signatures/pdf

Field Required Description
signature_methodYesremote_provider | local_pfx | stored_a1
processing_modeYesremote_provider=async, local_pfx/stored_a1=sync
pdfYesPDF file
providerCloudProvider for cloud signing
pfx + pfx_passwordlocal_pfxA1 certificate file
request_optionsOptionalAdditional signing options (array)

For provider=vidaas, send request_options[vidaas][login_hint] and choose the mode with request_options[vidaas][auth_mode]: push (default) or qrcode.

For provider=birdid, choose the mode using request_options[birdid][auth_mode]: authorization_code (default) or push.

curl -X POST "https://4signer.com/api/v1/signatures/pdf" \
  -H "Authorization: Bearer ACCOUNT_TOKEN" \
  -H "Accept: application/json" \
  -F "signature_method=remote_provider" \
  -F "provider=vidaas" \
  -F "processing_mode=async" \
  -F "pdf=@/tmp/document.pdf" \
  -F "request_options[vidaas][auth_mode]=push" \
  -F "request_options[vidaas][login_hint]=12345678901"
curl -X POST "https://4signer.com/api/v1/signatures/pdf" \
  -H "Authorization: Bearer ACCOUNT_TOKEN" \
  -H "Accept: application/json" \
  -F "signature_method=remote_provider" \
  -F "provider=vidaas" \
  -F "processing_mode=async" \
  -F "pdf=@/tmp/document.pdf" \
  -F "request_options[vidaas][auth_mode]=qrcode" \
  -F "request_options[vidaas][login_hint]=12345678901"
curl -X POST "https://4signer.com/api/v1/signatures/pdf" \
  -H "Authorization: Bearer ACCOUNT_TOKEN" \
  -H "Accept: application/json" \
  -F "signature_method=remote_provider" \
  -F "provider=birdid" \
  -F "processing_mode=async" \
  -F "pdf=@/tmp/document.pdf" \
  -F "request_options[birdid][auth_mode]=authorization_code"
import { createSignerConnector } from '@4signer/signer-connector-sdk'

const connector = createSignerConnector({
  apiBaseUrl: 'https://4signer.com/api/v1',
  bearerToken: 'ACCOUNT_TOKEN'
})

const result = await connector.sign({
  documentId: 'pdf-vidaas-001',
  documentType: 'pdf',
  certificateMode: 'cloud',
  providerHint: 'vidaas',
  documentContentBase64: pdfBase64,
  requestOptions: {
    vidaas: {
      auth_mode: 'qrcode', // or 'push'
      login_hint: '12345678901'
    }
  }
})

console.log(result.status)

Yesple PDF

Basic signature without visual customization.

curl -X POST "https://4signer.com/api/v1/signatures/pdf" \
  -H "Authorization: Bearer TOKEN_DA_ACCOUNT" \
  -H "Accept: application/json" \
  -F "signature_method=local_pfx" \
  -F "processing_mode=sync" \
  -F "pdf=@/tmp/document.pdf" \
  -F "pfx=@/tmp/certificate.pfx" \
  -F "pfx_password=PASSWORD"

PDF with visible appearance

Example with request_options for visible signature appearance, including image and PDF positioning.

curl -X POST "https://4signer.com/api/v1/signatures/pdf" \
  -H "Authorization: Bearer TOKEN_DA_ACCOUNT" \
  -F "signature_method=local_pfx" \
  -F "processing_mode=sync" \
  -F "pdf=@/tmp/document.pdf" \
  -F "pfx=@/tmp/certificate.pfx" \
  -F "pfx_password=PASSWORD" \
  -F "request_options[appearance][enabled]=true" \
  -F "request_options[appearance][page]=1" \
  -F "request_options[appearance][x]=100" \
  -F "request_options[appearance][y]=120" \
  -F "request_options[appearance][width]=180" \
  -F "request_options[appearance][height]=60" \
  -F "request_options[appearance][image_base64]=iVBORw0KGgoAAA..."

x, y, width, and height define the visible signature box. Change image_base64 to use a different signature image.

PDF without visible appearance

Invisible signature with cryptographic validity.

curl -X POST "https://4signer.com/api/v1/signatures/pdf" \
  -H "Authorization: Bearer TOKEN_DA_ACCOUNT" \
  -H "Accept: application/json" \
  -F "signature_method=local_pfx" \
  -F "processing_mode=sync" \
  -F "pdf=@/tmp/document.pdf" \
  -F "pfx=@/tmp/certificate.pfx" \
  -F "pfx_password=PASSWORD" \
  -F "request_options[use_visible_signature]=0"

PDF with A1

local_pfx e envio de arquivo PFX (endpoint direto da API). For cloud flow in Connector JS, use certificateMode: 'cloud' with providerHint.

A1 via arquivo PFX (local_pfx)

curl -X POST "https://4signer.com/api/v1/signatures/pdf" \
  -H "Authorization: Bearer TOKEN_DA_ACCOUNT" \
  -F "signature_method=local_pfx" \
  -F "processing_mode=sync" \
  -F "pdf=@/tmp/document.pdf" \
  -F "pfx=@/tmp/certificado-a1.pfx" \
  -F "pfx_password=SENHA_CERTIFICADO"

A1 credencial cadastrada (stored_a1)

curl -X POST "https://4signer.com/api/v1/signatures/pdf" \
  -H "Authorization: Bearer TOKEN_DA_ACCOUNT" \
  -F "signature_method=stored_a1" \
  -F "processing_mode=sync" \
  -F "pdf=@/tmp/document.pdf"

PDF with A3 Desktop (Connector)

import { createSignerConnector } from '@4signer/signer-connector-sdk'

const connector = createSignerConnector({
  apiBaseUrl: 'https://4signer.com/api/v1',
  bearerToken: 'TOKEN_DA_ACCOUNT'
})

const result = await connector.sign({
  documentId: 'pdf-001',
  documentType: 'pdf',
  certificateMode: 'local',
  documentContentBase64: pdfBase64
})

console.log(result.status)

PDF in cloud

Requires provider and credential. Asynchronous operation.

curl -X POST "https://4signer.com/api/v1/signatures/pdf" \
  -H "Authorization: Bearer TOKEN_DA_ACCOUNT" \
  -H "Accept: application/json" \
  -F "signature_method=remote_provider" \
  -F "processing_mode=async" \
  -F "provider=clicksign" \
  -F "pdf=@/tmp/document.pdf"

Timestamp (RFC3161)

Use request_options[timestamp] to enable TSA/ACT for PDF and XML signatures.

Field Description
request_options[timestamp][enabled]Enables timestamp (1/true)
request_options[timestamp][url]RFC3161 TSA URL
request_options[timestamp][username/password]Basic auth credentials (if required)
request_options[timestamp][token]Optional Bearer token
curl -X POST "https://4signer.com/api/v1/signatures/pdf" \
  -H "Authorization: Bearer TOKEN_DA_ACCOUNT" \
  -F "signature_method=local_pfx" \
  -F "processing_mode=sync" \
  -F "pdf=@/tmp/document.pdf" \
  -F "pfx=@/tmp/certificate.pfx" \
  -F "pfx_password=PASSWORD" \
  -F "request_options[timestamp][enabled]=1" \
  -F "request_options[timestamp][url]=https://tsa.example.com/rfc3161" \
  -F "request_options[timestamp][username]=tsa_user" \
  -F "request_options[timestamp][password]=tsa_pass"

XML

Endpoint base: POST /api/v1/signatures/xml

Field Required Description
signature_profileOptionalfiscal | xml-xades-diploma
signature_policyOptionalEx.: nfe-4.00, cte-4.00, diploma-icpbrasil-xades-1.0
signature_policy_parametersOptionalDefines target tag and policy parameters

Fiscal XML (NFe/CTe/NFSe)

Choose the tag with signature_policy_parameters[signed_element_local_name].

curl -X POST "https://4signer.com/api/v1/signatures/xml" \
  -H "Authorization: Bearer TOKEN_DA_ACCOUNT" \
  -F "signature_method=local_pfx" \
  -F "processing_mode=sync" \
  -F "xml=@/tmp/nfe.xml" \
  -F "pfx=@/tmp/certificate.pfx" \
  -F "pfx_password=PASSWORD" \
  -F "signature_profile=fiscal" \
  -F "signature_policy=nfe-4.00" \
  -F "signature_policy_parameters[signed_element_local_name]=infNFe" \
  -F "signature_policy_parameters[id_attribute]=Id"

Diploma XML

The target tag is defined by policy parameters. Ex.: DadosDiploma and Diploma.

curl -X POST "https://4signer.com/api/v1/signatures/xml/diploma" \
  -H "Authorization: Bearer TOKEN_DA_ACCOUNT" \
  -F "signature_method=remote_provider" \
  -F "processing_mode=async" \
  -F "xml=@/tmp/diploma.xml" \
  -F "signature_policy=diploma-ra-icpbrasil-xades-1.0" \
  -F "signature_policy_parameters[signed_element_local_name]=Diploma" \
  -F "signature_policy_parameters[id_attribute]=id" \
  -F "request_options[timestamp][enabled]=1" \
  -F "request_options[timestamp][url]=https://tsa.example.com/rfc3161"

Connector JS

In Connector, XML tag selection is done with xmlPolicyParameters.signed_element_local_name.

SDK installation

You can integrate with npm, direct ESM script, or classic script (legacy) using the official loader.

npm (recommended)

npm install @4signer/signer-connector-sdk

ESM script (without npm)

<script type="module">
  import { createSignerConnector } from 'https://cdn.jsdelivr.net/npm/@4signer/signer-connector-sdk@1.0.0/src/index.js'

  const connector = createSignerConnector({
    apiBaseUrl: 'https://4signer.com/api/v1',
    bearerToken: 'ACCOUNT_TOKEN'
  })
</script>

Legacy project with classic <script>

Use the loader to expose window.createSignerConnector.

<script>
  window.__4signerConnectorSdk = {
    moduleUrl: 'https://cdn.jsdelivr.net/npm/@4signer/signer-connector-sdk@1.0.0/src/index.js'
  }
</script>
<script src="/sdk/signer-connector-legacy-loader.js" defer></script>
<script>
  window.addEventListener('4signer:connector-ready', async function () {
    const connector = window.createSignerConnector({
      apiBaseUrl: 'https://4signer.com/api/v1',
      bearerToken: 'ACCOUNT_TOKEN'
    })

    const result = await connector.sign({
      documentId: 'legacy-001',
      documentType: 'pdf',
      certificateMode: 'cloud',
      documentContentBase64: pdfBase64
    })

    console.log(result.status)
  })
</script>
import { createSignerConnector } from '@4signer/signer-connector-sdk'

const connector = createSignerConnector({
  apiBaseUrl: 'https://4signer.com/api/v1',
  bearerToken: 'TOKEN_DA_ACCOUNT'
})

const result = await connector.sign({
  documentId: 'diploma-001',
  documentType: 'xml',
  certificateMode: 'local',
  documentContentBase64: diplomaXmlBase64,
  xmlProfile: 'xml-xades-diploma',
  xmlPolicy: 'diploma-icpbrasil-xades-1.0',
  xmlPolicyParameters: {
    signed_element_local_name: 'DadosDiploma',
    id_attribute: 'id'
  },
  requestOptions: {
    timestamp: {
      enabled: true,
      url: 'https://tsa.example.com/rfc3161'
    }
  }
})

console.log(result.status)

Cloud certificate discovery

List user certificates for BirdID or VIDaaS before starting cloud signing.

curl

curl -X POST "https://4signer.com/api/v1/connector/v1/providers/birdid/certificates/discovery" \
  -H "Authorization: Bearer ACCOUNT_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "username": "12345678901",
    "identification_type": "CPF"
  }'

Connector JS

const discovery = await connector.discoverCertificates({
  provider: 'birdid', // birdid | vidaas
  username: '12345678901',
  identificationType: 'CPF'
})

console.log(discovery.certificates)

After OAuth authentication, use /certificates/list to fetch effective certificates from the token.

curl (post-auth)

curl -X POST "https://4signer.com/api/v1/connector/v1/providers/birdid/certificates/list" \
  -H "Authorization: Bearer ACCOUNT_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "signature_id": "SIGNATURE_UUID"
  }'

Connector JS (post-auth)

const certificates = await connector.listCertificates({
  provider: 'birdid',
  signatureId: 'SIGNATURE_UUID'
  // or accessToken / username
})

console.log(certificates.certificates)

Webhooks

Webhook notifies your application when the signature status changes. Configure it in your account panel under Webhooks.

Field Uso
urlEndpoint HTTPS que recebera os eventos
secretKey to validate HMAC signature in the header
max_attemptsMaximum number of delivery attempts
retry_interval_secondsIntervalo entre retries quando falhar
timeout_secondsTimeout HTTP por tentativa de envio

Current delivery event: signature.status_changed.

Sent headers

Content-Type: application/json
Accept: application/json
X-Signer-Event: signature.status_changed
X-Signer-Delivery-Id: 9123
X-Signer-Signature-Timestamp: 2026-02-17T14:32:11Z
X-Signer-Signature: sha256=HMAC_DO_PAYLOAD

Event payload

{
  "event": "signature.status_changed",
  "occurred_at": "2026-02-17T14:32:11Z",
  "account": {
    "id": 9
  },
  "signature": {
    "id": "sig_01J...",
    "provider": "clicksign",
    "processing_mode": "async",
    "status_from": "pending_provider",
    "status_to": "signed",
    "external_id": "pedido-123",
    "error_code": null,
    "error_message": null,
    "started_at": "2026-02-17T14:31:00Z",
    "completed_at": "2026-02-17T14:32:11Z",
    "duration_ms": 71000
  }
}

Delivery is considered successful on HTTP 2xx. In case of failure, the system retries up to max_attempts.

Responses and errors

Sucesso (sync)

{
  "id": "sig_01J...",
  "status": "completed",
  "signed_file_base64": "..."
}

Asynchronous (cloud)

{
  "id": "sig_01J...",
  "status": "pending_provider",
  "webhook_status": "scheduled"
}