Authentication
Authentication is required to use T-API. Due to possible access restrictions for classic users, the concept of a technical user has been implemented. In order to create one, go to the API tab in the Pergamin. If you do not see the API tab in the system, please contact our support team.
Each technical user has three authentication methods available:
- Basic: Bearer token
Recommended for most use cases.
- Advanced: Pergamin certificate
Recommended for high security use cases.
- Advanced: Custom certificate
Recommended for higher than basic use cases, when it is not possible to use Pergamin certificate.
Bearer token
The default and easiest to implement authentication method that is created automatically for each technical user is the Bearer token. This is the token that must be passed in the Authorization header every time the T-API is queried. The token is automatically generated when a technical user is created and is visible in the user's details. The token has an unlimited validity period, but can be reset at any time by the organization's administrator.
Warning
Once reset, the previous bearer token is no longer valid and a new one must be used.
Warning
The token is a secret and should be treated as such. It is recommended to store it in a secure place, e.g. in a password manager. You won't be able to see it again after closing the window.
curl https://ext-api.pergam.in/ext-api/v2/documents \
-H "Accept: application/json"
-H "Authorization: Bearer {token}"
Pergamin certificate
A Pergam certificate is an X.509 certificate signed by Pergamin CA. To generate one, follow these steps:
- Generate private key using
opensslcommand: -
Generate CSR (Certificate Signing Request):
Note
In place of
[technical_user_id]you should put the ID of the technical user, and in place of[organisation_id]the ID of the organization to which the technical user belongs. -
Click
Pergamin certificatein the API tab near the technical user for which you want to generate the certificate and upload the CSR file generated in previous step.
CSR uploading window -
Download the certificate (the certificate will be available for download only immediately after it is generated, it will not be possible to download it again).
Now you can use the certificate to sign requests to the API using the procedure described in the Signing requests using certificate section.
Custom certificate
In case there is no possibility to use Pergamin certificate (e.g. for technical reasons), it is possible to upload your own certificate and sign requests to the T-API using it.
Warning
In this case, only the signature and certificate validity date will be validated.
To enable this authentication method, you must upload the certificate in PEM format by clicking Custom certificate next to the selected technical user.
Warning
Using your own certificate excludes the possibility of using the Pergamin certificate. At the same time, you can use only one of these authentication methods.
As in the case of the Pergamin certificate, you can now start using your private key and certificate to sign requests to the API using the procedure described in the Signing requests using certificate section.
Signing requests using certificate
Prerequisites
To authenticate using Certificate you must provide following headers:
- Certificate
- certificate encoded in base64 format. Certificate must be in PEM format. Certificate must be signed by Pergamin CA. Certificate must be valid at the time of request. Certificate must be valid for the technical user for which the request is made.
- ClientId
- certificate subject but represented as
RFC4514string. - Signature
- HMAC signature generated for each request individually (If request signature is invalid, request will be rejected) is required as well. This header is not required only when requesting endpoints from section Certificates and Health. Generating signature will require adding more headers wich allow our API to resolve correctness of sent signature, which is described in next section.
- Timestamp:
- epoch timestamp. Requests which are delivered after 15 seconds are considered to be invalid. Allowed values is e.g.
1660060402.879557(from Python) and1660060402(for PHP). Both of them are correct, only first part is taken into account.
Algorithm
- RequestKeySignature: Generate request key (64 bytes long) and generate signature using client private key (e.g.
pkey.pemfrom Pergamin Certificate section) usingSHA256algorithm withPSSpadding usingMGF1+SHA256algorithms, then encode asbase64. - Payload: Prepare request payload if any. Serialize to JSON then compress/encode using gzip and then encode to
base64. -
PayloadDigest: Calculate payload digest. Use
SHA256algorithm on payload and then encode binary result tobase64as string.Note
Set empty string if payload is empty
-
Prepare headers array:
Header Value Description SignatureVersion2Version of signature algorithm (always set to 2)SignatureMethodHmacSHA256Signature algorithm (always set to RSASSA-PSS)ClientIdie. O=237,CN=26Certificate subject in RFC4514 notation RequestKeySignaturerandom (64 bytes length) Random signature key Timestampie. 1660060402.879557Current timestamp in seconds (microseconds are also allowed) PayloadDigestsha256 hash of payload Empty string if payload is empty, otherwise value from step 3. Content-Typetext/plainContent type of request payload Acceptapplication/jsonContent type of response payload -
RequestHeaders: Sort this array by header name ascendingly and serialize to JSON.
-
Create string to be signed: HTTPVerb + "\n" + RequestHeaders + "\n" + HTTPRequestURI where:
* HTTPVerb is name of request method e.g POST (always in uppercase
RFC2616)* RequestHeaders is a JSON dump generated in previous step
* HTTPRequestURI is an request URI encoded according to
RFC3986 -
Prepare HMAC compliant
RFC2104with prepared string from previous step using SHA256 algorithm. Then encode tobase64. Use resulting value as the value of Signature header. - RequestKeyEncrypted: Encrypt request key using Pergamin's External API certificate public key, which you can retrieve using this API. For encryption use OAEP padding with MGF1 and SHA256 algorithms. Encrypted value encode to base 64.
- Append RequestKeyEncrypted and Certificate to request headers.
-
Headers send within request should be as follows:
SignatureVersionSignatureMethodClientIdRequestKeySignatureTimeStampPayloadDigestContent-TypeAcceptSignatureRequestKeyEncryptedCertificate
Pseudocode example
# 1. Generate random request key and sign it with private key
bytes request_key = random(64)
private_key pkey = load_private_key('pkey.pem')
bytes request_key_signature = pkey.sign(
bytes: request_key,
padding: PSS(padding: MGF1, salt: PSS.MAX_LENGTH),
hash: SHA256
)
# 2. Compress and encode payload data
bytes payload = gzip.compress(payload)
string payload = base64.encode(payload)
# 3. Calculate payload digest
bytes hash = sha256(payload)
string payload_digest = base64.encode(hash)
# 4. Build headers array
array headers = []
headers['SignatureMethod'] = 'HmacSHA256'
headers['SignatureVersion'] = '2'
headers['PayloadDigest'] = payload_digest
headers['TimeStamp'] = current_utc_timestamp()
headers['Content-type'] = 'text/plain'
headers['Accept'] = 'application/json'
headers['RequestKeySignature'] = request_key_signature
headers['ClientId'] = ''; // Depends on certificate subject \
# 5. Sort headers array by keys
array headers = array_sort_by_keys_asc(headers)
# 6. Create teext to be signed
string text_to_sign = request_method + '\n'
+ json.encode(headers) + '\n'
+ urlencode(request_uri)
# 7. Calculate HMAC signature
bytes hmac = hmac(text_to_sign, request_key, 'sha256')
string signature = base64.encode(hmac)
headers[Signature] = signature
# 8. Encrypt request key using Pergamin External API certificate public key
public_key pubkey = load_public_key('pergamin-ext-api-cert.pem')
bytes request_key_encrypted = pubkey.encrypt(
bytes: request_key,
padding: OAEP(padding: MGF1, algorithm: SHA256),
)
string request_key_encrypted = base64.encode(request_key_encrypted)
# 9. Appends RequestKeyEncrypted and Certificate to request headers
headers['RequestKeyEncrypted'] = request_key_encrypted
bytes certificate = load_certificate()
string certificate = base64.encode(certificate)
headers['Certificate'] = certificate
# 10. Send request
send_request(
url: request_uri,
payload: payload,
headers: headers
)


