Resend Email Service And Webhooks¶
This project uses Resend for outbound sales-invoice email delivery and for delivery/open/click/failure lifecycle webhooks.
Outbound Email Service¶
Outbound sends happen in accounting/invoice_email.py through Resend’s
/emails API and are called from SalesInvoiceEmailSendView.
Required environment variables:
RESEND_API_KEYRESEND_FROM_EMAIL(or legacy aliasRESEND_EMAIL_FROM)
Optional environment variables:
RESEND_REPLY_TORESEND_API_BASE_URL(default:https://api.resend.com)RESEND_REQUEST_TIMEOUT_SECONDS(default:20)RESEND_USER_AGENT(default:inkforje-accounting/1.0)
Webhook Endpoint¶
The application exposes a CSRF-exempt webhook endpoint:
/ledger/webhooks/resend/
Register this URL in Resend as:
https://<your-domain>/ledger/webhooks/resend/
Signature Verification¶
Incoming webhooks are verified with Svix headers:
svix-idsvix-timestampsvix-signature
The app verifies signatures using RESEND_WEBHOOK_SECRET before processing
events.
Webhook Secret Configuration¶
Set this in your environment file:
RESEND_WEBHOOK_SECRET=whsec_xxxxx
Local env file path:
/Users/danielmontecillo/Development/django/inkforje_accounting/.env
Production env file path (from deployment workflow):
<DEPLOY_PATH>/.env
Event Handling And Status Mapping¶
Supported Resend event types and mapped SalesInvoiceEmailLog.status:
email.scheduled->scheduledemail.sent->sentemail.delivered->deliveredemail.delivery_delayed->delivery_delayedemail.opened->openedemail.clicked->clickedemail.complained->complainedemail.bounced->bouncedemail.suppressed->suppressedemail.failed->failed
Webhook events that do not match a known provider_message_id are safely
acknowledged with HTTP 204 and ignored.
Data Stored Per Event¶
For each matched event, the app updates the existing email log row with:
statuslast_event_typelast_event_atprovider_response(raw event payload)error_message(for failed/bounced/suppressed/delayed reasons when present)
UI Surfaces Updated¶
Webhook-driven status appears in:
Sales Invoice detail status indicator
Sales Invoice update status indicator
Sales Correspondence list
Customer detail correspondence table
Setup Checklist¶
Add Resend API and webhook environment variables.
Run migrations:
uv run python manage.py migrate
Restart the Django process.
In Resend, subscribe email event types listed above.
Send a test sales invoice email and verify status changes in the UI.