Email, sent direct
Sent straight to the recipient’s mail server, signed with your domain’s DKIM key.
One API for email, SMS, and in-app messages. Charon accepts each request once, carries it to the person it’s for, and keeps evidence of what happened.
Notification 0193a7c2
Delivered
The notification and its delivery job are saved together. A retry gets the first answer back.
Workers lease each job. Temporary failures retry, and permanent ones stop.
Every attempt leaves evidence, sent to you as signed webhooks.
If a server drops the connection after taking a message, Charon marks it unknown instead of sending it twice.
Sent straight to the recipient’s mail server, signed with your domain’s DKIM key.
Segments are counted before sending, with a receipt for each one.
A feed for each person, with unread counts.
Send a notification with an idempotency key. Charon answers 202 Accepted
once the notification and its delivery job are stored together.
GET /v1/notifications/{id} returns state and timestamps, never the recipient or content.POST /v1/notifications
Authorization: Bearer chr_live.<id>.<secret>
Idempotency-Key: order-42
Content-Type: application/json
{
"channel": {
"type": "email",
"to": "ada@example.net",
"sender_domain_id": "8d3f…",
"template_version_id": "0c21…",
"variables": { "order_id": "42" }
}
}
curl "$CHARON_URL/v1/notifications" \
-H "Authorization: Bearer $CHARON_API_KEY" \
-H "Idempotency-Key: order-42" \
-H "Content-Type: application/json" \
-d '{
"channel": { "type": "in_app", "recipient_id": "user-1" },
"body": "Your order is ready."
}'
const response = await fetch(`${CHARON_URL}/v1/notifications`, {
method: 'POST',
headers: {
authorization: `Bearer ${process.env.CHARON_API_KEY}`,
'idempotency-key': `order-${order.id}`,
'content-type': 'application/json',
},
body: JSON.stringify({
channel: { type: 'in_app', recipient_id: user.id },
body: 'Your order is ready.',
}),
});
// response.status === 202
202 Accepted Idempotency-Replayed: false
An API key for the hosted service, and help setting up your sending domains and SMS senders. We start with the channels and volume you tell us about.
Ask the status API with the notification’s ID, or subscribe to signed webhooks for delivery, bounce, and complaint events.
Yes. Send the same request with the same idempotency key and Charon returns the original answer instead of sending again.
Only what it needs to deliver and prove delivery. The status API never returns recipients or content, and logs never contain them.