Zum Inhalt springen

REST-API (Tool API & Server-to-Server)

Das Browser-SDK kommuniziert mit der Tool API. Sie können dieselbe API von Ihrem eigenen Backend aus aufrufen — um Einwilligungen zu erfassen, die in Ihrer eigenen UI eingeholt wurden, um einmalige Zustimmungstoken auszustellen oder um Datensätze nachzuschlagen und zu prüfen.

Basis-URL: https://system.hashentry.com

MethodePfadZweckAuthentifizierung
GET/tool/v1/configBanner-Konfiguration, zugeordnete Dokumente, erkannte RegionAPI-Schlüssel (read)
GET/tool/v1/documents/{slug}/activeAktive Version eines Dokuments, einschließlich InhaltAPI-Schlüssel (read)
GET/tool/v1/documents/activeAktive Dokumente, die der Website zugeordnet sindAPI-Schlüssel (read)
POST/tool/v1/consentsEine Einwilligung erfassen (Route für Browser- / Mobile-SDK)API-Schlüssel (write) + Signatur
POST/tool/v1/consents/batchBis zu 100 Einwilligungen erfassenAPI-Schlüssel (write) + Signatur
POST/tool/v1/s2s/consentsEine Einwilligung von Ihrem Backend aus erfassenAPI-Schlüssel (write) + JWT + Signatur
POST/tool/v1/s2s/consents/batchBis zu 100 Einwilligungen von Ihrem Backend aus erfassenAPI-Schlüssel (write) + JWT + Signatur
POST/tool/v1/s2s/approval-tokensEin einmaliges Token für eine Dokumentzustimmung ausstellenAPI-Schlüssel (write) + JWT + Signatur
GET/tool/v1/consents/statusAktuelle Einwilligungen eines BesuchersAPI-Schlüssel (read)
GET/tool/v1/consents/verify/{id}Integritätsprüfung eines DatensatzesAPI-Schlüssel (read)
GET POST/api/v1/public/consents/verifyÖffentliche Integritätsprüfung (ohne Schlüssel)keine

Jede Anfrage an die Tool API enthält den Schlüssel der Website:

X-API-Key: he_live_…

Ein Schlüssel hat einen Geltungsbereich (Scope): read erlaubt die GET-Endpunkte, write erlaubt zusätzlich POST. Die Website muss im Dashboard verifiziert sein. Hat die Website eine Liste erlaubter Ursprünge, werden Browser-Anfragen von anderen Ursprüngen abgelehnt; hat sie eine IP-Allow-List, werden Anfragen von anderen Adressen abgelehnt.

X-Signature: <hex HMAC-SHA256>
X-Timestamp: <Unix time in seconds>
X-Nonce: <unique value per request>
body_hash = SHA-256(raw request body) (lowercase hex)
canonical = METHOD + "\n" + PATH + "\n" + TIMESTAMP + "\n" + NONCE + "\n" + body_hash
signature = HMAC-SHA256(key = API key, message = canonical) (lowercase hex)
  • METHOD wird in Großbuchstaben geschrieben. PATH ist der Anfragepfad einschließlich /tool/v1, ohne den Query-String, z. B. /tool/v1/s2s/consents.
  • Der Body-Hash wird über genau die Bytes berechnet, die Sie senden. Serialisieren Sie das JSON einmal und senden Sie genau diese Zeichenkette.
  • X-Timestamp muss innerhalb von ±300 Sekunden der Serverzeit liegen.
  • X-Nonce besteht aus 8–128 Zeichen aus A–Z a–z 0–9 . _ : - (eine UUID funktioniert) und kann pro Website nur einmal verwendet werden; eine Wiederholung wird mit NONCE_REPLAYED abgelehnt.

Durchgerechnetes Beispiel (der gemeinsame Testvektor des SDK und der API):

