Pular para o conteúdo principal

Get started on integration - Rest PKI Core

This article takes you from nothing to a first working call to Rest PKI Core. You will:

  1. Get your credentials: the endpoint of the instance and an API key
  2. Set up the client library for your programming language, or call the REST API directly
  3. Make a first call to check that everything is in place

How the integration works​

Your application talks to Rest PKI Core through a REST API, authenticated by an API key. The calls are always made by your application's backend: the API key gives access to your subscription, so it must never reach a browser or a mobile app.

When an operation needs the user, such as choosing a certificate and signing a document, or taking a selfie for a biometric check, you don't have to build those pages. Your backend creates a session, Rest PKI Core returns a URL, and the user is sent to a page hosted by Rest PKI Core. When the user is done, they come back to your application, which fetches the results through the API. See signature sessions and biometric sessions.

Get your credentials​

You need two parameters:

ParameterDescription
EndpointAddress of the Rest PKI Core instance. On the SaaS instance it is https://core.pki.rest/. On your own instance, it is the address of its dashboard, such as https://restpki.yourcompany.com/
API keyKey that identifies your application and authenticates its calls. It looks like MyApp|0f3c…: a prefix taken from the application name, a |, then 64 hexadecimal characters

If you are using the SaaS instance and your organization does not have access to it yet, contact our developer support. If you are using your own on-premises instance and have no subscription to work with yet, see Creating a subscription.

There is no public sandbox. The samples and the demo site use a trial subscription on the SaaS instance, whose API key Lacuna rotates every month: take the current key from the samples repository instead of copying it into your code.

Create an API key​

API keys belong to applications. Once you can sign in to the dashboard, create an application for your system and a key for it:

  1. Sign in to the dashboard of the instance
  2. On the left menu, click Applications, then Add
  3. On New Application, fill in a Name for the application. If you are asked for a Subscription, choose the one your system will work on
  4. Under Roles, check Worker (see Choosing roles below)
  5. Click Create
  6. On the application's page, click Keys, then Add
  7. On New Application Key, fill in a Description (for instance, the environment that will use the key) and choose an Expiration (see Key expiration below), then click Create
  8. Copy the key shown on the Key created dialog and store it in a safe place. You will not be able to view it again: if you lose it, create a new key
Keep the API key secret

Anyone who has the key can act on your subscription with the roles of its application. Store it as you would store a password: in a secret store such as Azure Key Vault, in an environment variable or, during development, in .NET user secrets. Never commit it to source control and never send it to a browser or a mobile app.

Choosing roles​

The roles of an application define what its keys can do. Give your application only the roles it needs:

RoleWhat it allows
WorkerThe operations of an integration: create and use signature sessions, sign documents, inspect signatures, authenticate users with certificates, issue timestamps, run biometric sessions, add marks and stamps to documents, and view transactions. This is the role most integrations need
MonitorView transactions, biometric sessions, enrollment batches and invoices, without performing any operation
ManagerEverything a Worker does, plus managing the subscription's settings and security contexts. It can view applications and users, but not manage them
AdminEverything, including managing applications and users

Key expiration​

The Expiration of a key can be In 1 year, In 2 years or Never expires. When a key expires, the calls made with it start failing with HTTP 401, so if you choose an expiring key, plan its replacement: an application can have more than one key, which lets you create the new key and switch your system to it before the old one expires.

Choose how to call the API​

Rest PKI Core's APIs are plain REST with JSON, but you don't need to deal with HTTP yourself. Lacuna provides client libraries that wrap the API in the idioms of each language, together with sample projects that use them:

LanguagePackageSource codeSamples
.NETLacuna.RestPkiCore.Client on NuGet—PkiSuiteSamples/dotnet
PHPlacuna/restpkicore-client on PackagistGitHubPkiSuiteSamples/php
Javacom.lacunasoftware.restpki:restpkicore-client on Maven CentralGitHubPkiSuiteSamples/java
Node.jsrestpki-core-client on npmGitHubPkiSuiteSamples/nodejs
Pythonrestpki-ng-python-client on PyPI—PkiSuiteSamples/python

Jump to the section of your language:

For any other language, call the API directly.

.NET​

Add the NuGet package Lacuna.RestPkiCore.Client to your project:

dotnet add package Lacuna.RestPkiCore.Client

