---
title: "TrustBridge quick reference"
description: "TrustBridge on one page: what you deploy, the API key, creating a Signing Session with CPF and PIN (or for a Company), signing PDFs, reading the outcome and handling errors."
canonical: "https://docs.lacunasoftware.com/en-us/articles/trustbridge/quick-reference"
locale: "en"
product: "TrustBridge"
last_updated: "2026-10-13"
---

# 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); TrustBridge signs hashes and stores no documents. 

| Choose instead | When it fits better |
| --- | --- |
| [CloudHub](https://docs.lacunasoftware.com/en-us/articles/cloudhub/quick-reference) | The certificates are cloud certificates held at an ICP-Brasil provider (a PSC), not on tokens or machines you manage. |
| [Rest PKI Core](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/quick-reference) | The person signs while using your web application, in their browser, and you want a hosted signing page. |
| [Web PKI](https://docs.lacunasoftware.com/en-us/articles/web-pki/quick-reference) | Your own web page must reach the certificates on the user's computer from JavaScript while they are at it. |
| [Signer](https://docs.lacunasoftware.com/en-us/articles/signer/quick-reference) | You 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:

| Component | Ships as | Current version | Guide |
| --- | --- | --- | --- |
| Server | Container image `trustbridge-server`, on Docker (Linux) or Azure App Service, with SQL Server | 1.13.0 | [Server installation](https://docs.lacunasoftware.com/en-us/articles/trustbridge/server-installation), [Azure App Service](https://docs.lacunasoftware.com/en-us/articles/trustbridge/azure) |
| Workstation Service and Tray App | Signed MSI `TrustBridge-Workstation-<version>-x64.msi`, one per holder's Windows machine | 1.5.0 | [Workstation installation](https://docs.lacunasoftware.com/en-us/articles/trustbridge/workstation-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. 
- **Workstation 1.5.0 needs Server 1.13.0**, and the two are upgraded together. A machine on an older release does not take part in creating sessions on Server 1.13.0. See [Changelog](https://docs.lacunasoftware.com/en-us/articles/trustbridge/changelog). 
- 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) when reporting a problem. 

## 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](https://docs.lacunasoftware.com/en-us/articles/trustbridge/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`; optionally `sessionDuration` in seconds (above the maximum is clamped) and `email`, a fallback address for a certificate that names none. 

```bash
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 }'
```

```json
{ "sessionId": "8f3c…", "cpf": "12345678909", "expiresIn": 3600, "expiresAt": "2026-09-21T15:04:05Z" }
```

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. 

```json
{ "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. 

```bash
curl -s https://trustbridge.example.com/v1/signatures \
  -H "X-API-Key: $API_KEY" \
  -F "sessionId=8f3c…" -F "document=@contract.pdf"
```

```json
{ "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. 

### 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). There is no webhook. How long a document stays fetchable is Lacuna Signer's retention, since the Server stores nothing. 

```bash
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](https://docs.lacunasoftware.com/en-us/articles/trustbridge/rest-api#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 on a Workstation release older than 1.5.0. 
- **`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). 
- **`SERVER_BUSY`** (429): the Server is at capacity; retry with your own backoff and jitter (no `Retry-After`). 

[Troubleshooting](https://docs.lacunasoftware.com/en-us/articles/trustbridge/troubleshooting#client-application-errors) 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. 
- The [Lacuna Test PKI certificates](https://docs.lacunasoftware.com/en-us/articles/pki-guide/test-certs) page has no TrustBridge section. 

TODO(docs): whether Lacuna offers a hosted TrustBridge test Server or sandbox, and whether the Lacuna Test PKI root can be added as a Trusted CA for testing.

## Try it

- On a running Server, open `/scalar` to browse the contract and try calls with an API key. 
- 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](https://docs.lacunasoftware.com/en-us/articles/trustbridge/rest-api#trying-the-contract-by-hand). 

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