Dokumentation

Die ridu-API ist kompatibel zu Resend: gleiche Pfade, Felder, Fehler und Webhook-Signaturen.

In drei Schritten

  1. Konto anlegen und API-Key kopieren.
  2. Domain hinzufügen und die zwei DNS-Einträge setzen.
  3. Mit dem Resend-SDK oder curl senden.

Authentifizierung

Jeder Aufruf trägt einen API-Key als Bearer-Token. Live-Keys (rd_live_) stellen zu, Test-Keys (rd_test_) durchlaufen alles, stellen aber nie zu. Limit: 10 Anfragen pro Sekunde je Organisation.

curl https://api.ridu.ai/domains \
  -H "Authorization: Bearer rd_live_…"

E-Mails senden

Der Idempotency-Key macht Wiederholungen sicher: dieselbe Anfrage innerhalb von 24 Stunden erzeugt keine zweite Mail.

curl -X POST https://api.ridu.ai/emails \
  -H "Authorization: Bearer rd_live_…" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-4711" \
  -d '{
    "from": "Acme <hallo@mail.acme.de>",
    "to": ["kunde@example.com"],
    "subject": "Deine Bestellung",
    "html": "<p>Danke!</p>",
    "tags": [{"name": "kind", "value": "order"}],
    "scheduled_at": "in 1 hour"
  }'

Weitere Felder: cc, bcc, reply_to, text (wird sonst aus html erzeugt), headers, attachments (content als Base64 oder path als URL, zusammen bis 40 MB), template, topic_id. Bis zu 100 Mails auf einmal über POST /emails/batch.

SMTP

Für Anwendungen ohne API-Anbindung. Bcc-Empfänger kommen aus dem SMTP-Umschlag, die Nachricht bleibt so, wie deine App sie baut.

Host:     smtp.ridu.ai
Port:     465 (TLS) oder 587 (STARTTLS)
User:     ridu
Passwort: rd_live_…

Optionale Header: X-Ridu-Tags: kind=order, Ridu-Idempotency-Key: …

Webhooks

Webhooks sind wie bei Svix signiert. Prüfe sie mit der svix-Bibliothek und dem Signatur-Secret aus dem Dashboard. Fehlgeschlagene Zustellungen wiederholen wir 7-mal über 32 Stunden.

import { Webhook } from "svix";

const event = new Webhook(process.env.RIDU_WEBHOOK_SECRET)
  .verify(rawBody, {
    "svix-id": req.headers["svix-id"],
    "svix-timestamp": req.headers["svix-timestamp"],
    "svix-signature": req.headers["svix-signature"],
  });

Event-Typen: email.sent email.scheduled email.delivered email.delivery_delayed email.bounced email.complained email.opened email.clicked email.failed email.suppressed email.canceled domain.created domain.updated domain.deleted contact.created contact.updated contact.deleted contact.topics.updated suppression.added suppression.removed

Testen

Diese Adressen erzeugen das jeweilige Ereignis, ohne dass etwas zugestellt wird oder das Kontingent belastet:

  • delivered@test.ridu.ai
  • bounced@test.ridu.ai
  • complained@test.ridu.ai
  • delayed@test.ridu.ai
  • suppressed@test.ridu.ai

Von Resend wechseln

Die offiziellen Resend-SDKs funktionieren unverändert. Setze den Key und die Basis-URL; Domains verifizierst du einmal neu, weil der DKIM-Schlüssel bei ridu liegt.

RESEND_API_KEY=rd_live_…
RESEND_BASE_URL=https://api.ridu.ai   # Node, PHP
RESEND_API_URL=https://api.ridu.ai    # Python

Fehler

Fehler haben dieselbe Form und dieselben Namen wie bei Resend, zum Beispiel validation_error, rate_limit_exceeded oder daily_quota_exceeded.

{
  "statusCode": 422,
  "name": "missing_required_field",
  "message": "Missing `subject` field."
}

Alle Endpunkte

Die Liste kommt direkt aus dem Router und ist damit immer vollständig.

MethodePfadKey
POST/emailsNur senden
POST/emails/batchNur senden
GET/emailsVollzugriff
GET/emails/{id}Vollzugriff
PATCH/emails/{id}Vollzugriff
POST/emails/{id}/cancelVollzugriff
POST/domainsVollzugriff
GET/domainsVollzugriff
GET/domains/{id}Vollzugriff
PATCH/domains/{id}Vollzugriff
DELETE/domains/{id}Vollzugriff
POST/domains/{id}/verifyVollzugriff
GET/suppressionsVollzugriff
POST/suppressionsVollzugriff
DELETE/suppressions/{email}Vollzugriff
POST/templatesVollzugriff
GET/templatesVollzugriff
GET/templates/{id}Vollzugriff
PATCH/templates/{id}Vollzugriff
DELETE/templates/{id}Vollzugriff
POST/templates/{id}/publishVollzugriff
POST/contactsVollzugriff
GET/contactsVollzugriff
GET/contacts/{id}Vollzugriff
PATCH/contacts/{id}Vollzugriff
DELETE/contacts/{id}Vollzugriff
GET/contacts/{id}/consentsVollzugriff
GET/contacts/{id}/segmentsVollzugriff
POST/contacts/{id}/segments/{segment}Vollzugriff
DELETE/contacts/{id}/segments/{segment}Vollzugriff
GET/contacts/{id}/topicsVollzugriff
PATCH/contacts/{id}/topicsVollzugriff
POST/segmentsVollzugriff
GET/segmentsVollzugriff
GET/segments/{id}Vollzugriff
PATCH/segments/{id}Vollzugriff
DELETE/segments/{id}Vollzugriff
GET/segments/{id}/contactsVollzugriff
POST/audiencesVollzugriff
GET/audiencesVollzugriff
GET/audiences/{id}Vollzugriff
DELETE/audiences/{id}Vollzugriff
POST/audiences/{id}/contactsVollzugriff
GET/audiences/{id}/contactsVollzugriff
GET/audiences/{aud}/contacts/{id}Vollzugriff
PATCH/audiences/{aud}/contacts/{id}Vollzugriff
DELETE/audiences/{aud}/contacts/{id}Vollzugriff
POST/topicsVollzugriff
GET/topicsVollzugriff
GET/topics/{id}Vollzugriff
PATCH/topics/{id}Vollzugriff
DELETE/topics/{id}Vollzugriff
POST/broadcastsVollzugriff
GET/broadcastsVollzugriff
GET/broadcasts/{id}Vollzugriff
PATCH/broadcasts/{id}Vollzugriff
DELETE/broadcasts/{id}Vollzugriff
POST/broadcasts/{id}/sendVollzugriff
POST/broadcasts/{id}/cancelVollzugriff
POST/webhooksVollzugriff
GET/webhooksVollzugriff
GET/webhooks/{id}Vollzugriff
PATCH/webhooks/{id}Vollzugriff
DELETE/webhooks/{id}Vollzugriff
POST/webhooks/{id}/testVollzugriff
POST/api-keysVollzugriff
GET/api-keysVollzugriff
DELETE/api-keys/{id}Vollzugriff