The package targets .NET Standard 2.0, so it runs on .NET 5 or later, on .NET Core 2.0 or later and on .NET Framework 4.6.1 or later (Microsoft recommends 4.7.2 or later for .NET Standard 2.0 libraries).

note

The package is named Lacuna.RestPkiCore.Client, but its classes are in the Lacuna.RestPki.Client namespace.

ASP.NET Core applications​

Register the Rest PKI Core services in Program.cs, binding their options to the RestPki configuration section:

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

Then add the section to appsettings.json, leaving the API key out of it:

{
"RestPki": {
"Endpoint": "https://core.pki.rest/"
}
}

Provide the API key through a source that stays out of source control. During development, use user secrets:

dotnet user-secrets set "RestPki:ApiKey" "YOUR_API_KEY"

In production, set the environment variable RestPki__ApiKey, or use a secret store such as Azure Key Vault. ASP.NET Core merges these sources into the same RestPki section.

Wherever your application needs to call Rest PKI Core, request an IRestPkiService through dependency injection:

using Lacuna.RestPki.Client;

public class SignatureController : Controller {

private readonly IRestPkiService restPkiService;

public SignatureController(IRestPkiService restPkiService) {
this.restPkiService = restPkiService;
}

...
}

AddRestPki() also registers IRestBioService, the service used for biometric sessions.

tip

If you prefer to set the options in code, pass them to AddRestPki(): builder.Services.AddRestPki(options => { options.Endpoint = ...; options.ApiKey = ...; });

Other .NET applications​

If your application does not use ASP.NET Core dependency injection, as in a .NET Framework or console application, get an IRestPkiService from the static class RestPkiServiceFactory:

using Lacuna.RestPki.Client;

var restPkiService = RestPkiServiceFactory.GetService(new RestPkiOptions() {
Endpoint = ConfigurationManager.AppSettings["RestPkiEndpoint"],
ApiKey = ConfigurationManager.AppSettings["RestPkiApiKey"],
});

In this example, the parameters come from the appSettings section of the web.config or app.config file, but they can come from wherever you prefer. For biometric sessions, use RestPkiServiceFactory.GetBioService(), which takes the same parameters.

Each call to the factory creates a new HTTP client, so create the service once and reuse it, for instance in a static field, instead of creating one on every request.

Options​

RestPkiOptions has the following properties, which can also be set in the RestPki configuration section:

PropertyDescription
EndpointAddress of the Rest PKI Core instance. If the address has a path, end it with a slash (https://yourcompany.com/restpki/), otherwise the last segment of the path is dropped
ApiKeyThe application's API key
CultureNameCulture of the API's responses, such as en-US, pt-BR or es-ES (see Culture below). Also available as Culture, of type CultureInfo
TimeoutSecondsHow long to wait for each response, in seconds. If not set, the client waits 60 seconds. Also available as Timeout, of type TimeSpan

Culture​

The client tells Rest PKI Core which culture to use in each call, and by default it uses the culture of the current thread (Thread.CurrentThread.CurrentUICulture). This works well when your application sets the culture of each request, as ASP.NET Core does with request localization.

To always use the same culture regardless of the thread, set CultureName. In ASP.NET Core, add it to the configuration section:

{
"RestPki": {
"Endpoint": "https://core.pki.rest/",
"CultureName": "en-US"
}
}

Otherwise, set it on RestPkiOptions:

var restPkiService = RestPkiServiceFactory.GetService(new RestPkiOptions() {
...,
CultureName = "en-US",
});

The same setting defines the language of the hosted biometric capture page (taken from the Accept-Language of the session-start request), so setting CultureName pins every capture page to that language.

Errors​

The methods of IRestPkiService may throw the following exceptions:

ExceptionWhen
RestPkiExceptionV2The API rejected the request (HTTP 422). Check the ErrorCode property, of type ErrorCodesV2, against the error codes. The ErrorMessage property describes the error in English and is meant for your logs, not for your users
ValidationExceptionA certificate or signature failed validation. The ValidationResults property tells what failed
RestForbiddenOperationExceptionThe application doesn't have a role that allows the operation (HTTP 403, see Choosing roles)
RestErrorExceptionAny other HTTP error, such as 401 for a missing or invalid API key. The StatusCode property has the HTTP status code (see HTTP status codes)
RestUnreachableExceptionThe endpoint could not be reached: check the endpoint address and your network
TimeoutExceptionThe response took longer than TimeoutSeconds

RestPkiExceptionV2 and ValidationException are in the Lacuna.RestPki.Client namespace, and the other Rest…Exception classes are in the Lacuna.RestClient namespace. All of them derive from Lacuna.RestClient.RestException, so to handle any error from the API in a single place, catch RestException (and TimeoutException, which is a standard .NET exception).

PHP​

Add the Composer package lacuna/restpkicore-client to your project (if you don't have Composer yet, get it here):

composer require lacuna/restpkicore-client

The package requires PHP 5.5 or later and uses Guzzle 6 or 7 to make HTTP calls. It is open source, hosted on GitHub: feel free to fork it if you need to customize it.

Create a RestPkiService, which implements RestPkiServiceInterface, passing it a RestPkiCoreClient built with the endpoint and the API key:

use Lacuna\RestPki\RestPkiOptions;
use Lacuna\RestPki\RestPkiCoreClient;
use Lacuna\RestPki\RestPkiService;

$options = new RestPkiOptions('https://core.pki.rest/', getenv('RESTPKI_API_KEY'));
$client = new RestPkiCoreClient($options);
$service = new RestPkiService($client);

In this example, the API key comes from the environment variable RESTPKI_API_KEY, which keeps it out of your code.

Culture​

To set the culture of the API's responses, pass it as the third parameter of RestPkiOptions:

$options = new RestPkiOptions('https://core.pki.rest/', getenv('RESTPKI_API_KEY'), 'en-US');

Errors​

All of the following exceptions are in the Lacuna\RestPki namespace:

ExceptionWhen
RestPkiExceptionThe API rejected the request (HTTP 422). getErrorCode() returns the error code and getDetail() describes the error, for your logs
ValidationExceptionA certificate or signature failed validation
RestErrorExceptionAny other HTTP error. getStatusCode() returns the HTTP status code (see HTTP status codes)
RestUnreachableExceptionThe endpoint could not be reached

PHP samples​

In our samples repository, the folders whose names end in -rest-core use Rest PKI Core. The endpoint and the API key are set in the restPkiNg entry of config.php.

Java​

Add the package com.lacunasoftware.restpki:restpkicore-client, from Maven Central, to your project. It requires Java 8 or later.

With Gradle, in build.gradle:

repositories {
mavenCentral()
}

dependencies {
implementation 'com.lacunasoftware.restpki:restpkicore-client:1.4.0'
}

With Maven, in pom.xml:

<dependency>
<groupId>com.lacunasoftware.restpki</groupId>
<artifactId>restpkicore-client</artifactId>
<version>1.4.0</version>
</dependency>

Check Maven Central for the latest version.

warning

Don't confuse it with com.lacunasoftware.restpki:restpki-core-client, an older package that is no longer updated.

The package is open source, hosted on GitHub: feel free to fork it if you need to customize it.

Get a RestPkiService from RestPkiServiceFactory.getService(), passing a RestPkiOptions with the endpoint and the API key:

import com.lacunasoftware.restpkicore.RestPkiOptions;
import com.lacunasoftware.restpkicore.RestPkiService;
import com.lacunasoftware.restpkicore.RestPkiServiceFactory;

RestPkiOptions options = new RestPkiOptions();
options.setEndpoint("https://core.pki.rest/");
options.setApiKey(System.getenv("RESTPKI_API_KEY"));
RestPkiService service = RestPkiServiceFactory.getService(options);

In this example, the API key comes from the environment variable RESTPKI_API_KEY, which keeps it out of your code. If your application reaches the internet through a proxy, set it with options.setProxy().

Culture​

To set the culture of the API's responses, call setCulture():

options.setCulture("en-US");

Errors​

The methods of RestPkiService declare throws Exception. These are the exceptions they throw, all in the com.lacunasoftware.restpkicore package:

ExceptionWhen
RestPkiExceptionThe API rejected the request (HTTP 422). getErrorCode() returns the error code
ValidationExceptionA certificate or signature failed validation
RestResourceNotFoundExceptionThe resource was not found (HTTP 404)
RestErrorExceptionAny other HTTP error. getStatusCode() returns the HTTP status code (see HTTP status codes)
RestUnreachableExceptionThe endpoint could not be reached

Java samples​

In our samples repository, the controllers whose names end in CoreController, such as SignatureSessionRestCoreController, use Rest PKI Core. The endpoint and the API key are set under rest-pki-core in application.yml.

Node.js​

Add the package restpki-core-client, from npm, to your project:

npm install restpki-core-client

The package doesn't declare the Node.js versions it supports. It brings its TypeScript typings, and makes its HTTP calls with the request package, which is deprecated on npm. It is open source, hosted on GitHub.

Create a RestPkiCoreClient, passing it the endpoint, without the trailing slash, as baseUrl and the API key as apiKey:

const { RestPkiCoreClient } = require('restpki-core-client');

const client = new RestPkiCoreClient({
baseUrl: 'https://core.pki.rest',
apiKey: process.env.RESTPKI_API_KEY,
});

In this example, the API key comes from the environment variable RESTPKI_API_KEY, which keeps it out of your code. The library sends it on the X-Api-Key header and builds each URL by appending the route, such as /api/signature, to baseUrl.

The client has a method for each route, such as prepareSignature() for POST api/signature, completeSignature() for POST api/signature/completion and createSignatureSession() for POST api/signature-sessions. Each method returns a promise of an object whose data property holds the body of the response, and statusCode its HTTP status code:

const response = await client.createSignatureSession({
returnUrl: 'https://localhost:3000/signature-callback',
});

// Send the user to response.data.redirectUrl
warning

The examples in the package's README create a Configuration object, a class that version 1.0.2 doesn't have: create a RestPkiCoreClient as above. The timeout and ignoreSslErrors options, which RestPkiCoreClient accepts, have no effect in this version.

Culture​

The library sends no Accept-Language header. To set the culture of the API's responses, add it to customHeaders, which the library sends on every request:

const client = new RestPkiCoreClient({
baseUrl: 'https://core.pki.rest',
apiKey: process.env.RESTPKI_API_KEY,
customHeaders: { 'Accept-Language': 'en-US' },
});

Errors​

When the API answers with an HTTP status code other than 2xx, the promise is rejected with an HttpError, exported by the package, whose statusCode property holds the HTTP status code (see HTTP status codes) and body the body of the response, already parsed from JSON. On HTTP 422, when the API rejected the request, body is an ErrorModel. When the endpoint can't be reached, the promise is rejected with the error of the request package.

Node.js samples​

In our samples repository, the routes whose files end in -core.js, such as pades-signature-core.js, use Rest PKI Core: they sign PDFs with two-step signatures and add PDF stamps. The endpoint and the API key are set under restPkiCore in config/default.js.

Python​

Add the package restpki-ng-python-client, from PyPI, to your project:

pip install restpki-ng-python-client

The package doesn't declare the Python versions it supports. It depends on pydantic 2 and on urllib3 below 2.1. Don't install its pre-releases (pip install --pre): 0.9.2rc1 doesn't contain the library.

note

The package is named restpki-ng-python-client, but you import it as restpki_ng_python_client.

The library is generated from the API: there is a class for each group of routes, such as SignatureApi, SignatureSessionsApi, DocumentsApi, SignatureInspectionApi and PdfApi, and a method for each route, named after it, such as api_signature_post() for POST api/signature. Create an ApiClient with the endpoint, without the trailing slash, and send the API key on the X-Api-Key header:

import os
import certifi
from restpki_ng_python_client import ApiClient, Configuration, SignatureApi

configuration = Configuration(host='https://core.pki.rest', ssl_ca_cert=certifi.where())
client = ApiClient(configuration)
client.set_default_header('X-Api-Key', os.environ['RESTPKI_API_KEY'])

signature_api = SignatureApi(client)

In this example, the API key comes from the environment variable RESTPKI_API_KEY, which keeps it out of your code, and the trusted CAs for HTTPS come from the certifi package. The library builds each URL by appending the route to host, so an endpoint ending in / gives URLs with //.

warning

Don't use the RestPkiClient class of version 0.9.1.1: it turns off the verification of the server's TLS certificate.

Culture​

The library sends no Accept-Language header. To set the culture of the API's responses, add it as a default header:

client.set_default_header('Accept-Language', 'en-US')

Errors​

All of the following exceptions are in the restpki_ng_python_client.exceptions module, and derive from ApiException:

ExceptionWhen
BadRequestExceptionHTTP 400: the request is malformed
UnauthorizedExceptionHTTP 401: the API key is missing, invalid or expired
ForbiddenExceptionHTTP 403: the application doesn't have a role that allows the operation (see Choosing roles)
NotFoundExceptionHTTP 404
ServiceExceptionHTTP 500 or other 5xx
ApiExceptionAny other HTTP error, including 422, when the API rejected the request. The library doesn't parse the ErrorModel: read it as JSON from the body property, and the HTTP status code from status

Python samples​

In our samples repository, the view pades_signature_rest_core.py uses Rest PKI Core, to sign a PDF with two-step signatures. The endpoint and the API key are set in REST_PKI_CORE_ENDPOINT and REST_PKI_CORE_API_KEY, in sample/config.py.

Calling the API directly​

The APIs of Rest PKI Core are RESTful, receiving and returning JSON, so they are easy to call from any modern programming language. If your application uses a language without a client library, call them directly:

  • URL: append the API's relative path to the endpoint. For instance, api/signature-sessions on the SaaS instance is https://core.pki.rest/api/signature-sessions
  • Authentication: pass the API key on the X-Api-Key header of every request
  • Body: send JSON with the Content-Type: application/json header

For instance:

POST https://core.pki.rest/api/signature-sessions
X-Api-Key: MyApp|0f3c...
Content-Type: application/json

All the APIs, with their requests and responses, are described on the API reference. On your own instance, the reference is at the path swagger of the endpoint, such as https://restpki.yourcompany.com/swagger.

HTTP status codes​

The API responds with the following HTTP status codes:

CodeMeaning
200 (OK)The request succeeded. The response depends on the API: see the API reference
400 (Bad Request)The request is malformed, for instance, a required field is missing
401 (Unauthorized)The API key is missing, invalid or expired
403 (Forbidden)The API key is valid, but its application doesn't have a role that allows the operation (see Choosing roles)
422 (Unprocessable Entity)The API rejected the request, usually because of a parameter that must be fixed. The body is an ErrorModel
500 (Internal Server Error)An unexpected error happened. The exceptionCode field of the body helps diagnose the problem: include it when contacting support

ErrorModel​

When the API responds with 422 (Unprocessable Entity), the body is an ErrorModel, named ErrorModelV2 in the API reference, with the following fields:

FieldTypeDescription
codestringThe error code (see error codes). Write your error handling against this field
messagestringDescription of the error, in English. It is meant for your logs, not for your users, since it is not localized
detailsobjectAdditional information about the error, when there is any
validationResultsobjectWhen the code is ValidationError, the results of the certificate or signature validation that failed

For instance:

{
"code": "SignatureSessionNotFound",
"message": "Signature session not found: 00000000-0000-0000-0000-000000000000"
}

Culture​

The API observes the Accept-Language request header, which changes the culture of the texts the API returns. The supported cultures are:

  • en-US (or just en)
  • pt-BR (or just pt)
  • es-ES (or just es)
note

Error messages are not affected by this header, so they should be logged, not shown to your users. To show an error to a user, map its code to a message of your own.

Make a first call​

With your credentials and the client library in place, check that everything works.

First, check the endpoint: open the address api/system/info of the endpoint in a browser, such as https://core.pki.rest/api/system/info. This address needs no API key and returns the version of the instance:

{"productName":"Lacuna Rest PKI Core","productVersion":"5.0.5 RTM","spaVersion":"...","timestamp":"..."}

Then, check the API key by creating a signature session. On .NET:

using Lacuna.RestPki.Api.SignatureSessions;

var response = await restPkiService.CreateSignatureSessionAsync(new CreateSignatureSessionRequest() {
ReturnUrl = "https://localhost:5001/signature-callback",
});

// Send the user to response.RedirectUrl

Calling the API directly:

curl -X POST "https://core.pki.rest/api/signature-sessions" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "returnUrl": "https://localhost:5001/signature-callback" }'

The response brings the ID of the session and the URL of its signature page:

{
"sessionId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"redirectUrl": "https://core.pki.rest/..."
}

Open the redirectUrl in a browser to see the page where your users will sign. If the call fails instead:

  • 401: the API key was not sent or is wrong. Check that you copied the whole key, including the application name before the |
  • 403: the application doesn't have the Worker role (see Choosing roles)
  • Endpoint unreachable: check the address of the endpoint and whether your server can reach it

Next steps​

View as Markdown