API referansı, SDK kurulumu, SMTP ayarları ve webhook doğrulama.
Beş dakikada ilk e-postanızı gönderin.
curl -X POST https://flanque.com/api/v1/messages \
-H "Authorization: Bearer flq_live_XXXXXXXXXXXXXXXX" \
-H "Content-Type: application/json" \
-d '{
"from": "Firma <info@firma.com>",
"to": "musteri@example.com",
"subject": "Siparişiniz onaylandı",
"html": "<h1>Teşekkürler!</h1><p>Sipariş no: 12345</p>",
"tags": ["order", "confirmation"],
"idempotencyKey": "order-12345"
}'Tüm REST istekleri Authorization başlığında Bearer API anahtarı taşır. Anahtarlar projeye bağlıdır ve kapsam (send, read) ile sınırlandırılır.
| Alan | Açıklama |
|---|---|
Authorization | Bearer flq_live_… |
Content-Type | application/json |
Idempotency-Key | İsteğe bağlı; gövdedeki idempotencyKey ile aynı işlevi görür |
Authorization: Bearer flq_live_XXXXXXXXXXXXXXXX
Anahtarınızı istemci tarafı kodda, mobil uygulamada veya sürüm kontrolünde saklamayın. Sızdığından şüpheleniyorsanız panelden anında iptal edip yenisini oluşturun.
POST /api/v1/messages ile tek bir mesaj gönderin. HTML ve metin gövdesi birlikte verilebilir. Gövde olduğu gibi gönderilir; kişiselleştirmeyi gönderimden önce kendi tarafınızda yapın.
| Alan | Tür | Açıklama |
|---|---|---|
from | string | Doğrulanmış alan adında gönderen adresi; "Ad <adres>" biçimi desteklenir. |
to | string | string[] | Alıcı adresi veya en fazla 50 adres. |
subject | string | Konu satırı (tek satır, en fazla 998 karakter). |
html | string | HTML gövde. text verilmezse otomatik türetilir. |
text | string | Düz metin gövde (isteğe bağlı). |
replyTo | string | Yanıt adresi (isteğe bağlı). |
tags | string[] | Raporlama için en fazla 10 etiket (harf, rakam, nokta, tire, alt çizgi). |
idempotencyKey | string | Tekrar güvenliği için benzersiz anahtar (en fazla 120 karakter). Aynı anahtar ilk yanıtı 200 ile döndürür. |
metadata | object | Webhook olaylarında geri dönen anahtar-değer çiftleri. |
import { Flanque } from class="tok-str">'flanque-sdk' const flanque = new Flanque(process.env.FLANQUE_API_KEY) const { messageId } = await flanque.emails.send({ from: class="tok-str">'Firma <info@firma.com>', to: class="tok-str">'musteri@example.com', subject: class="tok-str">'Siparişiniz onaylandı', html: class="tok-str">'<h1>Teşekkürler!</h1><p>Sipariş no: 12345</p>', tags: [class="tok-str">'order', class="tok-str">'confirmation'], idempotencyKey: class="tok-str">'order-12345', }) console.log(messageId) class=class="tok-str">"tok-cm">// msg_8f3a…
{
"ok": true,
"data": {
"id": "8f3a2c1e-9b4d-4c2a-a1f0-2d7e5b9c3a11",
"status": "queued",
"messageId": "<5e3cf63cb5d1fd84e3ee154f@firma.com>",
"from": "info@firma.com",
"to": "musteri@example.com",
"subject": "Siparişiniz onaylandı",
"createdAt": 1793000000000,
"idempotent": false,
"sandbox": false
}
}Aynı idempotencyKey ile tekrarlanan istek yeni mesaj oluşturmaz; ilk yanıt aynen döner. Ağ hatalarında bu anahtarla güvenle yeniden deneyin.
Her olay (accepted, delivered, bounced, complained, opened, clicked, unsubscribed) JSON gövdesiyle uç noktanıza POST edilir. İmza X-Flanque-Signature başlığında t=<zaman damgası ms>,v1=<hex> biçimindedir: v1 = HMAC-SHA256(gizli anahtar, "<t>.<ham gövde>"). 5 dakikadan eski zaman damgalarını reddedin.
| Alan | Açıklama |
|---|---|
X-Flanque-Signature | t=<ms>,v1=HMAC-SHA256(secret, "<t>.<rawBody>") hex |
X-Flanque-Event | Olay türü, örn. delivered |
X-Flanque-Delivery | Teslim kimliği; tekrarları ayıklamak için saklayın |
POST https://firma.com/hooks/flanque
X-Flanque-Event: bounced
X-Flanque-Delivery: evt_7d2b9c1a
X-Flanque-Signature: t=1793000003000,v1=3c9a1f…(64 hex)
{
"id": "evt_7d2b9c1a",
"type": "bounced",
"createdAt": 1793000003000,
"data": {
"messageId": "8f3a2c1e-9b4d-4c2a-a1f0-2d7e5b9c3a11",
"campaignId": null,
"to": "musteri@example.com",
"subject": "Siparişiniz onaylandı",
"reason": "smtp; 550 5.1.1 User unknown",
"link": null
}
}import { createHmac, timingSafeEqual } from class="tok-str">'node:crypto' class=class="tok-str">"tok-cm">// Başlık: X-Flanque-Signature: t=<ms>,v1=<hex>; imza class="tok-str">"${t}.${rawBody}" üzerinden hesaplanır. export function verifyFlanqueSignature(rawBody, header, secret, toleranceMs = 5 * 60 * 1000) { const parts = Object.fromEntries((header ?? class="tok-str">'').split(class="tok-str">',').map((p) => p.split(class="tok-str">'='))) const t = Number(parts.t) if (!Number.isFinite(t) || !parts.v1 || Math.abs(Date.now() - t) > toleranceMs) return false const expected = createHmac(class="tok-str">'sha256', secret).update(class="tok-str">`${t}.${rawBody}`).digest(class="tok-str">'hex') const a = Buffer.from(expected, class="tok-str">'utf8') const b = Buffer.from(parts.v1, class="tok-str">'utf8') return a.length === b.length && timingSafeEqual(a, b) } class=class="tok-str">"tok-cm">// Express: ham gövdeyi kullanın (express.raw) app.post(class="tok-str">'/hooks/flanque', express.raw({ type: class="tok-str">'application/json' }), (req, res) => { if (!verifyFlanqueSignature(req.body.toString(class="tok-str">'utf8'), req.get(class="tok-str">'X-Flanque-Signature'), process.env.FLANQUE_WEBHOOK_SECRET)) { return res.status(401).end() } const event = JSON.parse(req.body.toString(class="tok-str">'utf8')) res.status(200).end() })
İmzayı daima ham gövde üzerinde hesaplayın (JSON'u yeniden serileştirmeyin) ve sabit zamanlı karşılaştırma kullanın. Yanıt 2xx değilse teslim üstel geri çekilmeyle 5 kez yeniden denenir.
Mevcut uygulamanız SMTP konuşuyorsa yalnız sunucu bilgilerini değiştirmeniz yeterlidir. Kullanıcı adı proje SMTP kimliğidir; parola panelde oluşturulur ve yalnız bir kez gösterilir.
| Sunucu | smtp.flanque.com |
| Port | 2525 (STARTTLS) |
| Kimlik doğrulama | AUTH PLAIN / LOGIN |
| Kullanıcı adı | Proje SMTP kimliği (örn. novatech-prod) |
| Parola | SMTP kimlik parolası |
| Şifreleme | TLS 1.2+ zorunlu |
import nodemailer from class="tok-str">'nodemailer' const transport = nodemailer.createTransport({ host: class="tok-str">'smtp.flanque.com', port: 2525, secure: false, class=class="tok-str">"tok-cm">// STARTTLS auth: { user: class="tok-str">'novatech-prod', pass: process.env.FLANQUE_SMTP_PASSWORD }, }) await transport.sendMail({ from: class="tok-str">'Firma <info@firma.com>', to: class="tok-str">'musteri@example.com', subject: class="tok-str">'Siparişiniz onaylandı', html: class="tok-str">'<h1>Teşekkürler!</h1>', headers: { class="tok-str">'X-Flanque-Tag': class="tok-str">'order' }, })
Hata yanıtları { ok: false, code, message, fields? } biçimindedir. fields alanı doğrulama hatalarında alan bazlı mesaj taşır.
| Kod | HTTP | Anlam | Ne yapmalı |
|---|---|---|---|
BAD_INPUT | 400 | Gövde veya sorgu geçersiz. | fields alanındaki mesajlara göre isteği düzeltin. |
UNAUTHORIZED | 401 | API anahtarı eksik veya geçersiz. | Authorization: Bearer başlığını ve anahtarı kontrol edin. |
QUOTA | 402 | Plan kotası aşıldı. | Planı yükseltin veya dönem sonunu bekleyin. |
FORBIDDEN | 403 | Anahtar kapsamı bu işleme izin vermiyor. | send kapsamlı bir anahtar kullanın. |
NOT_FOUND | 404 | Kayıt bulunamadı. | Kimliği ve projeyi doğrulayın. |
CONFLICT | 409 | Çakışan kayıt (örn. aynı idempotencyKey farklı gövdeyle). | Yeni bir anahtar kullanın. |
RATE_LIMITED | 429 | Çok fazla istek. | Retry-After başlığına uyun; üstel geri çekilme uygulayın. |
{
"ok": false,
"code": "BAD_INPUT",
"message": "Alanları kontrol edin.",
"fields": { "to": "Geçerli bir e-posta adresi girin." }
}Sekiz dilde resmi istemci kütüphanesi; hepsi aynı OpenAPI şemasından üretilir ve idempotency, yeniden deneme ve webhook doğrulama yardımcıları içerir.