Dijital İmza API Entegrasyonu: REST ve Webhook Tam Rehber (2026)
Dijital imza API entegrasyonu, modern yazılımlarda sık talep edilen bir özelliktir. CRM’inizdeki müşteriye, İK sisteminizdeki çalışana, e-ticaret platformunuzdaki alıcıya kendi sisteminizden tek bir API isteğiyle imza akışı başlatabilirsiniz. Bu rehber geliştiriciler için İmzala.org’un gerçek API yüzeyini anlatır.
REST API ile dijital imza entegrasyonu, gerçek uçlar ve örnek kodlarla
Neden API Entegrasyonu?
Panelden tek tek sözleşme oluşturmak küçük hacim için yeterlidir. Ancak:
- Sözleşmeler otomatik üretiliyorsa (e-ticaret tamamlama, İK işe alım) manuel akış yetmez
- Kullanıcı kendi sisteminde kalmalı (örneğin İK yazılımında teklif kabul edilince sözleşme otomatik gitsin)
- Durum güncellemeleri gerçek zamanlı gerekir (CRM’de “müşteri imzaladı” işareti)
- İşlem kaydını kendi veritabanınızda tutmak istersiniz
REST API ve webhook bu ihtiyaçları karşılar.
İmzala.org API Genel Bakış
| Özellik | Değer |
|---|---|
| Protokol | HTTPS + REST + JSON |
| Versiyon | v1 |
| Kimlik doğrulama | X-API-Key header (imz_ + 64 hex) |
| Webhook | HMAC-SHA256 imzalı (X-Imzala-Signature-256) |
| Üretim host | api-prd.imzala.org |
| Test host | test-api.imzala.org |
| Dokümantasyon | api-docs.imzala.org (OpenAPI) |
Resmi bir SDK paketi yoktur; API standart REST olduğundan her dilden HTTP istemcisiyle kullanılır.
Adım 1: API Anahtarı Al
Panel → Ayarlar → API Anahtarları → “Yeni Anahtar”:
imz_a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456
Önemli:
- Anahtar bir kez gösterilir; kaybederseniz iptal edip yeniden üretin
- Üretim ve test için ayrı anahtarlar kullanın, karıştırmayın
- Anahtarı sunucu tarafında saklayın, istemci/tarayıcıya koymayın
REST API ve JSON yanıt, geliştirici çalışma ortamı
Adım 2: Şablonu Hazırla
Sözleşmeler şablondan üretilir. Önce şablonlarınızı listeleyin:
curl https://api-prd.imzala.org/api/v1/templates \
-H "X-API-Key: imz_a1b2c3..."
Bir şablonun taraflarını ve değişkenlerini görmek için:
curl https://api-prd.imzala.org/api/v1/templates/<template_id> \
-H "X-API-Key: imz_a1b2c3..."
Yanıt, şablondaki tarafların kimliklerini (template_party_id) ve doldurulabilir değişkenleri verir. Sözleşme oluştururken bu taraf kimliklerini eşleyeceksiniz.
Adım 3: Sözleşme Oluştur
cURL Örneği
curl -X POST https://api-prd.imzala.org/api/v1/demands \
-H "X-API-Key: imz_a1b2c3..." \
-H "Content-Type: application/json" \
-d '{
"template_id": "<template_id>",
"party_mapping": [
{
"template_party_id": "<template_party_id>",
"first_name": "Mehmet",
"last_name": "Yılmaz",
"email": "[email protected]",
"phone": "+905551234567",
"send_email": true,
"send_sms": true,
"variables": { "tutar": "15000", "baslangic_tarihi": "2026-06-01" }
}
],
"variables": { "sozlesme_no": "A-42" },
"expiry_date": "2026-07-10T00:00:00Z",
"dispatch_notifications": true,
"has_timestamp": true
}'
Başarılı Yanıt (201 Created)
{
"success": true,
"data": {
"id": "<demand_id>",
"status": "PENDING",
"template_id": "<template_id>",
"signing_urls": [
{
"party_id": "<party_id>",
"first_name": "Mehmet",
"last_name": "Yılmaz",
"email": "[email protected]",
"phone": "+905551234567",
"signing_url": "https://e.imzala.org/imza/<party_id>"
}
],
"result_url": "https://e.imzala.org/sonuc/<demand_id>",
"variables_applied": ["sozlesme_no", "tutar"],
"dispatched": 1
}
}
Şablonsuz, doğrudan dosya yükleyerek sözleşme oluşturmak isterseniz
POST /api/v1/demands/uploaducu (multipart) ile dosya ve taraf bilgilerini gönderebilirsiniz.
Adım 4: Webhook ile Anlık Bildirim
Sözleşme oluşturduktan sonra durum sormak için sürekli sorgulama (polling) yapmayın. Webhook ile sistem size bildirim gönderir.
Webhook Yapılandırma
Webhook’lar panelden yönetilir (app.imzala.org/settings/webhooks); API üzerinden oluşturma/silme desteklenmez. URL’inizi ve dinlemek istediğiniz olayları kaydedin, secret değerini kopyalayın.
Gerçek olay (event) adları:
demand.created: sözleşme oluşturulduparty.viewed: bir taraf belgeyi görüntülediparty.signed: bir taraf imzaladıparty.rejected: bir taraf imzayı reddettidemand.completed: tüm taraflar imzaladıdemand.expired: sözleşme süresi doldu
Webhook İsteği ve Payload
İmzala, kayıtlı URL’inize şu başlıklarla POST atar:
POST <sizin_url>
Content-Type: application/json
X-Imzala-Event: demand.completed
X-Imzala-Delivery: <benzersiz-teslim-uuid>
X-Imzala-Signature-256: sha256=<hmac-sha256-hex>
User-Agent: Imzala-Webhook/1.0
{
"id": "evt_3f9a...",
"type": "demand.completed",
"created_at": "2026-06-29T06:30:00.000Z",
"data": {
"demand_id": "<demand_id>",
"status": "COMPLETED",
"completed_at": "2026-06-29T06:30:00.000Z",
"parties": [
{ "id": "<party_id>", "name": "Mehmet Yılmaz", "email": "[email protected]", "signed_at": "..." }
]
}
}
HMAC İmza Doğrulama (kritik)
Webhook URL’iniz herkese açıktır; sahte istekler gelebilir. Her isteği doğrulayın.
Node.js
import crypto from 'crypto';
app.post('/webhooks/imzala', (req, res) => {
const header = req.headers['x-imzala-signature-256'] || '';
const body = req.rawBody; // ham gövde, parse edilmeden ÖNCE
const expected = 'sha256=' + crypto
.createHmac('sha256', process.env.IMZALA_WEBHOOK_SECRET)
.update(body)
.digest('hex');
if (header !== expected) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(body);
// Tekrarlı teslimleri ayıkla (X-Imzala-Delivery benzersizdir)
const deliveryId = req.headers['x-imzala-delivery'];
if (await alreadyProcessed(deliveryId)) {
return res.status(200).send('Already processed');
}
await processEvent(event);
await markProcessed(deliveryId);
res.status(200).send('OK');
});
Python
import hmac, hashlib
@app.route('/webhooks/imzala', methods=['POST'])
def webhook():
header = request.headers.get('X-Imzala-Signature-256', '')
body = request.get_data() # ham gövde
expected = 'sha256=' + hmac.new(
os.environ['IMZALA_WEBHOOK_SECRET'].encode(),
body,
hashlib.sha256,
).hexdigest()
if not hmac.compare_digest(header, expected):
return 'Invalid signature', 401
event = json.loads(body)
delivery_id = request.headers.get('X-Imzala-Delivery')
if already_processed(delivery_id):
return 'Already processed', 200
process_event(event)
mark_processed(delivery_id)
return 'OK', 200
Önemli: 2xx Hızlı Dön
Webhook işleyiciniz hızlı dönmelidir. Uzun işler için:
- Hemen 200 dönün
- İşi bir kuyruğa atın (BullMQ, Celery, Sidekiq)
- Asenkron işleyin
Aksi halde sistem teslimi başarısız sayar ve yeniden dener.
Webhook ile gerçek zamanlı entegrasyon: taraf imzalar imzalamaz sisteminize bildirim
Adım 5: Durum Sorgulama ve PDF
curl https://api-prd.imzala.org/api/v1/demands/<demand_id> \
-H "X-API-Key: imz_..."
Yanıt, sözleşmenin durumunu ve tarafların imza bilgisini içerir. Sözleşme tamamlandığında yanıttaki pdf_url alanı, sonuç PDF’inin genel (public) bağlantısını verir; tamamlanmamışsa bu alan null döner.
{
"success": true,
"data": {
"id": "<demand_id>",
"status": "COMPLETED",
"completed_at": "2026-06-29T06:30:00Z",
"pdf_url": "https://api-prd.imzala.org/sonuc/<demand_id>/pdf",
"parties": [
{ "id": "<party_id>", "status": "SIGNED", "signed_at": "2026-06-29T06:29:00Z" }
]
}
}
Not:
pdf_urlgenel bir sonuç bağlantısıdır ve API anahtarı gerektirmez. Bağlantıyı yalnızca yetkili sistemlerinizle paylaşın.
İmzalı PDF, TÜBİTAK KAMUnet zaman damgasıyla üretilir; bu, belgenin imzalanma anını ve sonradan değişmediğini teknik olarak gösterir.
Hata Yönetimi
Hatalar JSON olarak döner. Tipik biçim:
{ "success": false, "error": "Şablon bulunamadı" }
Bazı uçlar ek bir code alanı döndürür (örneğin INSUFFICIENT_CREDITS). Hatırlatma ucu iç içe bir hata nesnesi döndürür: { "success": false, "error": { "code": "...", "message": "...", "retry_after_seconds": 300 } }.
HTTP durum kodları standarttır: 400 (doğrulama), 401 (kimlik), 403 (izin), 404 (bulunamadı), 409 (çakışma), 422 (iş kuralı), 500 (sunucu).
Backend altyapı: Almanya’daki (AB/GDPR alanı) veri merkezi, KVKK’ya uygun süreçler
Gerçek Endpoint Listesi
İmzala.org harici API’si (X-API-Key) sekiz uç sunar:
| Uç | Açıklama |
|---|---|
GET /api/v1/templates | Aktif şablonları listeler |
GET /api/v1/templates/{id} | Şablon detayı, taraflar ve değişkenler |
GET /api/v1/templates/{id}/usage | Şablon için kullanım ve örnek istek |
POST /api/v1/demands | Şablondan sözleşme oluşturur |
POST /api/v1/demands/upload | Dosya yükleyerek sözleşme oluşturur |
GET /api/v1/demands/{id} | Sözleşme durumu ve ilerleme |
POST /api/v1/demands/{id}/items | Toplu alan (değişken) güncelleme |
POST /api/v1/demands/{id}/reminders | İmzalamamış taraflara hatırlatma |
Tam istek/yanıt şeması ve cURL örnekleri api-docs.imzala.org’dadır.
Tipik Kullanım Senaryoları
1. E-Ticaret Tamamlama → Mesafeli Satış Sözleşmesi
// Sipariş tamamlandığında
async function onCheckoutComplete(order) {
const res = await fetch('https://api-prd.imzala.org/api/v1/demands', {
method: 'POST',
headers: {
'X-API-Key': process.env.IMZALA_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
template_id: process.env.MESAFELI_SATIS_TEMPLATE_ID,
party_mapping: [{
template_party_id: process.env.MESAFELI_ALICI_PARTY_ID,
first_name: order.customer.firstName,
last_name: order.customer.lastName,
email: order.customer.email,
send_email: true,
variables: { siparis_no: order.id, toplam_tutar: String(order.total) },
}],
}),
});
const { data } = await res.json();
await db.orders.update(order.id, { signing_demand_id: data.id, status: 'AWAITING_SIGNATURE' });
}
// Webhook: tüm taraflar imzalayınca
app.post('/webhooks/imzala', verifySignature, async (req, res) => {
if (req.headers['x-imzala-event'] === 'demand.completed') {
await db.orders.updateByDemand(req.body.data.demand_id, { status: 'PROCESSING' });
}
res.send('OK');
});
2. İK İşe Alım → İş Sözleşmesi
def on_offer_accepted(offer):
res = requests.post(
'https://api-prd.imzala.org/api/v1/demands',
headers={'X-API-Key': os.environ['IMZALA_API_KEY']},
json={
'template_id': IS_SOZLESMESI_TEMPLATE_ID,
'party_mapping': [{
'template_party_id': CALISAN_PARTY_ID,
'first_name': offer.first_name,
'last_name': offer.last_name,
'email': offer.email,
'send_email': True,
'send_sms': True,
'variables': {'pozisyon': offer.position, 'maas': str(offer.salary)},
}],
},
)
demand = res.json()['data']
db.offers.update(offer.id, signing_demand_id=demand['id'])
# Webhook
@app.post('/webhooks/imzala')
def webhook(request):
verify_signature(request)
if request.headers.get('X-Imzala-Event') == 'demand.completed':
offer = db.offers.get_by_demand(request.json['data']['demand_id'])
# kendi İK akışınızı tetikleyin
return 'OK', 200
Production Kontrol Listesi
Üretime geçmeden önce:
- Webhook URL’i HTTPS olmalı
- HMAC doğrulaması (X-Imzala-Signature-256) uygulandı ve test edildi
- X-Imzala-Delivery ile tekrarlı teslimler ayıklanıyor
- Webhook işleyici hızlı 2xx dönüyor, ağır iş kuyruğa atılıyor
- API anahtarı sunucu tarafında, üretim/test ayrı
- İşlem kaydı kendi veritabanınızda tutuluyor (sözleşme kimliği + durum + zaman)
- KVKK aydınlatma metniniz İmzala.org API’si üzerinden işlenen verileri kapsıyor
API üzerinden müşteri verisi işleyen taraf veri sorumlusudur; İmzala.org veri işleyen sıfatıyla hareket eder (bkz. Veri İşleme Sözleşmesi).
Sonuç
İmzala.org API, dijital imzayı kendi sisteminizin bir parçası haline getirir. Standart REST + JSON + güvenli webhook ile entegrasyon hızlıdır. Test host’unda (test-api.imzala.org) doğrulayın, hazır olduğunuzda üretim host’una (api-prd.imzala.org) geçin.
Hızlı özet:
- 📡 REST + JSON + HTTPS
- 🔐 X-API-Key kimlik doğrulama + HMAC imzalı webhook
- 🔁 6 denemeli webhook yeniden gönderimi (artan beklemeyle)
- 📚 OpenAPI dokümantasyonu (api-docs.imzala.org)
- 🌐 Ayrı üretim ve test host’ları
Bu içerik genel bilgilendirme amaçlıdır, hukuki danışmanlık niteliği taşımaz. Somut işlemleriniz için bir avukata danışın.
İlgili Rehberler: