---
title: "Rest PKI Core quick reference"
description: "Rest PKI Core on one page: client packages, API key and endpoint, signature sessions, webhooks, timestamps, liveness, errors and test resources."
canonical: "https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/quick-reference"
locale: "en"
product: "Rest PKI Core"
last_updated: "2026-10-12"
---

# Rest PKI Core quick reference

The essentials of Rest PKI Core on one page, with links to the full articles.

## What it is for

Rest PKI Core adds digital signatures, signature validation, timestamping and biometric identity checks to your applications through a REST API, as a service at core.pki.rest or on your own instance (Windows, Linux, Docker or Azure). 
When a step needs the user, such as signing with a certificate or taking a selfie, your backend creates a session, sends the user to a page hosted by Rest PKI Core and fetches the results through the API. 

| Choose instead | When it fits better |
| --- | --- |
| [Rest PKI](https://docs.lacunasoftware.com/en-us/articles/rest-pki/quick-reference) (legacy) | Your application is already integrated with Rest PKI at pki.rest. Rest PKI Core also serves most Rest PKI APIs, which eases the move. |
| [PKI SDK](https://docs.lacunasoftware.com/en-us/articles/pki-sdk/quick-reference) | Your application is .NET and should sign and validate with a library in its own process; the PKI guide recommends it for server signatures in .NET. |
| [PKI Express](https://docs.lacunasoftware.com/en-us/articles/pki-express/quick-reference) | You want to sign on your own Windows or Linux servers, from virtually any language, with a license file instead of an API service. |
| [Web PKI](https://docs.lacunasoftware.com/en-us/articles/web-pki/quick-reference) | You need only the browser side: list the user's certificates and sign with them in JavaScript. Rest PKI Core's hosted signature page already uses it for local certificates. |
| [Signer](https://docs.lacunasoftware.com/en-us/articles/signer/quick-reference) | You need a document and signature manager that sends documents to people and collects their signatures. |

## Install

| Language | Package | Current major | Registry |
| --- | --- | --- | --- |
| .NET | `Lacuna.RestPkiCore.Client` (namespace `Lacuna.RestPki.Client`) | 5 (latest 5.0.0) | https://www.nuget.org/packages/Lacuna.RestPkiCore.Client/ |
| Java | `com.lacunasoftware.restpki:restpkicore-client` (package `com.lacunasoftware.restpkicore`) | 1 (latest 1.4.0) | https://central.sonatype.com/artifact/com.lacunasoftware.restpki/restpkicore-client |
| PHP | `lacuna/restpkicore-client` | 1 (latest 1.2.1) | https://packagist.org/packages/lacuna/restpkicore-client |
| Node.js | `restpki-core-client` | 1 (latest 1.0.2) | https://www.npmjs.com/package/restpki-core-client |
| Python | `restpki-ng-python-client` | 0 (latest 0.9.1.1) | https://pypi.org/project/restpki-ng-python-client/ |
| Browser (biometric widget) | `lacuna-restpki-widget`, also on cdn.lacunasoftware.com | 1 (latest 1.4.1) | https://www.npmjs.com/package/lacuna-restpki-widget |
| Any other language (Ruby…) | None: call the REST API directly | — | — |

In .NET, run `dotnet add package Lacuna.RestPkiCore.Client`; the package targets .NET Standard 2.0. In Java, don't use `com.lacunasoftware.restpki:restpki-core-client`: it is an older package that is no longer updated, even though its version number (4.0.0) is higher. 

TODO(docs): the .NET samples pin older majors of `Lacuna.RestPkiCore.Client` (1.10.1 in PkiSuiteSamples dotnet/mvc, 1.3.0 in dotnet/spa, 4.1.0-rc01 in RestBioSamples backend/dotnet) while NuGet is at 5.0.0; no page mentions the Python package `restpki-ng-python-client`, which the Python sample uses; Get started has no setup section for Node.js or Python; the biometric sessions page loads widget 1.3.1 from the CDN, while npm has 1.4.1.

## Configuration and authentication

* **API key**: send it on the `X-Api-Key` header of every request. Keys belong to an application created on the instance's dashboard (**Applications**), are shown only once and look like `MyApp|0f3c…`. Give the application the **Worker** role, the one most integrations need. See [Get started](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/integration/get-started#parameters) and [Choosing roles](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/integration/get-started#roles). 
* **Timestamp endpoints** take the key as `Authorization: ApiKey YOUR_API_KEY` instead. See [Requesting timestamps](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/requesting-timestamps). 
* **Endpoint**: `https://core.pki.rest/` on the SaaS instance (if your organization has no access to it yet, contact [developer support](mailto:suporte@lacunasoftware.com)); on your [own instance](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/on-premises), the address of its dashboard. Append the API path to it, as in `https://core.pki.rest/api/signature-sessions`. `api/system/info` needs no key and returns the instance's version. 
* **API reference**: at the `swagger` path of the endpoint, such as https://core.pki.rest/swagger, and as an OpenAPI document at https://docs.lacunasoftware.com/openapi/rest-pki-core.json. 
* **Licenses**: the SaaS instance needs no license file, but an application that uses Web PKI with Rest PKI Core needs a Web PKI license; an on-premises instance needs PKI SDK and Web PKI licenses. See [Licensing](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#rest-pki-core). 

In ASP.NET Core, register the services and bind them to the `RestPki` configuration section, then request `IRestPkiService` (or `IRestBioService`, for biometric sessions) through dependency injection. The section's keys are `Endpoint`, `ApiKey`, `CultureName` and `TimeoutSeconds` (60 seconds if not set); keep `ApiKey` out of *appsettings.json*, in user secrets (`RestPki:ApiKey`) during development and in the `RestPki__ApiKey` environment variable or a secret store in production. Other .NET applications call `RestPkiServiceFactory.GetService(new RestPkiOptions() { ... })` once and reuse the service. 

```cs
builder.Services.AddRestPki().Configure(builder.Configuration.GetSection("RestPki"));
```

TODO(docs): no page describes a sandbox or test environment: the docs name only the SaaS instance at `https://core.pki.rest/` and on-premises instances.

## Core operations

The examples are in C#, where `restPkiService` and `restBioService` are the `IRestPkiService` and `IRestBioService` from [Configuration](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/quick-reference#configuration). 

### Create a signature session

Lets the user sign on a page hosted by Rest PKI Core, uploading the documents there: create the session with a `returnUrl` and redirect the user to the `RedirectUrl` you get back. `CreateSignatureSessionAsync`, `POST api/signature-sessions`. See [Signature sessions](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/integration/signature-sessions). 

```cs
var response = await restPkiService.CreateSignatureSessionAsync(new CreateSignatureSessionRequest() {
	ReturnUrl = "http://localhost:8080/SessionCallback",
});
return Redirect(response.RedirectUrl);
```

### Get the signed documents

When the user comes back, the `returnUrl` carries `?signatureSessionId=...`: fetch the session and check its status, which is `Completed` or `UserCancelled`. `GetSignatureSessionAsync`, `GET api/signature-sessions/{id}`. Each document's `SignedFile.Url` is a temporary link that downloads the file without the API key. See [Signature sessions](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/integration/signature-sessions). 

```cs
public async Task<ActionResult> Callback(Guid signatureSessionId)
{
	var session = await restPkiService.GetSignatureSessionAsync(signatureSessionId);
	if (session.Status != SignatureSessionStatus.Completed)
	{
		return Redirect("/");
	}
	return View(session);
}
```

### Sign documents your application already has

Passes the documents when creating the session, so the user signs them and cannot upload others. Reference each file by path, bytes, stream or URL with `FileReference`. See [Predefining documents](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/integration/signature-sessions#predefined-documents) and [Referencing files](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/integration/file-referencing). 

```cs
string pdfPath = ...;
var documents = new List<SignatureSessionDocumentToSign> {
	new SignatureSessionDocumentToSign {
		File = FileReference.FromFile(pdfPath),
	},
};
var response = await restPkiService.CreateSignatureSessionAsync(new CreateSignatureSessionRequest() {
	...
}, documents: documents);
return Redirect(response.RedirectUrl);
```

### Receive the webhook

Rest PKI Core sends an HTTP `POST` with a `WebhookEventModel` of type `DocumentSignatureCompleted` when a document is signed and processed, optionally with Basic, Bearer or API key authentication. With the [webhook flow](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/integration/signature-sessions#webhook-flow), create the session with no `ReturnUrl` and open the signature page in a new tab. See [Webhooks](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/integration/webhooks). 

```cs
[HttpPost]
public async Task<ActionResult> Index(WebhookEventModel eventModel)
{
	switch (eventModel.Type)
	{
		case WebhookEventTypes.DocumentSignatureCompleted:
			await OnDocumentSignatureCompletedAsync(eventModel.Document);
			break;
	}
	return new HttpStatusCodeResult(HttpStatusCode.OK);
}

private async Task OnDocumentSignatureCompletedAsync(DocumentModel model)
{
	var apiDocument = await restPkiService.GetDocumentAsync(model);
	// SignedFile.Url is a temporary link that downloads the signed file without the API key.
	var content = await restPkiService.GetContentAsync(apiDocument.SignedFile.Url);
}
```

A user with the **Admin** or **Manager** role sets the webhook URL and its authentication on the dashboard, in **Settings** > **Webhook config**. With Basic authentication, the header is `Authorization: Basic base64(username):base64(password)`, not the RFC 7617 form. Answer with a 2xx status code; the **Recent calls** tab shows each notification and your app's response. See [Configuring webhooks](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/integration/webhooks#configuring-webhooks). 

### Sign with a key held by your server

Rest PKI Core prepares the signature and returns the hash to sign, your server signs it, and Rest PKI Core completes the signature. `PrepareSignatureAsync` and `CompleteSignatureAsync`, `POST api/signature` and `POST api/signature/completion`. In the browser variant, Web PKI reads the user's certificate and signs the hash on your own page instead. See [Two-step signatures](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/integration/two-step-signatures). 

```cs
var certificate = new X509Certificate2(certificatePath, "1234");
var certificateReference = CertificateReference.FromX509Certificate2(certificate);
var fileReference = FileReference.FromFile(userfilePath, userfile);
var signatureOptions = new PrepareSignatureOptions() { SecurityContextId = Util.GetSecurityContextId() };
var prepareSignatureResult = await restPkiService.PrepareSignatureAsync(fileReference, certificateReference, signatureOptions);
var toSignHash = prepareSignatureResult.ToSignHash.Value;
var signature = certificate.GetRSAPrivateKey().SignHash(toSignHash, prepareSignatureResult.ToSignHash.Algorithm.HashAlgorithmName, RSASignaturePadding.Pkcs1);
var signedDocument = await restPkiService.CompleteSignatureAsync(prepareSignatureResult.State, signature);
```

### Run a liveness check

Checks that a real person is in front of the camera. Start the session with a `TrustedOrigin` (widget on your page) or a `ReturnUrl` (redirect), hand the `SessionUrl` to your frontend, then complete it with the ticket the user brings back. `StartLivenessSessionAsync` and `CompleteLivenessSessionAsync`, `POST api/bio/sessions/liveness` and `POST api/bio/sessions/liveness/completion`. See [Liveness](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/integration/bio-sessions/liveness) and [Biometric sessions](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/integration/bio-sessions). 

```cs
var response = await restBioService.StartLivenessSessionAsync(new() {
	TrustedOrigin = exampleConfig.Value.TrustedOrigin,
	SubjectIdentifier = "Example",
});
_ = response.SessionUrl;    // The URL to be loaded in the Widget to start the biometric session.
var result = await restBioService.CompleteLivenessSessionAsync(request.Ticket);
var success = result.Success;
```

### Request a timestamp

Uses Rest PKI Core as an RFC 3161 timestamp provider: `POST` the hash to `api/tsp` on the endpoint, or use the TSP protocol at `tsp`, with the header `Authorization: ApiKey YOUR_API_KEY`. Add the tier as a suffix (`api/tsp/PkiBrazil`): on the SaaS instance it is required, `PkiBrazil` or `LacunaTest`. The response has `encodedValue`, the timestamp in Base64. See [Requesting timestamps](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/requesting-timestamps). 

```json
{
	"algorithm": "SHA256",
	"value": "L80RIvFw2jwpiObzFQN+tuEQQ4E9qnGeYYYd+4DrM8M="
}
```

## Errors

The API answers with HTTP status codes. On 422, the body is an `ErrorModel` (named `ErrorModelV2` in the API reference) whose `code` your error handling should test; its `message` is in English and meant for logs. The .NET client throws the exceptions below, which all derive from `Lacuna.RestClient.RestException`. See [HTTP status codes](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/integration/get-started#http-status-codes) and [.NET errors](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/integration/get-started#dotnet-errors). 

| Status | .NET exception | What to check |
| --- | --- | --- |
| 401 | `RestErrorException` (`StatusCode`) | The API key is missing, wrong or expired; copy the whole key, including the application name before the separator |
| 403 | `RestForbiddenOperationException` | The application lacks a role for the operation, usually **Worker** |
| 422 | `RestPkiExceptionV2` (`ErrorCode`) | The API rejected the request: see the error code |
| — | `ValidationException` (`ValidationResults`) | A certificate or signature failed validation |
| — | `RestUnreachableException` | The endpoint could not be reached |

The codes met first are `SignatureSessionNotFound` (check the session ID), `BadSignatureSessionOperation` (the operation is invalid for the session's or document's status), `BackgroundProcessing` (the resource is still being processed) and `DocumentNotFound`. The list in [Error codes](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/integration/error-codes) is not complete. 

## Test certificates and credentials

* **Test certificates**: download the Lacuna Test PKI certificates from [Test certificates](https://docs.lacunasoftware.com/en-us/articles/pki-guide/test-certs), and never trust that PKI in production. 
* **Trusting the test PKI**: pass the standard security context `StandardSecurityContexts.LacunaTest` (`803517ad-3bbc-4169-b085-60053a8f6dbf`), which trusts ICP-Brasil and the Lacuna Test PKI, as the `SecurityContextId` of a signature session or of `PrepareSignatureOptions`, or choose it as the subscription's **Default security context** in **Settings** > **General settings** on the dashboard. Rest PKI Core creates this context on every instance when it starts. The .NET sample passes it in debug builds only. See [Rest PKI Core](https://docs.lacunasoftware.com/en-us/articles/pki-guide/test-certs#rest-pki-core) on the test certificates page. 
* **Test timestamps**: on the SaaS instance, use the `LacunaTest` tier. 
* **Sample API key**: the PkiSuiteSamples projects ship with a trial key for the SaaS instance that expires on 31/10/2026. For a key of your own, contact [developer support](mailto:suporte@lacunasoftware.com). 

TODO(docs): no page says whether core.pki.rest offers test API keys or a trial subscription.

## Try it

Run the demos, or open the sample project for your language:

**Demos and samples**

- Live demo: [Sign a file with Rest PKI Core](https://try.lacunasoftware.com/en/pki-suite/sign-a-file-rest-pki-core)
- Live demo: [Timestamp a PDF](https://try.lacunasoftware.com/en/pki-suite/timestamp-a-pdf)
- Live demo: [Run a liveness check](https://try.lacunasoftware.com/en/lacuna-bio/run-a-liveness-check)
- Live demo: [Enroll and authenticate your face](https://try.lacunasoftware.com/en/lacuna-bio/enroll-and-authenticate-your-face)
- Live demo: [Your certificates in the browser](https://try.lacunasoftware.com/en/web-pki/certificates-in-the-browser)
- Sign a PDF with Rest PKI Core: [.NET](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/dotnet/mvc/PkiSuiteAspNetMvcSample/Controllers/PadesSignatureRestCoreController.cs) · [Java](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/java/springmvc/src/main/java/com/lacunasoftware/pkisuite/controller/PadesSignatureCoreController.java) · [Node.js](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/nodejs/expressmvc/routes/pades-signature-core.js) · [PHP](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/php/plain/public/pades-signature-rest-core/index.php) · [Python](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/python/flask/sample/views/pades_signature_rest_core.py) · [Ruby](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/ruby/rails/app/controllers/pades_signature_rest_core_controller.rb)
- Sign multiple PDFs with Rest PKI Core: [Node.js](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/nodejs/expressmvc/routes/batch-pades-signature-core.js)
- Sign a PDF with a server key using Rest PKI Core: [.NET](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/dotnet/mvc/PkiSuiteAspNetMvcSample/Controllers/PadesServerKeyRestCoreController.cs)
- Signature session with Rest PKI Core: [.NET](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/dotnet/mvc/PkiSuiteAspNetMvcSample/Controllers/SignatureSessionRestCoreController.cs) · [Java](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/java/springmvc/src/main/java/com/lacunasoftware/pkisuite/controller/SignatureSessionRestCoreController.java) · [PHP](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/php/plain/public/signature-session-rest-core/index.php)
- Signature session with predefined documents using Rest PKI Core: [.NET](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/dotnet/mvc/PkiSuiteAspNetMvcSample/Controllers/SignatureSessionPreDefRestCoreController.cs) · [Java](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/java/springmvc/src/main/java/com/lacunasoftware/pkisuite/controller/SignatureSessionPreDefRestCoreController.java)
- Validate files uploaded to a Rest PKI Core signature session: [.NET](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/dotnet/mvc/PkiSuiteAspNetMvcSample/Controllers/ValidateFileRestCoreController.cs) · [Java](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/java/springmvc/src/main/java/com/lacunasoftware/pkisuite/controller/ValidateFileRestCoreController.java) · [PHP](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/php/plain/public/validate-file-rest-core/index.php)
- Receive Rest PKI Core webhooks: [.NET](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/dotnet/mvc/PkiSuiteAspNetMvcSample/Controllers/WebhookRestCoreController.cs) · [Java](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/java/springmvc/src/main/java/com/lacunasoftware/pkisuite/controller/WebhookRestCoreController.java) · [PHP](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/php/plain/public/webhook-rest-core/index.php)
- Authenticate with a digital certificate using Rest PKI Core: [Java](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/java/springmvc/src/main/java/com/lacunasoftware/pkisuite/controller/AuthenticationRestPkiCoreController.java)
