# Seal PDFs

Seal a PDF with your own certificate: where to get one, what legivel keeps, and what a reader sees.

Page: https://legivel.com/docs/sealing

Seal PDFs with your certificate. legivel applies a seal on your instruction and on your behalf, using your certificate. A seal is a certificate-based digital signature written into the finished PDF.

## What a seal is

The seal covers the bytes of the document legivel produced. A reader that checks it can tell whether those bytes changed after the seal, and which certificate was used. The seal is invisible: it adds no stamp, image or page to the document.

legivel never seals with a certificate of its own. Every seal uses a certificate you supply, either with the request or from your account. There is no seal you did not ask for, and no certificate you did not provide.

## Who can seal

Sealing is included on every paid plan, from Starter upwards. A Free account's sealing request is refused with 403 `plan_required` and costs no document.

Seals are applied through the API and the MCP server. The editor produces unsealed PDFs.

## Sealing a document

Add a `sign` object to a render request. Three forms are accepted, and each one names exactly one certificate; see [Render a PDF](https://legivel.com/docs/api/render#sealing) for the full field reference.

```json
{
  "markdown": "# Approved invoice",
  "sign": {
    "certificate": "Acme certificate"
  }
}
```

- `certificate` names a certificate stored in your account.
- `p12` is a PKCS#12 (PFX) bundle as standard Base64, with its `password`. An empty password is valid for an unprotected bundle.
- `key`, `cert` and the optional `chain` carry the same credential as separate parts. Each is PEM text or Base64 of DER. A `chain` in PEM may hold several certificates. `password` is needed only for an encrypted key. RSA, ECDSA and Ed25519 keys are read.
- Each part decodes to at most 65,536 bytes. A public certificate on its own cannot seal: the private key must be present and must match the certificate.
- Optional `reason`, `location` and `contact` are written into the seal. They describe it; they never change whose certificate is used.

A sealed answer carries `X-Legivel-Signature: signed`. A request that asks for a seal is never answered with an unsealed PDF: if the seal cannot be applied, the request fails.

## Getting a certificate

You need a certificate whose private key you can export, together with that key. A certificate a provider keeps in a hardware token, a smart card or its own cloud service usually cannot be exported, and cannot be used here.

### From a certificate provider

Ask for a certificate for documents or electronic seals, issued to your organisation, and say that you need the private key in an exportable file. Providers usually deliver a `.p12` or `.pfx` file, which is the bundle form above. Check that your agreement with the provider allows a service to apply the certificate on your instruction.

### From files you already hold

If you hold the key and the certificate as separate files, send them as separate parts, or pack them into one bundle:

Pack a key and its certificate chain into a bundle

```bash
openssl pkcs12 -export \
  -inkey private-key.pem \
  -in certificate.pem \
  -certfile issuers.pem \
  -out bundle.p12

# Base64 for the request body
base64 -w0 bundle.p12
```

### Testing before you have one

A self-signed certificate you make yourself seals exactly like any other, so you can build and test your integration before a provider's certificate arrives:

A self-signed certificate for your own tests

```bash
openssl req -x509 -newkey rsa:2048 -days 30 -nodes \
  -keyout test-key.pem -out test-cert.pem \
  -subj "/CN=Test seal"
```

A reader will report the seal as untrusted, because nothing vouches for a certificate you issued to yourself. Everything else behaves the same.

## What legivel keeps

A certificate sent with the request is used for that render and is not written to your account, to storage or to the logs. Provide it again on the next request. The logs record that a seal was applied and the certificate's public fingerprint, never the key, the bundle or the password.

A certificate stored in your account is a different arrangement, because a stored bundle contains your private key:

- The bundle and its password are both encrypted at rest under a key held outside the database.
- The certificate's public details (name, issuer, validity dates, fingerprint) and the record of your authorisation are kept in readable form, so the account page can show them.
- Deleting the certificate removes the stored bundle, its password and that record. Renders already made keep their audit entries.

Storing a certificate records your authorisation (customer-seal-v2):

> I instruct legivel to use this certificate to seal the documents I submit, until I delete it.

## Reader trust and legal status

Three separate questions are easy to confuse, so it is worth stating them apart.

- **Is the seal cryptographically sound?** That is what legivel produces: a seal over the document's bytes, made with the certificate you supplied.
- **Will a reader show it as trusted?** That depends on the certificate's chain and on the reader's own trust settings and validation policy. A well-known issuer name on its own guarantees nothing; the same file can read as trusted in one reader and untrusted in another.
- **What does it mean in law?** That depends on the applicable law and the circumstances, and on the certificate itself. [eIDAS](https://eur-lex.europa.eu/legal-content/EN/TXT/PDF/?uri=CELEX%3A02014R0910-20241018) treats a signature by a person and a seal by an organisation differently, and reserves "qualified" for certificates issued under specific requirements. legivel makes no claim about the status of a seal it applies.

Reader validation

[Adobe's guidance on trusted identities](https://helpx.adobe.com/acrobat/using/trusted-identities.html) and its [verification preferences](https://helpx.adobe.com/acrobat/desktop/e-sign-documents/manage-digital-signatures/set-preferences.html) explain what a reader checks and why two readers can disagree about the same file.

## When a seal is refused

A credential legivel cannot use is refused with 400 `invalid_bundle` and a reason that says what was wrong, without repeating anything you sent:

| Reason | What to check |
| --- | --- |
| `wrong_password` | The password does not open this bundle or key. |
| `no_private_key` | No private key was found; a certificate alone cannot seal. |
| `cert_chain_incomplete` | No certificate was found for the key. |
| `key_cert_mismatch` | The key and the certificate are not a pair. |
| `certificate_expired` | The certificate's validity has ended. Renew it. |
| `certificate_not_yet_valid` | The certificate's validity has not started yet. |
| `unsupported_algorithm` | The key type or the bundle's encryption is not read. Re-export with current settings. |
| `iterations_exceeded` | The bundle's password protection asks for more work than legivel will spend. |

Other refusals use the ordinary codes on [Errors and quota](https://legivel.com/docs/errors): 403 `plan_required` on a Free plan, 400 `invalid_request` for `sign: true` or a `sign` object that names no certificate or mixes forms, and 400 `unknown_signing_identity` for a stored name that does not exist. A refused seal costs no document and never returns an unsealed PDF.
