Pular para o conteúdo principal

TrustBridge quick reference

The essentials of Lacuna TrustBridge on one page, with links to the full articles.

What it is for​

Lacuna TrustBridge lets your server-side application sign PDF documents with a person's ICP-Brasil certificate through a REST API, while the private key stays where it lives: on a smart card, a USB token or in the Windows store of the holder's workstation, or, when the deployment opts in, in a vault on the TrustBridge Server. Your application sends the holder's CPF and PIN once to open a Signing Session, then signs under it; it never learns which custody answered. TrustBridge is self-hosted: you run the Server (a Linux container) and install the Workstation package on each holder's Windows machine. Lacuna Signer does the document work (hash, PDF assembly, signed-document download), or REST PKI Core does it for a Client Application an Administrator switches to it; TrustBridge signs hashes and stores no documents.

Choose insteadWhen it fits better
CloudHubThe certificates are cloud certificates held at an ICP-Brasil provider (a PSC), not on tokens or machines you manage.
Rest PKI CoreThe person signs while using your web application, in their browser, and you want a hosted signing page.
Web PKIYour own web page must reach the certificates on the user's computer from JavaScript while they are at it.
SignerYou need a document workflow: participants, notifications, approvals, a signing page for each person.

Install​

There is no client library: the API is plain HTTP and JSON (or multipart), so any HTTP client works. What you deploy:

ComponentShips asCurrent versionGuide
ServerContainer image trustbridge-server, on Docker (Linux) with SQL Server or PostgreSQL, or on Azure App Service with Azure SQL1.24.0Server installation, Azure App Service
Workstation Service and Tray AppSigned MSI TrustBridge-Workstation-<version>-x64.msi, one per holder's Windows machine1.10.0Workstation installation
  • Every Server needs a Lacuna PKI SDK licence (Certificates:Validation:License, PKI_LICENSE in the Docker .env), and hands it to every admitted workstation; the MSI takes no licence.
  • Upgrade the Server first, then the fleet. Workstation 1.10.0 needs Server 1.20.0 or later (1.23.0 or later for the admin console to show who is at each machine's console), and Server 1.15.0 refuses Workstation 1.4.x, so a fleet still on 1.4.x goes to 1.5.0 before the Server moves. A machine on 1.5.0 serves every session except a per-transaction one. See Changelog.
  • The database is SQL Server, or PostgreSQL 16 or later on Docker, chosen once per deployment; App Service stays on Azure SQL.
  • A new machine waits in the admission queue until an Administrator admits it on the admin console.

Configuration and authentication​

The base address is your own Server's (for example https://trustbridge.example.com), and every operation is under /v1; a bare route answers 404 ENDPOINT_NOT_FOUND. Every call needs an API key in the X-API-Key header.

  • Get a key on the admin console's Client Applications screen (/admin/applications): register your application, then Issue key. The value is shown once and only its hash is stored.
  • A bad key is always 401 UNAUTHORIZED, whether missing, unknown, revoked, expired or its application disabled.
  • Treat sessionId and signatureId as bearer tokens: any accepted key can use a session or fetch a document whose id it holds. Keep them out of logs.
  • Quote X-Correlation-Id (on every response, errors included) and the error's code when reporting a problem; the Server's Audit Log records the code each call was answered with (Server 1.24.0).

Core operations​

Create a session, sign under it, fetch the signed PDF (which is also where you read the outcome), and end the session. The REST API page documents every operation; a running Server serves the OpenAPI document at /openapi/v1.json and a browsable reference at /scalar, both without a credential.

Create a Signing Session​

POST /v1/sessions with the holder's cpf (eleven digits, check digits verified) and pin (which only a Client Application with Sessions without a PIN may leave out); optionally sessionDuration in seconds (above the maximum is clamped) and email, a fallback address for a certificate that names none.

curl -s https://trustbridge.example.com/v1/sessions \
-H "X-API-Key: $API_KEY" -H "Content-Type: application/json" \
-d '{ "cpf": "12345678909", "pin": "1234", "sessionDuration": 3600 }'
{ "sessionId": "8f3c…", "cpf": "12345678909", "expiresIn": 3600, "expiresAt": "2026-09-21T15:04:05Z",
"transactionPin": null, "certificate": "MIIH…", "chain": ["MIIG…", "MIIF…"] }

certificate (DER, base64) and chain (its issuers, nearest first; [] for a certificate on a workstation) describe the bound certificate. transactionPin is null unless your Client Application has Per-Transaction PIN on.

The Server tries the Vault Certificates for that CPF first, then asks the workstations holding a certificate for it to prove they hold the PIN; the PIN itself never leaves the Server. When no workstation has the PIN cached, the holder is prompted at their Tray App and the request stays open until they answer or the prompt times out (60 s by default): set a generous client timeout. One session is active per CPF; creating another replaces it.

Sign for a Company​

Add cnpj (fourteen characters, the alphanumeric CNPJ accepted) to sign with a Company's e-CNPJ; cpf is still the person who holds it. With a cnpj only that Company's e-CNPJ can bind the session, and without one an e-CNPJ never can. The answers carry cnpj only when one applies. Needs Server 1.13.0.

{ "cpf": "12345678909", "cnpj": "12ABC34501DE35", "pin": "1234" }

Sign a document​

POST /v1/signatures with the sessionId and a PDF, as JSON (document base64-encoded, optional fileName) or as multipart. It signs inside the request and answers 202 with the signatureId and the fileName it signed under.

curl -s https://trustbridge.example.com/v1/signatures \
-H "X-API-Key: $API_KEY" \
-F "sessionId=8f3c…" -F "document=@contract.pdf"
{ "signatureId": "a1b2…", "fileName": "contract.pdf", "status": "PROCESSING", "acceptedAt": "2026-09-21T14:10:00Z" }

A 202 is not "it worked": read the outcome at the fetch. Only PDFs are signed, up to 10 MB by default. For several documents, POST /v1/signatures/batch takes up to 50 file parts (by default) in one multipart call and answers one result per document, in order; read each result rather than the status code. A batch is one call for the throttle and for the Signature Allowance.

The Signature Allowance is set per Client Application. An Administrator may set, on your Client Application, how many signing calls each session it creates may make (1 gives single-use sessions); the session then answers SESSION_EXPIRED after that many. Nothing in a response says whether there is one.

Signer or REST PKI Core. An Administrator may switch your Client Application to have its documents signed with REST PKI Core instead of Lacuna Signer. The calls and answers are the same, but signatureId is then REST PKI Core's id, REST PKI Core keeps the signed PDF, and every failure before it answers the signed document is a refusal rather than a 202. A refusal after the holder's key signed promises nothing either way: sending the document again signs it again.

Sign digests (Hash Signing)​

POST /v1/signatures/hashes with the sessionId, a digestAlgorithm (SHA-256, SHA-384 or SHA-512) and up to 50 base64 hashes answers raw RSASSA-PKCS1-v1_5 signatures in the same order, synchronously and all or nothing. It is for an integrator that builds its own CAdES, XAdES or PAdES around certificate and chain. It is off until an Administrator grants it to your Client Application; until then it answers 403 HASH_SIGNING_NOT_GRANTED. Needs Server 1.14.0.

{ "sessionId": "8f3c…", "digestAlgorithm": "SHA-256", "hashes": ["uU0nuZNNPgilLlLX2n2r+sSE7+N6U4DukIj3rOLvzek="] }

Per-Transaction PIN​

An Administrator can switch a Client Application to ask for the PIN on every signing call (Server 1.15.0). Read transactionPin off each session:

  • null: nothing new; send no pin.
  • "workstation": each signing call waits while the holder authorizes it at the Tray App (60 s by default, outside the signing time); send no pin, and allow for the wait in your timeout. A batch asks once.
  • "client" (a Vault Certificate): send the holder's PIN as pin on every signing call.

A pin sent where it does not belong is 400 INVALID_REQUEST. A prompt declined, unanswered or not shown is 422 PIN_NOT_AVAILABLE with a details word, and nothing is signed. For no Tray at the console, the holder can reopen the Tray App from the Start menu's TrustBridge shortcut (Workstation 1.9.0); the Server's operator sees on the admin console why it could not be shown. Keep one long-lived session per user in this mode.

Sessions without a PIN (Server 1.18.0) is a second switch, only on beside Per-Transaction PIN: your application may then leave pin out of POST /v1/sessions, and the session binds, with nobody asked anything, to the single certificate that could serve it. Where more than one could (two machines, a vault certificate beside a machine, an old card and its renewal), creation answers 400 INVALID_REQUEST with details beginning pin is required.: ask your user for the PIN and send the same request with it.

Fetch the signed document​

GET /v1/signatures/{signatureId}/document. Poll on 409 DOCUMENT_NOT_READY; stop on 200 (the signed PDF) or 422 DOCUMENT_UNAVAILABLE (refused, cancelled or expired, or no longer held). There is no webhook. How long a document stays fetchable is Lacuna Signer's retention, or REST PKI Core's for a document signed there, since the Server stores nothing.

curl -s https://trustbridge.example.com/v1/signatures/a1b2…/document \
-H "X-API-Key: $API_KEY" -o signed.pdf -w '%{http_code}\n'

Check, describe and end a session​

  • GET /v1/sessions/status?sessionId=… answers active and the time left; it never extends the session. Signing does extend it.
  • GET /v1/certificates/info?sessionId=… describes the bound certificate; check that status is ACTIVE before signing.
  • POST /v1/sessions/deactivate with { "sessionId": "…" } ends it at once; with nothing active it answers 401 SESSION_EXPIRED.

Errors​

Every error is { "error": { "code", "message", "details" } }. Branch on code, never on message, and treat an unknown code as an unexpected failure. See The error envelope.

  • SESSION_EXPIRED (401) on any call: the session expired, was deactivated, replaced or used up its Signature Allowance. Create a new one.
  • INVALID_PIN (401): every candidate certificate was tried and none matched. TOO_MANY_PIN_ATTEMPTS (429) is the per-CPF lockout: retrying makes it worse.
  • PIN_NOT_AVAILABLE (422): no comparison could be made (prompt timed out or declined, vault certificate not opened, too many recent failed attempts); details says which. WORKSTATION_OFFLINE (422): the holder's machines are offline, or, for a per-transaction Client Application, on a Workstation release older than 1.6.0; with details workstation removed, the session's machine was removed from the platform and the session will never sign again, so create a new one.
  • HASH_SIGNING_NOT_GRANTED (403): your Client Application has not been granted Hash Signing.
  • CERT_NOT_FOUND (404) / CERT_NOT_ACTIVE (422): no certificate for the CPF, or none with an ACTIVE verdict.
  • SIGNER_REJECTED (422) vs SIGNER_ERROR (502): the signature service refused the request (don't resend it unchanged) vs could not be reached (nothing was signed; resend later). With REST PKI Core, SIGNER_ERROR and INTERNAL_ERROR can come after the holder's key signed, and then resending signs again.
  • SERVER_BUSY (429): the Server is at capacity; retry with your own backoff and jitter (no Retry-After).

Troubleshooting maps each code to what an operator checks.

Test certificates and credentials​

  • TrustBridge signs only with certificates whose chain it trusts. To sign with test certificates from a private CA, an Administrator adds that CA on the Trusted CAs screen, which reaches every admitted workstation without a restart.
  • To trust the Lacuna Test PKI, set Certificates:Validation:UseLacunaTestPki to true (default false) on the Server; a workstation does the same through its own setting of the same name. See The anchor sources and on a workstation. Development only: Lacuna publishes the private keys of those sample certificates. With it on, the Server logs Critical at start and shows a warning banner on every admin page, and a workstation logs Critical at every start.
  • With it on, an admin account bound to a sample certificate's CPF is open to anyone who downloaded that sample, and a workstation reports sample certificates as ACTIVE. Turn it off on anything but a development box.
  • The sample certificates (PKCS #12, password 1234) and the Lacuna Root Test v3 details are on the Test certificates page.

Lacuna offers no hosted TrustBridge test Server or sandbox: to test, contact Lacuna support.

TODO(docs): whether adding Lacuna Root Test v3 on the Trusted CAs screen works instead of UseLacunaTestPki.

Try it​

  • On a running Server, open /scalar to browse the contract and try calls with an API key.
  • An Administrator can make a real Test Signature end to end from the admin console's Test Signature page (/admin/test-signature), typing a CPF, its PIN and an API key; it returns the signed one-page PDF, or, asked for several documents (up to 50, Server 1.23.0), a ZIP of the copies signed in one batch call. The PIN may be left empty where the key's application has Sessions without a PIN, and the signature follows that application's Signer or REST PKI Core setting. The deployment can also offer it on the public Landing Page with TestSignature:Enabled.
  • Lacuna Software can provide a Postman collection of the contract with an environment carrying a sample PDF: create a session, sign, fetch. See Trying the contract by hand.

TODO(docs): no TrustBridge demo or sample project is published.

View as Markdown