API key : he_live_0123456789abcdef0123456789abcdef
Method : POST
Path : /tool/v1/consents
Timestamp : 1760000000
Nonce : 3f2b8c1e-5a47-4d0e-9b6a-7c1d2e3f4a5b
Body : {"consent_type":"cookie","decision":"accepted","language":"tr","idempotency_key":"9a1c2b3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","metadata":{"note":"çerez ✓"}}
body_hash : 93316d8d6adb505a19668f4022e4e33b12aed9c0c4bb97d205b5064257090d34
canonical : POST\n/tool/v1/consents\n1760000000\n3f2b8c1e-5a47-4d0e-9b6a-7c1d2e3f4a5b\n93316d8d6adb505a19668f4022e4e33b12aed9c0c4bb97d205b5064257090d34
signature : e108683927badf35c36d5f467f63a9704c131d0102f14b06af7ed3046d44a8be

(\n steht für ein einzelnes Zeilenvorschubzeichen; der Body ist UTF-8.) Wenn Ihre Implementierung für diese Eingaben diese Signatur erzeugt, ist sie korrekt.

Node.js
const crypto = require('crypto');
function sign(apiKey, method, path, body) {
const timestamp = Math.floor(Date.now() / 1000).toString();
const nonce = crypto.randomUUID();
const bodyHash = crypto.createHash('sha256').update(body, 'utf8').digest('hex');
const canonical = [method.toUpperCase(), path, timestamp, nonce, bodyHash].join('\n');
const signature = crypto.createHmac('sha256', apiKey).update(canonical, 'utf8').digest('hex');
return { 'X-Signature': signature, 'X-Timestamp': timestamp, 'X-Nonce': nonce };
}
const body = JSON.stringify({ consent_type: 'document_approval', decision: 'accepted', /* … */ });
const headers = {
'Content-Type': 'application/json',
'X-API-Key': apiKey,
Authorization: `Bearer ${jwt}`, // nur S2S-Routen
...sign(apiKey, 'POST', '/tool/v1/s2s/consents', body),
};

Die Signatur belegt, dass die Anfrage mit dem API-Schlüssel erstellt und nicht wiederholt eingespielt wurde. Da das Browser-SDK denselben Schlüssel verwendet, der im Quelltext der Seite sichtbar ist, belegt die Signatur allein nicht, dass eine Anfrage von Ihrem Backend stammt — dafür sind die S2S-Routen da.

S2S-Anfragen benötigen drei Dinge: einen API-Schlüssel mit write-Scope, die Anfragesignatur und ein JWT eines Benutzers mit der Rolle api_user:

  1. Laden Sie im Dashboard ein Teammitglied mit der Rolle api_user ein. Diese Rolle kann nur die S2S-API verwenden; eine Anmeldung im Panel ist damit nicht möglich.
  2. Melden Sie sich mit POST /api/v1/auth/login an, um ein JWT zu erhalten; erneuern Sie es mit POST /api/v1/auth/refresh.
  3. Senden Sie Authorization: Bearer <jwt> zusammen mit X-API-Key und den Signatur-Headern. Der Benutzer muss zu dem Mandanten gehören, dem die Website gehört.

Nur S2S-Anfragen dürfen ip_address, user_agent, otp_verified und otp_reference setzen. Auf der Browser-Route werden IP-Adresse und User-Agent immer aus der Verbindung übernommen, und die OTP-Felder werden ignoriert.


POST /tool/v1/consents (oder /tool/v1/s2s/consents)

