Dokumentation
Die ridu-API ist kompatibel zu Resend: gleiche Pfade, Felder, Fehler und Webhook-Signaturen.
In drei Schritten
- Konto anlegen und API-Key kopieren.
- Domain hinzufügen und die zwei DNS-Einträge setzen.
- 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.aibounced@test.ridu.aicomplained@test.ridu.aidelayed@test.ridu.aisuppressed@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 # PythonFehler
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.
| Methode | Pfad | Key |
|---|---|---|
| POST | /emails | Nur senden |
| POST | /emails/batch | Nur senden |
| GET | /emails | Vollzugriff |
| GET | /emails/{id} | Vollzugriff |
| PATCH | /emails/{id} | Vollzugriff |
| POST | /emails/{id}/cancel | Vollzugriff |
| POST | /domains | Vollzugriff |
| GET | /domains | Vollzugriff |
| GET | /domains/{id} | Vollzugriff |
| PATCH | /domains/{id} | Vollzugriff |
| DELETE | /domains/{id} | Vollzugriff |
| POST | /domains/{id}/verify | Vollzugriff |
| GET | /suppressions | Vollzugriff |
| POST | /suppressions | Vollzugriff |
| DELETE | /suppressions/{email} | Vollzugriff |
| POST | /templates | Vollzugriff |
| GET | /templates | Vollzugriff |
| GET | /templates/{id} | Vollzugriff |
| PATCH | /templates/{id} | Vollzugriff |
| DELETE | /templates/{id} | Vollzugriff |
| POST | /templates/{id}/publish | Vollzugriff |
| POST | /contacts | Vollzugriff |
| GET | /contacts | Vollzugriff |
| GET | /contacts/{id} | Vollzugriff |
| PATCH | /contacts/{id} | Vollzugriff |
| DELETE | /contacts/{id} | Vollzugriff |
| GET | /contacts/{id}/consents | Vollzugriff |
| GET | /contacts/{id}/segments | Vollzugriff |
| POST | /contacts/{id}/segments/{segment} | Vollzugriff |
| DELETE | /contacts/{id}/segments/{segment} | Vollzugriff |
| GET | /contacts/{id}/topics | Vollzugriff |
| PATCH | /contacts/{id}/topics | Vollzugriff |
| POST | /segments | Vollzugriff |
| GET | /segments | Vollzugriff |
| GET | /segments/{id} | Vollzugriff |
| PATCH | /segments/{id} | Vollzugriff |
| DELETE | /segments/{id} | Vollzugriff |
| GET | /segments/{id}/contacts | Vollzugriff |
| POST | /audiences | Vollzugriff |
| GET | /audiences | Vollzugriff |
| GET | /audiences/{id} | Vollzugriff |
| DELETE | /audiences/{id} | Vollzugriff |
| POST | /audiences/{id}/contacts | Vollzugriff |
| GET | /audiences/{id}/contacts | Vollzugriff |
| GET | /audiences/{aud}/contacts/{id} | Vollzugriff |
| PATCH | /audiences/{aud}/contacts/{id} | Vollzugriff |
| DELETE | /audiences/{aud}/contacts/{id} | Vollzugriff |
| POST | /topics | Vollzugriff |
| GET | /topics | Vollzugriff |
| GET | /topics/{id} | Vollzugriff |
| PATCH | /topics/{id} | Vollzugriff |
| DELETE | /topics/{id} | Vollzugriff |
| POST | /broadcasts | Vollzugriff |
| GET | /broadcasts | Vollzugriff |
| GET | /broadcasts/{id} | Vollzugriff |
| PATCH | /broadcasts/{id} | Vollzugriff |
| DELETE | /broadcasts/{id} | Vollzugriff |
| POST | /broadcasts/{id}/send | Vollzugriff |
| POST | /broadcasts/{id}/cancel | Vollzugriff |
| POST | /webhooks | Vollzugriff |
| GET | /webhooks | Vollzugriff |
| GET | /webhooks/{id} | Vollzugriff |
| PATCH | /webhooks/{id} | Vollzugriff |
| DELETE | /webhooks/{id} | Vollzugriff |
| POST | /webhooks/{id}/test | Vollzugriff |
| POST | /api-keys | Vollzugriff |
| GET | /api-keys | Vollzugriff |
| DELETE | /api-keys/{id} | Vollzugriff |