REST API (Tool API ve Sunucudan Sunucuya)
Tarayıcı SDK’sı Tool API ile konuşur. Aynı API’yi kendi backend’inizden de çağırabilirsiniz — kendi arayüzünüzde alınan onayları kaydetmek, tek kullanımlık onay token’ları üretmek veya kayıtları sorgulayıp doğrulamak için.
Temel URL: https://system.hashentry.com
| Metot | Yol | Amaç | Kimlik doğrulama |
|---|---|---|---|
GET | /tool/v1/config | Banner yapılandırması, bağlı dokümanlar, algılanan bölge | API anahtarı (read) |
GET | /tool/v1/documents/{slug}/active | Tek bir dokümanın, içeriği dahil aktif sürümü | API anahtarı (read) |
GET | /tool/v1/documents/active | Siteye bağlı aktif dokümanlar | API anahtarı (read) |
POST | /tool/v1/consents | Tek bir onay kaydeder (tarayıcı / mobil SDK rotası) | API anahtarı (write) + imza |
POST | /tool/v1/consents/batch | 100’e kadar onay kaydeder | API anahtarı (write) + imza |
POST | /tool/v1/s2s/consents | Backend’inizden tek bir onay kaydeder | API anahtarı (write) + JWT + imza |
POST | /tool/v1/s2s/consents/batch | Backend’inizden 100’e kadar onay kaydeder | API anahtarı (write) + JWT + imza |
POST | /tool/v1/s2s/approval-tokens | Tek kullanımlık bir doküman onay token’ı üretir | API anahtarı (write) + JWT + imza |
GET | /tool/v1/consents/status | Tek bir ziyaretçinin güncel onayları | API anahtarı (read) |
GET | /tool/v1/consents/verify/{id} | Tek bir kaydın bütünlük kontrolü | API anahtarı (read) |
GET POST | /api/v1/public/consents/verify | Herkese açık bütünlük kontrolü (anahtarsız) | yok |
Kimlik doğrulama
Section titled “Kimlik doğrulama”API anahtarı
Section titled “API anahtarı”Her Tool API isteği sitenin anahtarını taşır:
X-API-Key: he_live_…Bir anahtarın bir kapsamı (scope) vardır: read, GET endpoint’lerine izin verir; write buna ek olarak POST isteklerine izin verir. Site panelde doğrulanmış olmalıdır. Sitenin izin verilen origin’ler listesi varsa, diğer origin’lerden gelen tarayıcı istekleri reddedilir; IP izin listesi varsa, diğer adreslerden gelen istekler reddedilir.
İstek imzası (tüm POST istekleri)
Section titled “İstek imzası (tüm POST istekleri)”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_hashsignature = HMAC-SHA256(key = API key, message = canonical) (lowercase hex)METHODbüyük harflidir.PATH,/tool/v1dahil, sorgu dizesi (query string) hariç istek yoludur; örn./tool/v1/s2s/consents.- Gövde hash’i, gönderdiğiniz baytların tam olarak kendisi üzerinden hesaplanır. JSON’u bir kez serileştirin ve aynı dizeyi gönderin.
X-Timestamp, sunucu saatinin ±300 saniye aralığında olmalıdır.X-Nonce,A–Z a–z 0–9 . _ : -karakterlerinden oluşan 8–128 karakterdir (bir UUID uygundur) ve site başına yalnızca bir kez kullanılabilir; tekrarıNONCE_REPLAYEDile reddedilir.
Adım adım örnek (SDK ile API’nin ortak test vektörü):
API key : he_live_0123456789abcdef0123456789abcdefMethod : POSTPath : /tool/v1/consentsTimestamp : 1760000000Nonce : 3f2b8c1e-5a47-4d0e-9b6a-7c1d2e3f4a5bBody : {"consent_type":"cookie","decision":"accepted","language":"tr","idempotency_key":"9a1c2b3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","metadata":{"note":"çerez ✓"}}
body_hash : 93316d8d6adb505a19668f4022e4e33b12aed9c0c4bb97d205b5064257090d34canonical : POST\n/tool/v1/consents\n1760000000\n3f2b8c1e-5a47-4d0e-9b6a-7c1d2e3f4a5b\n93316d8d6adb505a19668f4022e4e33b12aed9c0c4bb97d205b5064257090d34signature : e108683927badf35c36d5f467f63a9704c131d0102f14b06af7ed3046d44a8be(\n, tek bir satır besleme (line feed) karakterini ifade eder; gövde UTF-8’dir.) Uygulamanız bu girdiler için bu imzayı üretiyorsa doğrudur.
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}`, // yalnızca S2S rotaları ...sign(apiKey, 'POST', '/tool/v1/s2s/consents', body),};İmza, isteğin API anahtarıyla yapıldığını ve tekrar oynatılmadığını (replay) kanıtlar. Tarayıcı SDK’sı, sayfa kaynağında görünür olan aynı anahtarı kullandığından, imza tek başına bir isteğin backend’inizden geldiğini kanıtlamaz — S2S rotaları bunun içindir.
Sunucudan sunucuya rotalar (/tool/v1/s2s/…)
Section titled “Sunucudan sunucuya rotalar (/tool/v1/s2s/…)”S2S istekleri üç şey gerektirir: write kapsamlı bir API anahtarı, istek imzası ve api_user rolüne sahip bir kullanıcının JWT’si:
- Panelde
api_userrolüyle bir ekip üyesi davet edin. Bu rol yalnızca S2S API’yi kullanabilir; panele giriş yapamaz. - JWT almak için
POST /api/v1/auth/loginile oturum açın;POST /api/v1/auth/refreshile yenileyin. Authorization: Bearer <jwt>başlığınıX-API-Keyve imza başlıklarıyla birlikte gönderin. Kullanıcı, sitenin sahibi olan tenant’a ait olmalıdır.
Yalnızca S2S istekleri ip_address, user_agent, otp_verified ve otp_reference alanlarını ayarlayabilir. Tarayıcı rotasında IP adresi ve user agent her zaman bağlantıdan alınır ve OTP alanları yok sayılır.
Onay kaydetme
Section titled “Onay kaydetme”POST /tool/v1/consents (veya /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" }}| Alan | Kurallar |
|---|---|
consent_type | Zorunlu. 50 karaktere kadar (A–Z a–z 0–9 _ - .). Kullanımda olanlar: cookie, document_approval, do_not_sell_opt_out. |
decision | Zorunlu. accepted, rejected, partial veya withdrawn. |
document_version_id | Siteye bağlı bir dokümanın aktif bir sürümünün UUID’si. Bu alan olmadan — veya aktif olmayan bir sürümle — istek 409 CONFIG_OUTDATED ile reddedilir. Bir çerez onayı, sitenin cookie_policy dokümanına referans verir. |
language | Verilmişse, o sürümün dili olmalıdır. |
categories | Kategori anahtarı → boolean biçiminde nesne. Yalnızca banner yapılandırmasında tanımlı kategoriler saklanır. |
idempotency_key | 8–64 karakter (A–Z a–z 0–9 . _ : -). Aşağıya bakın. |
visitor_id | Kişi için sizin referansınız, 100 karaktere kadar. |
visitor_region, visitor_country | 10 / 2 karaktere kadar. |
compliance_framework | kvkk, gdpr, uk_gdpr, ccpa, lgpd, popia, pipeda, pipl, pipa veya none. |
source | 20 karaktere kadar, örn. client, server. |
metadata, extra_fields | Her biri en fazla 30 anahtar ve yaklaşık 16 KB olan nesneler. |
approval_token | Bir document_approval için tek kullanımlık token (aşağıya bakın). |
| İmza / özel doküman alanları | signature_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 — tümü üst düzeydedir. Bkz. Doküman Onayı ve İmza. |
ip_address, user_agent, otp_verified, otp_reference | Yalnızca S2S. |
document_version_id değerini GET /tool/v1/config?language=en (data.documents[].version.id) veya GET /tool/v1/documents/{slug}/active?language=en üzerinden alın.
Yanıt: 202 Accepted
Section titled “Yanıt: 202 Accepted”{ "message": "…", "data": { "consent_token": "ct_…", "proof_hash": "…64 hex characters…", "created_at": "2026-10-10T10:00:00+00:00", "duplicate": false }}202, isteğin tüm kontrollerden geçtiği ve kaydın yazılmak üzere kabul edildiği anlamına gelir. Token, kanıt hash’i ve zaman damgası bu noktada kesindir; ancak satır bir arka plan worker’ı tarafından yazılır, bu nedenle status ve verify kısa bir an için kaydı bulamayabilir.
idempotency_key
Section titled “idempotency_key”Kullanıcı eylemi başına bir anahtar gönderin ve o eylemin her yeniden denemesinde aynı anahtarı kullanın. Aynı anahtarla tekrarlanan bir istek ikinci bir kayıt oluşturmaz ve kota tüketmez; özgün yanıtı "duplicate": true ile döndürür. Anahtarlar 24 saat boyunca hatırlanır. Tarayıcı SDK’sı karar başına bir UUID üretir ve bunu ilk deneme, istemci yeniden denemeleri ve çevrimdışı kuyruğundan yapılan yeniden gönderimler için kullanır.
Toplu gönderim (batch)
Section titled “Toplu gönderim (batch)”{ "consents": [ { … }, … ] } ile POST /tool/v1/consents/batch (1–100 öğe, yukarıdakiyle aynı alanlar).
{ "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 } ] }}Toplu istek işlendiğinde durum kodu 202 olur; results içindeki her girdiyi kontrol edin. Doğrulama hataları ve bilinmeyen ya da aktif olmayan bir doküman sürümü içeren bir öğe, toplu isteğin tamamını reddettirir (422 / 409).
Tek kullanımlık onay token’ları
Section titled “Tek kullanımlık onay token’ları”POST /tool/v1/s2s/approval-tokens — yalnızca S2S.
{ "document_slug": "service-contract", "subject": "user-4711", "signer_name": "Jane Doe", "expires_in": 600}| Alan | Kurallar |
|---|---|
document_slug / document_version_id | En az biri. Sürüm kimliği verildiğinde token yalnızca o sürüm için geçerlidir. |
subject | Zorunlu. Kişi için sizin referansınız (en fazla 100 karakter); kaydın visitor_id değeri olarak saklanır. |
signer_name, signer_email, signer_phone, signer_id_number | İsteğe bağlı. Kefil olduğunuz kimlik bilgileri. |
otp_verified, otp_reference | İsteğe bağlı. Gerçekleştirdiğiniz bir OTP kontrolünü beyan eder. |
custom_document_hash | İsteğe bağlı. Sisteminizin ürettiği bir dokümanın SHA-256 değeri (hex); bu durumda onay tam olarak o içeriği taşımalıdır. |
expires_in | Saniye, 30–3600. Varsayılan 600. |
Yanıt 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 }}approval_token değerini sayfaya verin ve SDK’ya iletin (approvalToken) veya bir document_approval onayının üst düzey approval_token alanı olarak gönderin. Sunucu token’ı bir kez tüketir, kimliği token’dan alır ve gizli olmayan approval_token_id ile birlikte identity_assurance: tenant_attested değerini kaydeder. Başka bir nedenle (hız sınırı, kota) reddedilen bir istek token’ı tüketmez. HashEntry, token’ın yalnızca hash’ini saklar.
Okuma ve doğrulama
Section titled “Okuma ve doğrulama”GET /tool/v1/consents/status?visitor_id=…
Section titled “GET /tool/v1/consents/status?visitor_id=…”Tek bir visitor_id değerine ait, süresi dolmamış en fazla 20 onayı, en yenisi başta olacak şekilde döndürür. İsteğe bağlı filtreler: consent_type, document_slug, document_version_id.
GET /tool/v1/consents/verify/{id}
Section titled “GET /tool/v1/consents/verify/{id}”{id}; bir onay UUID’si, bir consent_token (ct_…) veya bir proof_hash değeridir.
{ "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" }}Bu yanıtın ne anlama geldiği — ve ne anlama gelmediği:
valid: trueşu anlama gelir: kayıt sizin tenant’ınıza aittir, HashEntry kanıt hash’ini saklanan kayıttan tenant’ınızın gizli anahtarıyla yeniden hesaplamış ve hash eşleşmiştir; ayrıca — kayıt bir Merkle grubunun (batch) parçasıysa — dahil edilme kanıtı doğrudur. Bir satırın var olması yeterli değildir.- Kaydın Merkle kanıtı yoksa
merkle_validdeğerinullolur. is_tsa_stamped, kayıt için (doğrudan veya Merkle grubu üzerinden) bir zaman damgası token’ının var olduğunu söyler. Token’ın imzasının bu çağrıda doğrulandığını söylemez.- Bu, HashEntry’nin HashEntry verisi üzerinde yaptığı bir kontroldür. Sunucunun yanıtına güvenmeden doğrulamak için bir delil paketi dışa aktarın ve kendiniz doğrulayın: Delilleri çevrimdışı doğrulama.
- Bilinmeyen bir kimlik,
"valid": falsevecode: "CONSENT_NOT_FOUND"ile404döndürür.
GET|POST /api/v1/public/consents/verify
Section titled “GET|POST /api/v1/public/consents/verify”API anahtarı yoktur; hız sınırı uygulanır. Parametreler: token (bir ct_… token’ı veya SDK’nın _he_consent çerezinin değeri), proof_hash veya id. Kararı, kategorileri, site alan adını, zaman damgalarını, hash durumunu ve zaman damgası bilgisini döndürür; IP adresini, user agent’ı veya ziyaretçi kimliğini hiçbir zaman döndürmez.
- Var olan bir kayıt: yukarıda açıklandığı şekilde
validdeğeriyle200. - Bir sunucu kaydıyla eşleştirilemeyen bir tarayıcı çerezi değeri:
"valid": false,"source": "client_token","server_record_found": falseve çözülmüş çerez alanlarıyla200. Çerez imzalı değildir; bu nedenle tek başına hiçbir zaman geçerli olarak bildirilmez. - Hiçbir şey bulunamadığında:
"valid": falseile404. Tanımlayıcı verilmediğinde:422.
Hata kodları
Section titled “Hata kodları”Hata yanıtları JSON’dur ve code alanında kararlı bir makine kodu taşır (ayrıca error_code ve error.code; bazı kimlik doğrulama hataları yalnızca error.code kullanır).
| HTTP | Kod | Anlamı |
|---|---|---|
| 401 | MISSING_API_KEY, INVALID_API_KEY | API anahtarı yok veya bilinmiyor. |
| 401 | MISSING_SIGNATURE_HEADERS, TIMESTAMP_EXPIRED, INVALID_SIGNATURE, INVALID_NONCE, NONCE_REPLAYED | İstek imzası sorunları. |
| 401 | MISSING_BEARER_TOKEN, INVALID_BEARER_TOKEN | S2S: JWT eksik veya geçersiz. |
| 403 | SITE_NOT_VERIFIED | Siteyi panelde doğrulayın. |
| 403 | ORIGIN_NOT_ALLOWED, IP_NOT_ALLOWED | Sitenin izin listesinde değil. |
| 403 | INSUFFICIENT_ROLE, TENANT_MISMATCH | S2S: kullanıcı bu tenant’ın bir api_user kullanıcısı değil. |
| 403 | — | API anahtarının kapsamı bu metoda izin vermiyor. |
| 404 | DOCUMENT_NOT_FOUND, VERSION_NOT_FOUND, CONSENT_NOT_FOUND | |
| 409 | CONFIG_OUTDATED | document_version_id eksik, aktif değil, dili yanlış veya sunucunun yapılandırma önbelleği soğuk. /tool/v1/config yanıtını yeniden okuyun; yalnızca sürüm hâlâ aktif sürümse yeniden gönderin. |
| 422 | VALIDATION_ERROR | Alan hataları errors içindedir. |
| 422 | APPROVAL_TOKEN_REQUIRED, APPROVAL_TOKEN_INVALID, APPROVAL_TOKEN_CONFLICT | Bkz. tek kullanımlık onay token’ları. |
| 422 | INVALID_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_LARGE | İstek gövdesi (payload) sınırları. |
| 429 | RATE_LIMIT_EXCEEDED | Plana göre hız sınırı. Bkz. Retry-After, X-RateLimit-Limit, X-RateLimit-Remaining. |
| 429 | CONSENT_LIMIT_EXCEEDED, NO_CONSENT_SUBSCRIPTION | Planın onay kotası tükendi / aktif bir plan yok. |
| 429 | TOO_MANY_INVALID_API_KEYS | Tek bir IP adresinden geçersiz anahtarlarla çok fazla istek. |
| 503 | QUEUE_OVERLOADED, ADMISSION_UNAVAILABLE, API_KEY_LOOKUP_UNAVAILABLE | Geçici. Retry-After süresinden sonra aynı idempotency_key ile yeniden deneyin. |
408, 425, 429 ve 5xx yanıtlarını aynı gövde ve aynı idempotency_key ile (ve yeni bir zaman damgası, nonce ve imza ile) yeniden deneyin. Diğer 4xx yanıtlarını değiştirmeden yeniden denemeyin.