---
title: "GeCert API"
description: "GeCert REST API: authentication, the key, certificate, access, key store, usage and report routes with the permissions they require, the API used by Gecert Connect and the error codes."
canonical: "https://docs.lacunasoftware.com/en-us/articles/gecert/api"
locale: "en"
product: "GeCert"
last_updated: "2026-10-13"
---

# GeCert API

The [GeCert](https://docs.lacunasoftware.com/en-us/articles/gecert) REST API is the one the web application and [Gecert Connect](https://docs.lacunasoftware.com/en-us/articles/gecert/gecert-connect) use. The full description of the
routes and models is in your instance's Swagger, at `https://your-gecert-address/swagger`. 

## Authentication

Requests carry the `Authorization: Bearer YOUR_TOKEN` header, with an access token issued by the instance's [GrantID](https://docs.lacunasoftware.com/en-us/articles/grant-id)
for the GeCert API (the server's `Oidc:ApiName` setting). It is the same token the web application obtains when the user signs in and that
Gecert Connect obtains at login. The organization-area routes operate on the organization the user belongs to, as the web application
does. 

Only the application configuration routes are anonymous: 

| Route | Response |
|---|---|
| `GET /api/app-configuration` | `{"hidePoweredBy": false}` |
| `GET /api/app-configuration/gecert-connect` | The minimum Gecert Connect version and whether the server is under maintenance: `{"minSupportedVersion": "1.1.0.0", "underMaintenance": false}` |
| `GET /api/app-configuration/gecert-connect/server` | The server address and the GrantID data for Gecert Connect: `serverUrl`, `grantIdAuthority`, `grantIdClientAppId`, `grantIdApiName`, `grantIdRedirectUri`. Error `GecertConnectServerNotConfigured` if the [`GecertConnect`](https://docs.lacunasoftware.com/en-us/articles/gecert/on-premises/configure-gecert-connect) section is not filled in |
| `GET /api/system/info` | The product name and version: `{"productName":"Gecert","productVersion":"1.x.x"}` |

## Routes

The lists (`.../list`) are paginated and accept the `q` (search), `offset`, `limit` and `order` parameters. The permission of each route
is checked on the resource's organization; in the Sys Admin area, on the root. 

### Keys

| Route | What it does | Permission |
|---|---|---|
| `GET /api/keys/list` | Lists the organization's keys | `ViewKeys` |
| `GET /api/keys/available/list` | Lists the keys that have no certificate yet | `ViewKeys` |
| `GET /api/keys/{id}/summary` | Key summary: name, organization, certificate and key store type | `ViewKeys` |
| `GET /api/keys/{id}/details` | Details: type, size and key store type. Answers with the `CannotRetrieveKeyFromKeyStore` failure when the key is not found in the key store | `ViewKeys` |
| `GET /api/keys/{id}/csr` | The CSR kept for the key, in PEM, with the subject name and the hash algorithm | `ViewKeys` |
| `POST /api/keys/{id}/custom-csr` | Issues a new CSR for the key. Body: `{"params": "CN=...,O=...", "hashAlgorithm": "SHA256"}` | `ManageKeys` |
| `GET /api/keys/{id}/parameters` | The key's parameters in the key store, as JSON. Error `KeyStoreParametersNotAccessible` if the store does not allow key registration | `ViewKeys` |
| `GET /api/keys/{id}/parameters/accessible` | Whether the parameters can be read (`true` or `false`) | `ViewKeys` |
| `GET /api/keys/{id}/events` | The key's events, paginated | `ViewKeys` |
| `PUT /api/keys` | Registers a key that already exists in the key store. Body: `{"parameters": {"keyStore": "...", "keyName": "...", "keyStoreParameters": {...}}}` ([see below](https://docs.lacunasoftware.com/en-us/articles/gecert/api#key-registration-parameters)) | `ManageKeys` |
| `PUT /api/keys/{id}` | Renames the key. Body: `{"name": "..."}` | `ManageKeys` |
| `DELETE /api/keys/{id}` | Deletes the key (and removes it from the key store when [hard deletion](https://docs.lacunasoftware.com/en-us/articles/gecert#key-stores) is configured). Error `GecertKeyHasActiveCertificate` if it has a certificate | `ManageKeys` |

### Certificates

| Route | What it does | Permission |
|---|---|---|
| `GET /api/certificates/list` | Lists the organization's certificates, with the number of authorized users | `ViewCertificates` |
| `GET /api/certificates/{id}` | Details: subject, issuer, type, e-mail, validity, SHA-1 thumbprint and the key ID | `ViewCertificates` |
| `GET /api/certificates/{id}/events` | The certificate's events, paginated | `ViewCertificates` |
| `GET /api/certificates/{id}/usage` | The [key usages](https://docs.lacunasoftware.com/en-us/articles/gecert/api#key-usages) of the certificate, paginated | `ViewCertificates` |
| `GET /api/certificates/{id}/authorized-users` | The users with access to the certificate, paginated | `ViewCertificateAccess` |
| `GET /api/certificates/{id}/public-bytes` | The encoded certificate (DER), in Base64 | Certificate access (`UseKey`) |
| `GET /api/certificates/my` | The certificates the authenticated user has access to | Authenticated user |
| `POST /api/certificates` | Adds a certificate from a PKCS #12 uploaded beforehand. Body: `{"blobId": "...", "keyStoreName": "...", "password": "..."}`. Failures: `CertificatePasswordIsIncorrect`, `CertificateAlreadyExistsOnSubscription`, `CertificateIsExpectedToHaveRsaKeys` | `ManageCertificates` |
| `PUT /api/certificates` | Registers a certificate (`.cer`) for an existing key. Body: `{"blobId": "...", "keyId": "..."}`. Failures: `CertificateIsNotExpectedToHavePassword`, `CertificateAlreadyExistsOnSubscription`, `KeysAreNotEquivalent` | `ManageCertificates` |
| `DELETE /api/certificates/{id}` | Deletes the certificate, its accesses and its key | `ManageCertificates` |

The responses of `POST` and `PUT /api/certificates` have the format `{"success": true, "id": "..."}` or
`{"success": false, "failure": "CertificatePasswordIsIncorrect", "failureType": "NewCertificateResponseFailures"}`.

### Certificate accesses

| Route | What it does | Permission |
|---|---|---|
| `GET /api/certificate-access` | Lists the organization's accesses, paginated | `ViewCertificateAccess` |
| `POST /api/certificate-access` | Grants access. Body: `{"certificateId": "...", "userId": "..."}`. Failures: `CertificateAccessAlreadyExists`, `UserNeedsSubscriptionAccess`, `UserHasAccessToThisCertificateInAnotherSubscription` | `ManageCertificateAccess` |
| `DELETE /api/certificate-access/{id}` | Removes one access | `ManageCertificateAccess` |
| `DELETE /api/certificate-access/certificates/{certificateId}` | Removes every access to a certificate | `ManageCertificateAccess` |
| `DELETE /api/certificate-access/users/{userId}` | Removes every access of a user in the organization | `ManageCertificateAccess` |
| `POST /api/certificate-access/certificates/{from}/to/{to}` | Copies every access from one certificate to another. The response lists the result for each user | `ManageCertificateAccess` on both certificates |
| `GET /api/users/{userId}/authorized-certificates` | The certificates a user has access to | `ViewCertificateAccess` |
| `GET /api/users/{userId}/subscription-access/verification` | Whether the user has access to the organization (`true` or `false`) | `ViewCertificateAccess` |

### Key stores

| Route | What it does | Permission |
|---|---|---|
| `GET /api/key-stores` | The key stores the organization has access to: name, type, whether it is the default, whether it accepts key registration and insertion, hard delete, key sizes and name pattern | `ManageKeys` |
| `GET /api/key-stores/{type}/example` | An example of the registration parameters for the type (`Kryptus`, `AzureKeyVault` or `Pkcs11`) | `ManageKeys` |
| `GET /api/key-stores/list` | Every key store configured in the instance, paginated | `Read` on the root (Sys Admin) |
| `GET /api/key-stores/details?name=...` | The details of a key store, by type: for Azure Key Vault, the endpoint, the application ID and whether it uses HSM; for Kryptus, the host, port and users; for PKCS #11, the module and the token serial number | `Read` on the root (Sys Admin) |
| `GET /api/subscriptions/my/key-stores` | The organization's key store accesses | `ManageKeys` |
| `GET /api/subscriptions/{id}/key-stores` | The key store accesses of an organization, paginated | `ViewKeyStoreAccess` on the root |
| `POST /api/key-store-access` | Grants an organization access to a key store. Body: `{"subscriptionId": "...", "keyStoreName": "..."}`. Failure: `KeyStoreAccessAlreadyExists` | `ManageKeyStoreAccess` on the root |
| `DELETE /api/key-store-access/{id}` | Removes the access. The keys already on the key store continue to work | `ManageKeyStoreAccess` on the root |

### Key usages

| Route | What it does | Permission |
|---|---|---|
| `GET /api/key-usages/list` | The usages of the organization's keys, paginated: date, certificate, user, operation (`Encrypt`, `Decrypt`, `Sign` or `Verify`), algorithm, hash, value and, for verifications, whether the signature was valid | `ViewCertificates` |

### Reports

| Route | What it does | Permission |
|---|---|---|
| `POST /api/reports/certificates/expiration-date` | Generates the expiration report of the organization's certificates (name, e-mail and expiration date). Body: `{"fileType": "Xlsx"}`, `"Csv"` or `"Pdf"` | `ManageCertificates` |
| `POST /api/reports/certificates/{id}/events` | Generates the report of the events of one certificate (date, entity, operation, details, agent and organization) | `ManageCertificates` |
| `GET /api/reports/{id}?fileType=...` | Downloads the generated report | Access ticket returned by the generation |

The generation answers with `{"success": true, "ticket": {"location": "..."}}`, where `location` is the address to download the file; or
with the `EmptyReport` failure, when there is nothing to include. 

## API used by Gecert Connect

These routes, also under `/api/keys`, are the ones [Gecert Connect](https://docs.lacunasoftware.com/en-us/articles/gecert/gecert-connect#use-by-applications) calls on behalf of the Lacuna
Key Storage Provider. They only see the keys of the certificates the authenticated user has access to, and every operation with the private
key requires the `UseKey` permission and is recorded in the key usages. 

| Route | What it does |
|---|---|
| `GET /api/keys` | The user's keys: `[{"id": "...", "attributes": {"enabled": true}}]` |
| `GET /api/keys/{id}` | The public key: `{"id": "...", "keyType": "RSA", "keyOperations": ["Encrypt", "Decrypt", "Sign", "Verify", "WrapKey", "UnwrapKey"], "rsaModulus": "...", "rsaPublicExponent": "...", "managed": true}`, with the modulus and exponent in Base64 |
| `POST /api/keys` | Creates an RSA key in the current organization. Body: `{"keyName": "...", "keyStore": "...", "keySize": 2048, "keyType": "RSA"}`. Requires `ManageKeys` |
| `POST /api/keys/{id}/signature` | Signs a hash. Body: `{"algorithm": "RS256", "value": "HASH_IN_BASE64"}`; `algorithm` can be `RS256` (default) or `RS512`. Response: the signature, in Base64 |
| `POST /api/keys/{id}/decryption` | Decrypts. Body: `{"algorithm": "RSA1_5", "value": "DATA_IN_BASE64"}`; `RSA1_5` (PKCS #1 v1.5) is the only padding and the default. Response: the decrypted data, in Base64 |
| `POST /api/keys/{id}/encryption` | Encrypts with the certificate's public key. Same body and response |
| `POST /api/keys/{id}/signature-verification` | Verifies a signature with the public key. Body: `{"algorithm": "RS256", "value": "SIGNATURE_IN_BASE64", "digest": "HASH_IN_BASE64"}`. Response: `true` or `false` |
| `GET /api/keys/stopwatch-info`, `GET /api/keys/{id}/stopwatch-info` | The same responses as `GET /api/keys` and `GET /api/keys/{id}`, with the time spent in each step (database, key store connection, reading the parameters), used by **Check server connection** |

An algorithm other than the accepted ones answers with the `OperationAlgorithmNotSupported` error. 

## Key registration parameters

To register a key that already exists in the key store (`PUT /api/keys` or **Register existing key**), give the parameters that identify
it, according to the key store type. The `type` field is required, and `GET /api/key-stores/{type}/example` returns a template. GeCert
tests the parameters before saving: it reads the public key and signs a CSR with the key; if that fails, it answers with
`KeyStoreParametersFailedValidation`. 

| Key store | Parameters |
|---|---|
| Kryptus HSM | `{"type": "Kryptus", "publicKeyUniqueIdentifier": "...", "privateKeyUniqueIdentifier": "..."}`: the KMIP unique identifiers of the public and private keys |
| Azure Key Vault | `{"type": "AzureKeyVault", "keyName": "..."}` or `{"type": "AzureKeyVault", "kid": "https://.../keys/name/version"}`, with the optional `kty` (`RSA`, `RSA-HSM`, `EC` or `EC-HSM`) and `curveName` |
| PKCS #11 device | `{"type": "Pkcs11", "id": "...", "label": "..."}`: the key's ID (in Base64; in the web application, also in hexadecimal) or its label. At least one of the two |

The database key store does not accept key registration, and any key store can have registration disabled in the
[configuration](https://docs.lacunasoftware.com/en-us/articles/gecert/on-premises/configure-key-stores) (`KeyRegistrationDisabled`): the error is then `KeyStoreDoesNotSupportKeyRegistration`.

## Error codes

Errors have the format `{"code": "...", "message": "..."}`, with the matching HTTP status code. Besides the platform's common codes
(`SubscriptionNotFound`, `UserNotFound`, `UploadNotFound`, `RoleMissing` and others), GeCert defines: 

| Code | When it happens |
|---|---|
| `CertificateNotFound`, `GecertKeyNotFound`, `CertificateAccessNotFound`, `KeyStoreAccessNotFound` | The resource does not exist or does not belong to the organization |
| `SubscriptionMismatch` | The given key belongs to another organization |
| `BadKeyStore` | The given key store is not configured in the instance |
| `BadKeyStoreParameters` | The registration parameters could not be read |
| `KeyStoreParametersFailedValidation` | The key could not be used with the given parameters |
| `KeyParametersIncompatibleWithCertificate` | The key does not match the certificate |
| `KeyStoreDoesNotSupportKeyRegistration` | The key store does not accept registration of existing keys |
| `KeyStoreDoesNotSupportKeyInsertion` | The key store does not accept key generation or import (`KeyInsertionDisabled`) |
| `KeyStoreParametersNotAccessible` | The key parameters cannot be shown for this key store |
| `PinProtectionNotSupported` | The key store does not support partitions |
| `GecertKeyHasActiveCertificate` | The key cannot be deleted because it has a certificate |
| `OperationAlgorithmNotSupported` | The operation algorithm is not `RS256`, `RS512` or `RSA1_5` |
| `GecertConnectServerNotConfigured` | The server's `GecertConnect` section is not filled in |

## See also

* [GeCert](https://docs.lacunasoftware.com/en-us/articles/gecert)
* [Gecert Connect](https://docs.lacunasoftware.com/en-us/articles/gecert/gecert-connect)
* [Configure key stores](https://docs.lacunasoftware.com/en-us/articles/gecert/on-premises/configure-key-stores)