{
"consent_type": "cookie",
"decision": "partial",
"document_version_id": "0190a1b2-…",
"language": "en",
"categories": { "necessary": true, "analytics": true, "marketing": false },
"idempotency_key": "9a1c2b3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d",
"visitor_id": "user-4711",
"visitor_region": "DE",
"compliance_framework": "gdpr",
"metadata": { "order_id": "ORD-54321" }
}
FeldRegeln
consent_typeErforderlich. Bis zu 50 Zeichen (A–Z a–z 0–9 _ - .). In Verwendung: cookie, document_approval, do_not_sell_opt_out.
decisionErforderlich. accepted, rejected, partial oder withdrawn.
document_version_idUUID einer aktiven Version eines Dokuments, das der Website zugeordnet ist. Ohne sie — oder mit einer Version, die nicht aktiv ist — wird die Anfrage mit 409 CONFIG_OUTDATED abgelehnt. Eine Cookie-Einwilligung verweist auf das cookie_policy-Dokument der Website.
languageFalls angegeben, muss es die Sprache dieser Version sein.
categoriesObjekt aus Kategorieschlüssel → Boolean. Es werden nur Kategorien gespeichert, die in der Banner-Konfiguration definiert sind.
idempotency_key8–64 Zeichen (A–Z a–z 0–9 . _ : -). Siehe unten.
visitor_idIhre Referenz für die Person, bis zu 100 Zeichen.
visitor_region, visitor_countryBis zu 10 / 2 Zeichen.
compliance_frameworkkvkk, gdpr, uk_gdpr, ccpa, lgpd, popia, pipeda, pipl, pipa oder none.
sourceBis zu 20 Zeichen, z. B. client, server.
metadata, extra_fieldsObjekte mit jeweils höchstens 30 Schlüsseln und etwa 16 KB.
approval_tokenEinmaliges Token für eine document_approval (siehe unten).
Felder für Signatur / eigenes Dokumentsignature_image, signature_mime_type, signer_name, signer_email, signer_phone, signer_id_number, declaration_text, drawing_duration_ms, stroke_count, strokes_data, input_type, screen_resolution, custom_document_content, custom_document_mime_type — alle auf oberster Ebene. Siehe Dokumentzustimmung & Signatur.
ip_address, user_agent, otp_verified, otp_referenceNur S2S.

Die document_version_id erhalten Sie von GET /tool/v1/config?language=en (data.documents[].version.id) oder von GET /tool/v1/documents/{slug}/active?language=en.

{
"message": "…",
"data": {
"consent_token": "ct_…",
"proof_hash": "…64 hex characters…",
"created_at": "2026-10-10T10:00:00+00:00",
"duplicate": false
}
}

202 bedeutet, dass die Anfrage alle Prüfungen bestanden hat und der Datensatz zum Schreiben angenommen wurde. Das Token, der Proof-Hash und der Zeitstempel sind zu diesem Zeitpunkt endgültig, aber die Zeile wird von einem Hintergrund-Worker geschrieben, sodass status und verify sie für einen kurzen Moment möglicherweise nicht finden.

Senden Sie einen Schlüssel pro Benutzeraktion und verwenden Sie ihn bei jedem erneuten Versuch dieser Aktion wieder. Eine wiederholte Anfrage mit demselben Schlüssel erzeugt keinen zweiten Datensatz und verbraucht kein Kontingent; sie gibt die ursprüngliche Antwort mit "duplicate": true zurück. Schlüssel werden 24 Stunden lang gespeichert. Das Browser-SDK erzeugt eine UUID pro Entscheidung und verwendet sie für den ersten Versuch, für Wiederholungsversuche des Clients und für erneute Sendungen aus seiner Offline-Warteschlange.

POST /tool/v1/consents/batch mit { "consents": [ { … }, … ] } (1–100 Einträge, dieselben Felder wie oben).

{
"data": {
"accepted": 2,
"rejected": 1,
"results": [
{ "index": 0, "status": "accepted", "consent_token": "ct_…", "proof_hash": "…", "created_at": "…", "duplicate": false },
{ "index": 1, "status": "accepted", "consent_token": "ct_…", "proof_hash": "…", "created_at": "…", "duplicate": true },
{ "index": 2, "status": "rejected", "error": "…", "error_code": "CONSENT_LIMIT_EXCEEDED", "code": 429 }
]
}
}

Der Status ist 202, wenn der Batch verarbeitet wurde; prüfen Sie jeden Eintrag von results. Validierungsfehler und ein Eintrag mit einer unbekannten oder inaktiven Dokumentversion führen zur Ablehnung des gesamten Batches (422 / 409).


