---
title: "Integration guide - Amplia"
description: "Amplia API integration guide: API key, endpoint and client libraries, then the issuance flows (issue link, CSR, PKCS #12, attribute certificates), revocation and errors."
canonical: "https://docs.lacunasoftware.com/en-us/articles/amplia/integration"
locale: "en"
product: "Amplia"
last_updated: "2026-10-12"
---

# Integration guide - Amplia

Your system can create certificate orders and issue certificates through [Amplia](https://docs.lacunasoftware.com/en-us/articles/amplia)'s REST API, while operators manage CAs,
templates and orders on the dashboard.  This guide covers the API calls; for a
one-page summary, see the [Amplia quick reference](https://docs.lacunasoftware.com/en-us/articles/amplia/quick-reference).

## Before you start

You need three values: 

* **API key**: every request sends your application's API key in the `X-Api-Key` header, in the form `yourapp|xxxx…`. 
  To get one, [create an application and an API key](https://docs.lacunasoftware.com/en-us/articles/amplia/integration#api-key) on the Amplia dashboard.
* **Endpoint**: the address of the Amplia instance, prefixed to every relative URL of the API. 
  Lacuna's cloud instance is `https://amplia.lacunasoftware.com/`, the default in the samples; with an on-premises instance, use the
  [dashboard domain](https://docs.lacunasoftware.com/en-us/articles/amplia/on-premises#dashboard-domain) you chose. 
  TODO(docs): no separate sandbox or test endpoint is documented.
* **CA id**: the id of the CA that issues the certificates, sent as `caId` when you create an order. The samples keep it in their
  configuration next to the API key; the attribute certificate sample uses a second CA, since attribute certificates need a CA set up
  for them. 
  The samples' comments add that an application can have a default CA, in which case `caId` can be left out. 
  TODO(docs): where a default CA is set for an application.

The API observes the `Accept-Language` header (`en-US` or `pt-BR`), which also sets the language of the issue links it returns; error
messages are not affected by it. 

### Create an application and an API key

Your system calls the API as an **application** of an Amplia subscription, with a role that decides what it can do: 

1. Sign in to the Amplia dashboard and click **Applications** on the left menu, then *Add*.
1. Fill out a name, select the subscription on which the certificates are issued and mark the application's role (see below), then
   click *Create*.
1. Click **Keys**, then *Add*. Fill out a description and an expiration, then click *Create*.
1. Copy the API key: it cannot be retrieved later.

| Role | Create orders, have Amplia email or text the issue link, revoke | Get the issue link or QR code, issue certificates | Webhook settings |
|---|---|---|---|
| **Worker** | Yes | Yes | No |
| **Registration Agent** | Yes | No | No |
| **Manager**, **Admin** | Yes | Yes | Yes |

A system that runs the whole flow needs **Worker**, the role that [Amplia Reg](https://docs.lacunasoftware.com/en-us/articles/amplia-reg) also uses. A **Registration
Agent** application can create orders and send the holder the issue link by email or SMS, but cannot read the link or issue the
certificate itself. 

## Client libraries

Any HTTP client can call the API, whose OpenAPI description is at https://docs.lacunasoftware.com/openapi/amplia.json. Lacuna publishes
client libraries, which the samples use: 

| Language | Package | Registry |
|---|---|---|
| .NET | `Lacuna.Amplia.Client` | [NuGet](https://www.nuget.org/packages/Lacuna.Amplia.Client) |
| Java | `com.lacunasoftware.amplia:amplia-client` | [Maven Central](https://central.sonatype.com/artifact/com.lacunasoftware.amplia/amplia-client) |
| Node.js | `amplia-client` | [npm](https://www.npmjs.com/package/amplia-client) |
| PHP | `lacuna/amplia-client` | [Packagist](https://packagist.org/packages/lacuna/amplia-client) |
| Python | `amplia-client` | [PyPI](https://pypi.org/project/amplia-client/) |

The client majors don't follow Amplia's version: every endpoint that the 1.x clients below call is served by Amplia 5.0.1. 
The .NET client is described [below](https://docs.lacunasoftware.com/en-us/articles/amplia/integration#dotnet-client).

The Java (1.2.1), Node.js (1.3.3), PHP (1.3.0) and Python (1.0.0) clients wrap these calls: 

| Operation | Node.js, Java, PHP | Python | Endpoint |
|---|---|---|---|
| Create an order | `createOrder` | `create_order` | `POST /api/orders/{format}` |
| Get an order | `getOrder` | `get_order` | `GET /api/v2/orders/{id}` (Java: `GET /api/orders/{format}/{id}`) |
| Get the issue link | `getOrderIssueLink` | `get_order_issue_link` | `GET /api/orders/{id}/issue-link` |
| Issue from a CSR | `issueCertificate` | `issue_certificate` | `POST /api/v2/certificates` |
| Issue a PKCS #12 file | `issuePkcs12Certificate` (Node.js only) | | `POST /api/certificates/pkcs12` |
| Revoke a certificate | `revokeCertificate` | `revoke_certificate` | `DELETE /api/certificates/{id}` |

None of the four sends the issue link by email or SMS or reads its QR code: call those endpoints directly, or use the .NET client (see
[Other ways to deliver the issue link](https://docs.lacunasoftware.com/en-us/articles/amplia/integration/issue-on-user-machine#deliver-the-link)). 

Each sample creates the client from the endpoint and the API key: 

**Node.js**

```js
const { AmpliaClient } = require("amplia-client");

static getAmpliaClient() {
	let CONFIG = Config.getInstance().get('amplia');
	let key = CONFIG['apiKey'];
	let endpoint = CONFIG['endpoint'];
	return new AmpliaClient({
		endpoint: endpoint,
		apiKey: key
	});
}
```

**Java**

```java
import com.lacunasoftware.amplia.AmpliaClient;

public static AmpliaClient getAmpliaClient() {
	String apiKey = getProperties().getAmplia().getApiKey();
	String endpoint = getProperties().getAmplia().getEndpoint();
	if (endpoint == null || endpoint.length() == 0) {
		endpoint = "https://amplia.lacunasoftware.com/";
	}
	return new AmpliaClient(endpoint, apiKey);
}
```

**PHP**

```php
use Lacuna\Amplia\AmpliaClient;

public static function getAmpliaClient()
{
    $config = getConfig();
    $ampliaApiKey = $config['amplia']['apiKey'];
    $ampliaEndpoint = $config['amplia']['endpoint'];
    return new AmpliaClient($ampliaEndpoint, $ampliaApiKey);
}
```

**Python**

```python
from amplia_client import AmpliaClient

def get_amplia_client():
    api_key = current_app.config['AMPLIA_API_KEY']
    endpoint = current_app.config['AMPLIA_ENDPOINT']
    return AmpliaClient(endpoint, api_key)
```

### .NET client

`Lacuna.Amplia.Client` 5.0.0 targets .NET Standard 2.0 and is built from the same source as Amplia 5.0.1. Get an `IAmpliaService`
from dependency injection, after `services.AddAmplia(...)`, or from `AmpliaServicesFactory.GetService(endpoint, apiKey)`; the
`AmpliaClient` class still works, but is marked `[Obsolete]`. 

```csharp
using Lacuna.Amplia.Api;
using Lacuna.Amplia.Api.CertificateFormatting;
using Lacuna.Amplia.Api.Orders;
using Lacuna.Amplia.Client;

IAmpliaService amplia = AmpliaServicesFactory.GetService("https://amplia.lacunasoftware.com/", apiKey);

var order = await amplia.CreateOrderAsync(new CreateOrderRequest2<PkiBrazilCertificateParameters> {
	CAId = caId,
	Kind = CertificateKinds.PublicKey,
	ValidityEnd = DateTimeOffset.Now.AddYears(2),
	Parameters = new PkiBrazilCertificateParameters {
		Name = subjectName,
		Cpf = cpf,
		PhoneNumber = phoneNumber,
	},
});
string issueLink = await amplia.GetOrderIssueLinkAsync(order.Id, returnUrl);
```

In ASP.NET Core, `services.AddAmplia(o => { o.Endpoint = …; o.ApiKey = …; })`, or `services.AddAmplia().Configure(configuration.GetSection("Amplia"))`,
registers `IAmpliaService`; `AmpliaOptions` also has `Timeout`, `Culture` (sent as `Accept-Language`) and `DefaultSubscriptionId`. 

| Operation | .NET method | Endpoint |
|---|---|---|
| Create an order | `CreateOrderAsync` | `POST /api/orders/{format}` (`POST /api/v2/orders` for the non-generic request) |
| Get an order | `GetOrderAsync` | `GET /api/v2/orders/{id}` |
| Get the issue link | `GetOrderIssueLinkAsync` | `GET /api/orders/{id}/issue-link` |
| Email or text the issue link | `SendIssueEmailAsync`, `SendIssueSmsAsync` | `POST /api/orders/{id}/send-issue-email-request`, `POST /api/v2/orders/{id}/send-issue-sms-request` |
| Get the QR code | `GetOrderIssueQRCodeDataAsync`, `GetOrderIssueQRCodeImageAsync` | `GET /api/orders/{id}/issue-qrcode-data`, `issue-qrcode-image` |
| Issue from a CSR | `IssueCertificateAsync` | `POST /api/v2/certificates` |
| Issue a PKCS #12 file | `IssuePkcs12CertificateAsync` | `POST /api/certificates/pkcs12` |
| Get a certificate | `GetCertificateAsync` | `GET /api/v2/certificates/{id}` |
| Revoke a certificate | `RevokeCertificateAsync` | `DELETE /api/certificates/{id}` |

API errors (422) throw `AmpliaException`, whose `Code` is the error code, or `OrderLockedException` when the code is `OrderLocked`. 

## How issuance works

Every certificate starts with an **order** on a CA, which holds the holder's data and the certificate's validity. The order is then
fulfilled, issuing one certificate, in one of these ways: 

| Where the key pair is made | How you issue | Page |
|---|---|---|
| On the holder's computer, by Amplia's issue page | Send the holder an issue link | [Issue on the holder's machine](https://docs.lacunasoftware.com/en-us/articles/amplia/integration/issue-on-user-machine) |
| On your server, or in the user's browser with Web PKI | Send Amplia a CSR | [Issue from a CSR](https://docs.lacunasoftware.com/en-us/articles/amplia/integration/issue-from-csr) |
| By Amplia, which returns it in a password-protected file | Ask for a PKCS #12 (.pfx) | [Issue a PKCS #12 file](https://docs.lacunasoftware.com/en-us/articles/amplia/integration/pkcs12) |
| No key pair: the certificate attests an attribute of the holder | Issue without a CSR | [Attribute certificates](https://docs.lacunasoftware.com/en-us/articles/amplia/integration/attribute-certificates) |

Start with [Create certificate orders](https://docs.lacunasoftware.com/en-us/articles/amplia/integration/orders). Then:

* [Issue on the holder's machine](https://docs.lacunasoftware.com/en-us/articles/amplia/integration/issue-on-user-machine)
* [Issue from a CSR](https://docs.lacunasoftware.com/en-us/articles/amplia/integration/issue-from-csr)
* [Issue a PKCS #12 file](https://docs.lacunasoftware.com/en-us/articles/amplia/integration/pkcs12)
* [Attribute certificates](https://docs.lacunasoftware.com/en-us/articles/amplia/integration/attribute-certificates)
* [Revoke certificates](https://docs.lacunasoftware.com/en-us/articles/amplia/integration/revocation)
* [Errors](https://docs.lacunasoftware.com/en-us/articles/amplia/integration/errors)

## Webhook

Amplia can notify your system whenever a certificate is issued: the notification body is a `WebhookEventModel` whose `type` is
`OrderCertificateIssued`, with the `order` and, once issued, the `certificate`. 

The webhook belongs to the subscription. A user with the **Admin** or **Manager** role sets it on the dashboard, under **Settings** >
**Webhook configuration**: 

* **Enable webhook**, the **URL** that Amplia posts the notification to, and the **Authentication type**, which decides the header
  Amplia sends with each notification:

  | Authentication type | Header |
  |---|---|
  | `NoAuth` | No authentication header |
  | `Bearer` | `Authorization: Bearer <token>` |
  | `ApiKey` | `X-Api-Key: <key>` |
  | `CustomAuthorizationHeader` | `Authorization: <scheme> <value>` |
  | `Basic` | `Authorization: Basic <value>` (see the caution below) |

* The **Recent calls** tab lists the notifications sent, with the status code and, for failed calls, the response. 

Amplia sends a `POST` with a JSON body and counts any 2xx answer as delivered. The JSON keeps the property names of Amplia's models,
in PascalCase (`Type`, `Order`, `Certificate`), with enums as names: 

```json
{
  "Type": "OrderCertificateIssued",
  "Order": { "Id": "…", "Status": "Issued", "CertificateId": "…" },
  "Certificate": { "Id": "…" }
}
```

> **Caution: Basic authentication**
>
> With `Basic`, the dashboard encodes the user name and the password separately and joins them with a colon,
> `base64(user):base64(password)`, instead of the standard `base64(user:password)`. A standard Basic authentication handler rejects that
> value, so prefer `Bearer`, `ApiKey` or `CustomAuthorizationHeader`.

TODO(docs): whether and how often Amplia retries a failed notification.

## See also

* [Amplia quick reference](https://docs.lacunasoftware.com/en-us/articles/amplia/quick-reference)
* [Operation Guide](https://docs.lacunasoftware.com/en-us/articles/amplia/operation)
* [Changelog](https://docs.lacunasoftware.com/en-us/articles/amplia/changelog)
