docs.getting_started.title

docs.getting_started.intro

docs.getting_started.intro2

docs.getting_started.step1.title

docs.getting_started.step1.desc

docs.getting_started.step2.title

docs.getting_started.step2.desc

docs.getting_started.step3.title

docs.getting_started.step3.desc

docs.mail.title

docs.mail.desc

  • docs.mail.feature1
  • docs.mail.feature2
  • docs.mail.feature3
  • docs.mail.feature4

docs.calendar.title

docs.calendar.desc

  • docs.calendar.feature1
  • docs.calendar.feature2
  • docs.calendar.feature3
  • docs.calendar.feature4

docs.notes.title

docs.notes.desc

  • docs.notes.feature1
  • docs.notes.feature2
  • docs.notes.feature3
  • docs.notes.feature4

docs.passwords.title

docs.passwords.desc

  • docs.passwords.feature1
  • docs.passwords.feature2
  • docs.passwords.feature3
  • docs.passwords.feature4

docs.security.title

docs.security.desc

docs.nav.2fa

docs.security.2fa

docs.encryption.title

  • docs.encryption.key_exchange: X25519 (Curve25519)
  • docs.encryption.encryption: XChaCha20-Poly1305
  • docs.encryption.key_derivation: Argon2id
  • docs.encryption.recovery: BIP39 (24 words)

docs.api.title

docs.api.desc

Getting started

  1. Add a domain and verify it (DNS) under Domains.
  2. Add a verified sender identity (a From address on that domain).
  3. Create an API key for the domain under API — copy it once; only its hash is stored.

Authentication

Pass your key as a Bearer token. Base URL: https://api.defnd.email/v1.

Authorization: Bearer dfnd_xxxxxxxx...

Send an email

from and reply_to must be verified sender identities on a domain your key is scoped to.

curl -X POST https://api.defnd.email/v1/emails \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "from": "hello@yourdomain.com", "reply_to": "hello@yourdomain.com", "to": "recipient@example.com", "subject": "Hello", "html": "<p>Message content</p>", "text": "Message content" }'

Idempotency

Pass an Idempotency-Key header (any unique string, max 255 chars) on POST /v1/emails to make retries safe: a repeated key within 24 hours returns the original response — marked with Idempotency-Replayed: true — instead of sending a duplicate. While the first request is still in flight, duplicates get 409 with Retry-After.

-H "Idempotency-Key: order-42-confirmation"

Other endpoints

  • POST /v1/emails/batch — send up to 100 messages in one request ({"emails":[ ... ]}).
  • GET /v1/emails, GET /v1/emails/{id} — list and check delivery status.
  • GET/POST /v1/templates, POST /v1/templates/{id}/render — reusable templates with {{variable}} placeholders.
  • GET/POST /v1/webhooksemail.queued / delivered / opened / clicked / bounced / unsubscribed events (HMAC-signed; HTTPS only).
  • GET /v1/suppressions, DELETE /v1/suppressions/{email} — bounce/complaint suppression list.
  • GET /v1/domains, GET /v1/domains/{domain}/stats — domains and sending stats.

Keys are scoped: requests are limited to the scopes you grant (transactional:send, transactional:read, templates:read, templates:write, webhooks:manage) and to the key's verified domains.

Webhook signatures

Every webhook request carries X-Defnd-Signature: sha256=<hex> — an HMAC-SHA256 of the raw request body with your webhook's secret. Verify it before trusting the event (the Node/Go SDKs ship a verifyWebhookSignature helper).