Authentication
Every API call requires your account token in the Authorization header using the Bearer format.
Where to get your account token
- Access the 4signer dashboard with an administrator user.
- Open
API Access. - Create or copy the
account token. - 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
● 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
Downloads by operating system
Install according to the signer's operating system.
- Frontend calls Connector with
certificateMode: 'local'. - Connector creates an API session and requests local bootstrap.
- Agent signs locally and returns proof to the API.
- API finalizes status and makes the signed file available.
Endpoint base: POST /api/v1/signatures/pdf
| Field | Required | Description |
|---|---|---|
| signature_method | Yes | remote_provider | local_pfx | stored_a1 |
| processing_mode | Yes | remote_provider=async, local_pfx/stored_a1=sync |
| Yes | PDF file | |
| provider | Cloud | Provider for cloud signing |
| pfx + pfx_password | local_pfx | A1 certificate file |
| request_options | Optional | Additional 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"
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-simple-001',
documentType: 'pdf',
certificateMode: 'local',
documentContentBase64: pdfBase64
})
console.log(result.status)
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..."
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-visible-001',
documentType: 'pdf',
certificateMode: 'local',
documentContentBase64: pdfBase64,
requestOptions: {
use_visible_signature: true,
appearance: {
enabled: true,
page: 1,
x: 100,
y: 120,
width: 180,
height: 60,
image_base64: signatureImageBase64
}
}
})
console.log(result.status)
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"
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-invisible-001',
documentType: 'pdf',
certificateMode: 'local',
documentContentBase64: pdfBase64,
requestOptions: {
use_visible_signature: false
}
})
console.log(result.status)
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"
// local_pfx via arquivo e direto no endpoint da API.
// No Connector JS nao ha upload de arquivo PFX.
// Para fluxo local no cliente, use certificateMode='local' (Desktop Agent):
const result = await connector.sign({
documentId: 'pdf-a1-pfx-equivalente',
documentType: 'pdf',
certificateMode: 'local',
documentContentBase64: pdfBase64
})
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"
import { createSignerConnector } from '@4signer/signer-connector-sdk'
const connector = createSignerConnector({
apiBaseUrl: 'https://4signer.com/api/v1',
bearerToken: 'TOKEN_DA_ACCOUNT'
})
// Equivalente do stored_a1 no Connector JS:
const result = await connector.sign({
documentId: 'pdf-a1-stored-001',
documentType: 'pdf',
certificateMode: 'cloud',
documentContentBase64: pdfBase64
})
console.log(result.status)
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"
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-cloud-001',
documentType: 'pdf',
certificateMode: 'cloud',
documentContentBase64: pdfBase64
})
console.log(result.status)
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"
const result = await connector.sign({
documentId: 'xml-diploma-001',
documentType: 'xml',
certificateMode: 'local',
documentContentBase64: diplomaXmlBase64,
xmlProfile: 'xml-xades-diploma',
xmlPolicy: 'diploma-icpbrasil-xades-1.0',
requestOptions: {
timestamp: {
enabled: true,
url: 'https://tsa.example.com/rfc3161',
token: 'TSA_TOKEN'
}
}
})
XML
Endpoint base: POST /api/v1/signatures/xml
| Field | Required | Description |
|---|---|---|
| signature_profile | Optional | fiscal | xml-xades-diploma |
| signature_policy | Optional | Ex.: nfe-4.00, cte-4.00, diploma-icpbrasil-xades-1.0 |
| signature_policy_parameters | Optional | Defines 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"
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: 'nfe-001',
documentType: 'xml',
certificateMode: 'local',
documentContentBase64: nfeXmlBase64,
xmlProfile: 'fiscal',
xmlPolicy: 'nfe-4.00',
xmlPolicyParameters: {
signed_element_local_name: 'infNFe',
id_attribute: 'Id'
}
})
console.log(result.status)
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"
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: 'cloud',
documentContentBase64: diplomaXmlBase64,
xmlProfile: 'xml-xades-diploma',
xmlPolicy: 'diploma-ra-icpbrasil-xades-1.0',
xmlPolicyParameters: {
signed_element_local_name: 'Diploma',
id_attribute: 'id'
},
requestOptions: {
timestamp: {
enabled: true,
url: 'https://tsa.example.com/rfc3161'
}
}
})
console.log(result.status)
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 |
|---|---|
| url | Endpoint HTTPS que recebera os eventos |
| secret | Key to validate HMAC signature in the header |
| max_attempts | Maximum number of delivery attempts |
| retry_interval_seconds | Intervalo entre retries quando falhar |
| timeout_seconds | Timeout 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"
}