REST API
CloudHub's API has eight operations. The client libraries wrap them, but any HTTP client can call them directly; this page documents the wire format. The same API is described interactively, as OpenAPI, at cloudhub.lacunasoftware.com/swagger.
Conventions
- Base URL:
https://cloudhub.lacunasoftware.com. - Authentication: every operation requires your API key in the
X-Api-Keyheader. A request without it, or with an unknown key, gets HTTP 401 with an empty body. - JSON: request and response bodies are JSON, with camelCase property names.
- Binary values (hashes, certificates, signatures) travel as base64 strings. The certificate and
sign-hash operations return a bare JSON string, such as
"MIIH…". - Enumerations travel as strings, such as
"SingleSignature"or"CPF". The numeric values the 1.x clients send (1forSingleSignature) are still accepted. - Timeouts: signing waits on the provider. Allow up to two minutes for
sign-hash.
| Operation | Purpose |
|---|---|
POST /api/sessions | Create a session at every provider that holds a certificate for the signer |
POST /api/sessions/services/{name} | Create a session at one provider |
GET /api/sessions/services | Discover providers without creating a session |
GET /api/sessions/services/{name}/availability | Ask one provider whether it holds a certificate |
GET /api/sessions/certificate | Read the session's certificate |
GET /api/v2/sessions/certificate | Read the session's certificate, with its alias and provider |
POST /api/sessions/sign-hash | Sign a hash with the session's certificate |
GET /api/sessions/custom-state | Read back the customState given when the session was created |
Sessions
POST /api/sessions
Creates a session. With an identifier, CloudHub runs discovery and returns only the providers that hold a certificate for it; without one, it returns every provider.
| Body field | Type | Required | Description |
|---|---|---|---|
redirectUri | string | Yes | Absolute URI CloudHub sends the user back to, with session appended. Must be registered for your key. |
identifier | string | No | The signer's CPF or CNPJ, digits only. |
identifierType | CPF or CNPJ | No | How to read identifier. When omitted, more than 11 digits means a CNPJ. |
type | session type | No | What the user authorizes. Defaults to SingleSignature. |
lifetimeInSeconds | integer | No | The session lifetime to ask the provider for. The provider may grant less. |
customState | string | No | Your own data, kept with the session and returned by GET /api/sessions/custom-state. |
discover | boolean | No | Whether to run discovery. Defaults to true when identifier is given. false returns every provider and passes identifier to each as a login hint. true requires identifier. |
curl https://cloudhub.lacunasoftware.com/api/sessions \
-H "X-Api-Key: $CLOUDHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{"identifier": "12345678909", "redirectUri": "https://app.example.com/sign/complete", "type": "SingleSignature"}'
The response is a SessionModel:
{
"services": [
{
"serviceInfo": {
"serviceName": "BirdID",
"provider": "SOLUTI",
"endpoint": "https://api.birdid.com.br/",
"badgeUrl": "https://cdn.lacunasoftware.com/img/psc/birdid.png"
},
"authUrl": "https://api.birdid.com.br/oauth/authorize?client_id=…"
}
]
}
Errors: InvalidRedirectUri, UnauthorizedRedirectUri, IdentifierRequiredToDiscover; HTTP 400
when redirectUri is missing.
POST /api/sessions/services/{name}
Creates a session at one provider, without discovery. Use it when the user has already chosen the
provider. name is a serviceName as CloudHub returns it, such as BirdID.
The body takes the same fields as POST /api/sessions except identifierType.
identifier, when given, is passed to the provider as a login hint; discover is ignored.
The response is a single TrustServiceAuthParametersModel:
serviceInfo and authUrl.
Errors: ServiceNotFound (with details.name), InvalidRedirectUri, UnauthorizedRedirectUri.
Discovery
GET /api/sessions/services
Runs discovery without creating a session, and returns the providers that hold a certificate for
the identifier as a list of TrustServiceInfoModel. There is no authUrl
in this response.
| Query parameter | Required | Description |
|---|---|---|
identifier | Yes | The CPF or CNPJ, digits only. |
identifierType | No | CPF (default) or CNPJ. |
curl "https://cloudhub.lacunasoftware.com/api/sessions/services?identifier=12345678909" \
-H "X-Api-Key: $CLOUDHUB_API_KEY"
A provider that fails to answer is left out of the list.
GET /api/sessions/services/{name}/availability
Asks one provider whether it holds a certificate for the identifier. Takes the same query
parameters as GET /api/sessions/services.
{
"discoveryAvailable": true,
"certificateFound": true
}
discoveryAvailable is false when the provider could not answer; certificateFound is then
null.
Errors: ServiceNotFound (with details.name).
Using a session
These operations take the session value your redirect URI received. They fail with
SessionInvalidOrAlreadyUsed when CloudHub doesn't know the session or the provider no longer
accepts it. The certificate and sign-hash operations also fail with SessionExpired once the
session's lifetime is over.
GET /api/sessions/certificate
Returns the session's certificate, DER-encoded and then base64-encoded, as a JSON string. When the provider holds several certificates for the user, CloudHub picks the one that is currently valid and most recently issued.
curl "https://cloudhub.lacunasoftware.com/api/sessions/certificate?session=9f2c…e81a" \
-H "X-Api-Key: $CLOUDHUB_API_KEY"
"MIIHGjCCBQKgAwIBAgI…"
GET /api/v2/sessions/certificate
Returns the same certificate as a CertificateModel, with its alias and the
provider's service name:
{
"content": "MIIHGjCCBQKgAwIBAgI…",
"alias": "a5f1…",
"serviceName": "BirdID"
}
Pass alias to sign-hash as certificateAlias to sign with exactly this certificate.
POST /api/sessions/sign-hash
Signs a hash with the user's key and returns the signature value, base64-encoded, as a JSON string.
| Body field | Type | Required | Description |
|---|---|---|---|
session | string | Yes | The session value. |
hash | string | Yes | The hash to sign, base64-encoded. |
digestAlgorithmOid | string | One of these two | The OID of the hash's digest algorithm, such as 2.16.840.1.101.3.4.2.1 for SHA-256. Takes precedence over digestAlgorithm. |
digestAlgorithm | string | One of these two | The algorithm's name, such as SHA-256. |
certificateAlias | string | No | The certificate to sign with, from GET /api/v2/sessions/certificate. Defaults to the certificate GET /api/sessions/certificate returns. |
curl https://cloudhub.lacunasoftware.com/api/sessions/sign-hash \
-H "X-Api-Key: $CLOUDHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{"session": "9f2c…e81a", "hash": "n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg=", "digestAlgorithmOid": "2.16.840.1.101.3.4.2.1"}'
"Qy1kZ3N0b3JlIHNpZ25hdHVyZSB2YWx1ZS4uLg…"
Errors: DigestAlgorithmNameOrOidIsRequired, InvalidDigestAlgorithm, SessionExpired,
SessionInvalidOrAlreadyUsed.
GET /api/sessions/custom-state
Returns the customState given when the session was created, as a JSON string, or null when
there was none. The session query parameter is required.
Errors: SessionInvalidOrAlreadyUsed.
Models
SessionModel
| Field | Type | Description |
|---|---|---|
services | TrustServiceAuthParametersModel[] | One entry per provider. Empty when none holds a certificate for the identifier. |
TrustServiceAuthParametersModel
| Field | Type | Description |
|---|---|---|
serviceInfo | TrustServiceInfoModel | The provider. |
authUrl | string | Where to send the user to authorize at this provider. |
TrustServiceInfoModel
| Field | Type | Description |
|---|---|---|
serviceName | string | The provider's name in CloudHub, such as BirdID. It goes in the path of the single-provider operations. |
provider | string | The company that operates the service, such as SOLUTI. |
endpoint | string | The provider's API address. |
badgeUrl | string | The provider's logo. May be null. |
CertificateModel
| Field | Type | Description |
|---|---|---|
content | string | The certificate, DER-encoded, then base64-encoded. |
alias | string | The certificate's identifier at the provider. |
serviceName | string | The provider the certificate came from. |
GetServiceAvailabilityResponse
| Field | Type | Description |
|---|---|---|
discoveryAvailable | boolean | Whether the provider answered. |
certificateFound | boolean or null | Whether it holds a certificate for the identifier. Null when it did not answer. |
TrustServiceSessionTypes
SingleSignature, MultiSignature, SignatureSession, AuthenticationSession. See
Session types.
IdentifierTypes
CPF, CNPJ.
Errors
| HTTP status | Body | Meaning |
|---|---|---|
| 400 | A validation problem, listing the fields | A required field is missing or malformed, such as redirectUri. |
| 401 | Empty | The X-Api-Key header is missing or the key is unknown. |
| 422 | { "code", "message", "details" } | CloudHub refused the request. code is one of the codes below. |
| 500 | A JSON string with a short code, such as "4F1A2B" | An unexpected failure, often at the provider. Quote the code to Lacuna support. |
{
"code": "UnauthorizedRedirectUri",
"message": "Unauthorized redirect URI",
"details": {
"redirectUri": "https://app.example.com/sign/complete"
}
}
| Code | Meaning | What to do |
|---|---|---|
InvalidRedirectUri | redirectUri is not an absolute URI. | Send a full URI, with scheme and host. |
UnauthorizedRedirectUri | redirectUri is not registered for your key. details.redirectUri shows it. | Ask Lacuna support to register it. See Redirect URIs. |
IdentifierRequiredToDiscover | discover is true but there is no identifier. | Send the identifier, or drop discover. |
ServiceNotFound | No provider has that name. details.name shows it. | Use a serviceName CloudHub returned. |
DigestAlgorithmNameOrOidIsRequired | sign-hash has neither digestAlgorithm nor digestAlgorithmOid. | Send one of them. |
InvalidDigestAlgorithm | The digest algorithm name or OID is not recognized. | Send the OID your signature library reports. |
SessionInvalidOrAlreadyUsed | CloudHub doesn't know the session, or the provider no longer accepts it, for example because it was already used. | Create a new session. |
SessionExpired | The session's lifetime is over. It can happen on the first use, when the user took long to authorize. | Create a new session and send the user to the provider again. |