Version 1.0.0
Heros DOCUMENTS
The public half of every key that signs a payslip.
https://sandbox.droomwork.ioA payslip carries a signature and the identifier of the key that made it. This is where you get that key, so you can check the signature yourself.
What you should know before you start
You need no credential here, and there is nothing to hold. This is the only path on the platform that asks for none. Whoever is checking a payslip may never have heard of us, so an account would put the answer out of reach of the only people who want it.
Only the public half is here. There is no endpoint that returns a private key and no scope that would reach one; the two halves are kept apart, and what this answers is the half you need to verify with.
A key names the employer it belongs to. Each organisation signs with its own, so what a signature tells you is that this employer issued this payslip, not that we did.
Keys are replaced over time, and an old payslip stays checkable. A payslip names the key that signed it, so you fetch that key and not the one in use today. A key that has been replaced carries the date it was, and still verifies everything signed while it was live.
The signature is over the record, not over the page. So an altered page still carries a signature that verifies, and checking one tells you nothing about the page in your hand. GET /v1/payroll/payslips/{payslip_id}/document says what to compare.
Every operation below has two samples: Direct HTTP, with nothing but your language's own client, and Client library, with ours. Same request, same answer; the switch above each sample picks one and remembers it. Which should I use?
/v1/signing_keys/{signing_key_id}#Get the key a payslip was signed with
documents.signing_keys.retrieve
This gives you the public half of a signing key, so you can check a payslip's signature for yourself without holding anything of ours.
Send the signing_key_id from the payslip in the path. You get the key as PEM, the algorithm it uses, the employer it belongs to, and the dates it was created and replaced.
No credential is needed and none is read. Whoever is checking a payslip may have no account, which is the whole reason this answers to anybody.
A key we never issued answers not_found. There is nothing here that returns a private half, under this identifier or any other.
Path parameters
signing_key_id
string
requiredThe key's identifier, starting with sgk_, such as sgk_01M1E34QM07M2N5P8R3T6V9W1Y. Take it from signing_key_id on the payslip you are checking, at GET /v1/payroll/payslips/{payslip_id}. No endpoint creates or lists keys: one is written when a payslip is signed and reaches you on that payslip.
Returns
The public half of that key, with the employer it belongs to and its dates.
object
always "signing_key"
requiredAlways signing_key. Tells you which kind of record you are looking at, so one handler can read any response.
id
string
requiredThe key's own identifier, the same one you sent in the path and the one the payslip named in signing_key_id.
organisation_id
string
requiredThe employer this key belongs to, such as org_01J8XQ4M7K2N9P3R5T7V9W1Y3Z. Each one signs with its own key, so a signature says that this employer issued the payslip. No endpoint creates or lists keys; this is the organisation the payslip you are checking belongs to.
algorithm
string
requiredHow to verify, for example ed25519. Feed public_key and this to any library that implements it; there is nothing of ours to install.
public_key
string
requiredThe public half, as PEM, beginning -----BEGIN PUBLIC KEY-----. This is what you verify a signature against.
created_at
string · date-time
requiredWhen this key was created, as an RFC 3339 timestamp in UTC.
retired_at
string · date-time · nullable
optionalWhen this key was replaced, as an RFC 3339 timestamp in UTC, or null while it is the one in use. A replaced key still verifies everything signed while it was live.
Other responses
Errors it can return
curl -X GET "https://sandbox.droomwork.io/v1/signing_keys/sgk_01M1E34QM07M2N5P8R3T6V9W1Y"import { Configuration, DOCUMENTSApi } from '@heros/sdk';
const api = new DOCUMENTSApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
const result = await api.documentsSigningKeysRetrieve({ signingKeyId: 'sgk_01M1E34QM07M2N5P8R3T6V9W1Y' });const response = await fetch('https://sandbox.droomwork.io/v1/signing_keys/sgk_01M1E34QM07M2N5P8R3T6V9W1Y', {
method: 'GET',
headers: {
},
});
const result = await response.json();import os
import heros_sdk
config = heros_sdk.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = heros_sdk.ApiClient(config)
api = heros_sdk.DOCUMENTSApi(client)
result = api.documents_signing_keys_retrieve(signing_key_id='sgk_01M1E34QM07M2N5P8R3T6V9W1Y')import os
import requests
response = requests.request(
'GET',
'https://sandbox.droomwork.io/v1/signing_keys/sgk_01M1E34QM07M2N5P8R3T6V9W1Y',
headers={
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = HerosSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new HerosSdk\Api\DOCUMENTSApi(new GuzzleHttp\Client(), $config);
$result = $api->documentsSigningKeysRetrieve(signing_key_id: 'sgk_01M1E34QM07M2N5P8R3T6V9W1Y');<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/signing_keys/sgk_01M1E34QM07M2N5P8R3T6V9W1Y');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
],
]);
$result = json_decode(curl_exec($ch), true);import com.useheros.sdk.ApiClient;
import com.useheros.sdk.Configuration;
import com.useheros.sdk.api.DocumentsApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
DocumentsApi api = new DocumentsApi(client);
var result = api.documentsSigningKeysRetrieve("sgk_01M1E34QM07M2N5P8R3T6V9W1Y");var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/signing_keys/sgk_01M1E34QM07M2N5P8R3T6V9W1Y"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Heros.Sdk.Api;
using Heros.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new DOCUMENTSApi(config);
var result = api.DocumentsSigningKeysRetrieve(signingKeyId: "sgk_01M1E34QM07M2N5P8R3T6V9W1Y");using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/signing_keys/sgk_01M1E34QM07M2N5P8R3T6V9W1Y");
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import heros "github.com/fenibofubara/heros-sdk-go"
ctx := context.WithValue(context.Background(), heros.ContextAPIKeys, map[string]heros.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := heros.NewConfiguration()
cfg.Servers = heros.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := heros.NewAPIClient(cfg)
result, _, err := client.DOCUMENTSAPI.DocumentsSigningKeysRetrieve(ctx, "sgk_01M1E34QM07M2N5P8R3T6V9W1Y").Execute()req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/signing_keys/sgk_01M1E34QM07M2N5P8R3T6V9W1Y", nil)
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"object": "signing_key",
"id": "sgk_01M1E34QM07M2N5P8R3T6V9W1Y",
"organisation_id": "org_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"algorithm": "ed25519",
"public_key": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEARWRKyJMc3qxJ8FhFZFK1OBs1kOJ6TFW7N0OT3hRqH1M=\n-----END PUBLIC KEY-----\n",
"created_at": "2026-09-01T09:00:00Z",
"retired_at": null
}