POST /tool/v1/s2s/approval-tokens — nur S2S.

{
"document_slug": "service-contract",
"subject": "user-4711",
"signer_name": "Jane Doe",
"signer_email": "[email protected]",
"expires_in": 600
}
FeldRegeln
document_slug / document_version_idMindestens eines davon. Mit einer Versions-ID gilt das Token nur für diese Version.
subjectErforderlich. Ihre Referenz für die Person (max. 100 Zeichen); wird als visitor_id des Datensatzes gespeichert.
signer_name, signer_email, signer_phone, signer_id_numberOptional. Identitätsangaben, für die Sie sich verbürgen.
otp_verified, otp_referenceOptional. Erklären eine OTP-Prüfung, die Sie durchgeführt haben.
custom_document_hashOptional. SHA-256 (hex) eines von Ihrem System erzeugten Dokuments; die Zustimmung muss dann genau diesen Inhalt enthalten.
expires_inSekunden, 30–3600. Standard 600.

Antwort 201:

{
"data": {
"approval_token": "hat_…",
"approval_token_id": "atk_…",
"expires_in": 600,
"expires_at": "2026-10-10T10:10:00+00:00",
"document_id": "…",
"document_slug": "service-contract",
"document_version_id": null
}
}

Geben Sie approval_token an die Seite weiter und übergeben Sie es dem SDK (approvalToken) oder senden Sie es als approval_token auf oberster Ebene einer document_approval-Einwilligung. Der Server verbraucht es einmal, übernimmt die Identität aus dem Token und erfasst identity_assurance: tenant_attested zusammen mit der nicht geheimen approval_token_id. Eine Anfrage, die aus einem anderen Grund abgelehnt wird (Rate-Limit, Kontingent), verbraucht das Token nicht. HashEntry speichert nur einen Hash des Tokens.


Gibt bis zu 20 nicht abgelaufene Einwilligungen einer visitor_id zurück, die neuesten zuerst. Optionale Filter: consent_type, document_slug, document_version_id.

{id} ist eine Einwilligungs-UUID, ein consent_token (ct_…) oder ein proof_hash.

{
"valid": true,
"data": {
"consent_type": "cookie",
"decision": "accepted",
"proof_hash": "…",
"hash_version": 2,
"hash_valid": true,
"merkle_valid": null,
"is_anonymized": false,
"is_tsa_stamped": false,
"created_at": "2026-10-10T10:00:00+00:00"
}
}

Was diese Antwort bedeutet — und was nicht:

  • valid: true bedeutet: Der Datensatz gehört zu Ihrem Mandanten, HashEntry hat den Proof-Hash aus dem gespeicherten Datensatz mit dem geheimen Schlüssel Ihres Mandanten neu berechnet und er stimmt überein, und — falls der Datensatz Teil eines Merkle-Batches ist — sein Inklusionsbeweis ist korrekt. Das bloße Vorhandensein einer Zeile reicht nicht aus.
  • merkle_valid ist null, wenn der Datensatz keinen Merkle-Beweis hat.
  • is_tsa_stamped besagt, dass für den Datensatz ein Zeitstempel-Token existiert (direkt oder über seinen Merkle-Batch). Es besagt nicht, dass die Signatur des Tokens in diesem Aufruf geprüft wurde.
  • Dies ist eine Prüfung, die HashEntry auf den Daten von HashEntry durchführt. Um zu prüfen, ohne der Antwort des Servers zu vertrauen, exportieren Sie ein Nachweispaket und prüfen Sie es selbst: Nachweise offline prüfen.
  • Eine unbekannte ID liefert 404 mit "valid": false und code: "CONSENT_NOT_FOUND".

Kein API-Schlüssel; mit Rate-Limit. Parameter: token (ein ct_…-Token oder der Wert des Cookies _he_consent des SDK), proof_hash oder id. Zurückgegeben werden die Entscheidung, die Kategorien, die Domain der Website, Zeitstempel, der Hash-Status und Informationen zum Zeitstempel, niemals jedoch die IP-Adresse, der User-Agent oder die Besucher-ID.

  • Ein vorhandener Datensatz: 200 mit valid wie oben beschrieben.
  • Ein Browser-Cookie-Wert, der keinem Server-Datensatz zugeordnet werden kann: 200 mit "valid": false, "source": "client_token", "server_record_found": false und den dekodierten Cookie-Feldern. Das Cookie ist nicht signiert, daher wird es für sich allein nie als gültig gemeldet.
  • Nichts gefunden: 404 mit "valid": false. Kein Bezeichner: 422.

Fehlerantworten sind JSON und enthalten in code einen stabilen Maschinencode (außerdem error_code und error.code; manche Authentifizierungsfehler verwenden nur error.code).

HTTPCodeBedeutung
401MISSING_API_KEY, INVALID_API_KEYKein oder unbekannter API-Schlüssel.
401MISSING_SIGNATURE_HEADERS, TIMESTAMP_EXPIRED, INVALID_SIGNATURE, INVALID_NONCE, NONCE_REPLAYEDProbleme mit der Anfragesignatur.
401MISSING_BEARER_TOKEN, INVALID_BEARER_TOKENS2S: JWT fehlt oder ist ungültig.
403SITE_NOT_VERIFIEDVerifizieren Sie die Website im Dashboard.
403ORIGIN_NOT_ALLOWED, IP_NOT_ALLOWEDNicht in der Allow-List der Website.
403INSUFFICIENT_ROLE, TENANT_MISMATCHS2S: Der Benutzer ist kein api_user dieses Mandanten.
403—Der Scope des API-Schlüssels erlaubt die Methode nicht.
404DOCUMENT_NOT_FOUND, VERSION_NOT_FOUND, CONSENT_NOT_FOUND
409CONFIG_OUTDATEDdocument_version_id fehlt, ist nicht aktiv, hat die falsche Sprache, oder der Konfigurations-Cache des Servers ist kalt. Lesen Sie /tool/v1/config erneut; senden Sie nur dann erneut, wenn die Version weiterhin die aktive ist.
422VALIDATION_ERRORFeldfehler stehen in errors.
422APPROVAL_TOKEN_REQUIRED, APPROVAL_TOKEN_INVALID, APPROVAL_TOKEN_CONFLICTSiehe einmalige Zustimmungstoken.
422INVALID_CATEGORIES, METADATA_TOO_MANY_KEYS, METADATA_TOO_LARGE, EXTRA_FIELDS_TOO_MANY_KEYS, EXTRA_FIELD_NAME_TOO_LONG, EXTRA_FIELDS_TOO_LARGE, STROKES_DATA_TOO_LARGE, INVALID_SIGNATURE_IMAGE, SIGNATURE_IMAGE_TOO_LARGE, INVALID_CUSTOM_DOCUMENT, UNSUPPORTED_CUSTOM_DOCUMENT_TYPE, CUSTOM_DOCUMENT_TOO_LARGEPayload-Limits.
429RATE_LIMIT_EXCEEDEDRate-Limit je Tarif. Siehe Retry-After, X-RateLimit-Limit, X-RateLimit-Remaining.
429CONSENT_LIMIT_EXCEEDED, NO_CONSENT_SUBSCRIPTIONDas Einwilligungskontingent des Tarifs ist aufgebraucht / es gibt keinen aktiven Tarif.
429TOO_MANY_INVALID_API_KEYSZu viele Anfragen mit ungültigen Schlüsseln von einer IP-Adresse.
503QUEUE_OVERLOADED, ADMISSION_UNAVAILABLE, API_KEY_LOOKUP_UNAVAILABLEVorübergehend. Versuchen Sie es nach Retry-After mit demselben idempotency_key erneut.

Wiederholen Sie Antworten mit 408, 425, 429 und 5xx mit demselben Body und demselben idempotency_key (und mit neuem Zeitstempel, neuer Nonce und neuer Signatur). Wiederholen Sie andere 4xx-Antworten nicht unverändert.