Sendings
The Sending resource is Hantera’s centralized communication queue system. It tracks queued messages (emails, and in the future: SMS, push notifications) through the entire delivery lifecycle with granular status tracking and automatic retries.
What is a Sending?
A Sending represents a single queued communication to a primary recipient. When you send an email using the sendEmail function, a Sending record is created to track delivery status, retries, and any errors that occur.
Key characteristics:
- One record per primary recipient: Multi-recipient emails create one record for the
torecipient; CC/BCC are best-effort delivery - Asynchronous processing: Messages are queued and processed in the background
- Status tracking: Monitor pending, sent, and bounced messages via the Graph API
- Rate limiting: Respects configured rate limits to avoid overwhelming mail servers
- Automatic retries: Transient failures are automatically retried with exponential backoff (up to 3 times)
Creating Sendings
Sendings can be created in two ways depending on your use case:
Via Filtrera (Components/Reactors)
Use the sendEmail function in Filtrera for component and reactor logic:
import 'resources'
from sendEmail { subject = 'Order Confirmation' body = { plainText = 'Thank you for your order!' html = '<h1>Thank you for your order!</h1>' } category = 'order_confirmation' dynamic = { orderId = order.id }}See: sendEmail function documentation
Via REST API (External Applications)
For external applications, use the HTTP API:
POST /resources/sendings/email{ "subject": "Order Confirmation", "body": { "plainText": "Thank you for your order!", "html": "<h1>Thank you for your order!</h1>" }, "category": "order_confirmation", "dynamic": { "orderId": "12345" }}Lifecycle & Status
Each Sending progresses through these states:
pending
The message is queued and waiting to be processed by the background service. Pending sendings can be cancelled via the REST API.
sent
The message was successfully delivered to the mail server. Note that this indicates delivery to the mail server, not necessarily to the recipient’s inbox.
bounced
Delivery failed after all retries were exhausted. Check the errorMessage field for details.
cancelled
The sending was cancelled before being processed. Only pending sendings can be cancelled using the DELETE /resources/sendings/{id} REST endpoint.
Transport Types
The transport field indicates the communication channel:
email: Email delivery (currently supported)sms: SMS delivery (planned)push: Push notification (planned)
Currently, only email transport is implemented.
Processing Behavior
How it works:
- Queueing: When
sendEmailis called, a Sending record is created withpendingstatus - Processing: Background service processes the queue every 10 seconds (configurable)
- Rate limiting: Default 60 emails/minute (configurable)
- Retries: Failed deliveries are retried up to 3 times with exponential backoff
- Final status: After retries, status becomes either
sentorbounced
Multi-Recipient Behavior
When you provide cc or bcc lists:
- One Sending record is created for the primary
torecipient (with tracked status) - CC and BCC recipients receive the email as best-effort delivery
- No individual tracking for CC/BCC recipients
The cc and bcc recipients are stored as comma-separated strings in the Sending record’s data field, but do not have their own Sending records or status tracking.
Querying Sendings
Use the Graph API to query Sending records:
[ { "edge": "sendings", "filter": "status == 'pending'", "orderBy": "createdAt desc", "node": { "fields": ["sendingId", "recipient", "category", "createdAt"] } }]See: Sending Graph Node for complete query documentation
Custom Data
Store queryable data in the dynamic field:
import 'resources'
from sendEmail { to = customer.email subject = 'Campaign Offer' body = { html = '<p>Special offer just for you!</p>' } dynamic = { customerId = customer.id campaignId = campaign.id segmentId = segment.id }}Then define custom Graph fields to query this data:
uri: /resources/registry/graph/sending/fields/campaignIdspec: value: type: text source: dynamic->'campaignId'Now you can query by campaign:
[ { "edge": "sendings", "filter": "campaignId == '12345' and status == 'sent'", "count": true }]Access Control
Creating sendings requires the sendings:write permission:
sendings:write # Create new sendings via sendEmail or REST APIQuerying sendings uses the Graph API, which requires Graph-specific permissions:
graph/sending:query # Query sending recordsgraph/sending:field # Access specific fieldsManaging sendings via REST requires:
sendings:write # POST /resources/sendings/email (create)sendings:read # GET /resources/sendings/{id} (retrieve status)sendings:write # DELETE /resources/sendings/{id} (cancel)REST API
The Sending resource includes a REST API for queueing, monitoring, and cancelling email delivery from external applications.
Available Endpoints
POST /resources/sendings/email- Queue an email for deliveryGET /resources/sendings/{id}- Retrieve sending status and detailsDELETE /resources/sendings/{id}- Cancel a pending sending
When to Use REST vs Filtrera
Use REST API when:
- Building external integrations
- Sending emails from non-Hantera environments
- Need direct HTTP access without Filtrera runtime
Use Filtrera sendEmail when:
- Writing automations using rules and jobs within Hantera
- Building Hantera apps
Examples
For practical examples of using the Sendings REST API in real-world scenarios, see the Customer Registration for E-Commerce guide which demonstrates sending registration confirmations and password reset emails.
Cancelling Sendings
Only sendings with pending status can be cancelled. Attempting to cancel sent, bounced, or already cancelled sendings returns a 409 Conflict error.
DELETE /resources/sendings/{sendingId}Returns:
204 No Content- Successfully cancelled404 Not Found- Sending does not exist409 Conflict- Sending status is not pending
Monitoring & Troubleshooting
Check Queue Depth
Monitor the number of pending sendings:
[ { "edge": "sendings", "filter": "status == 'pending'", "count": true }]Health indicators:
- Healthy: < 50 pending
- Warning: 50-100 pending
- Critical: > 100 pending
Find Recent Failures
[ { "edge": "sendings", "filter": "status == 'bounced' and createdAt >= '2025-10-30T00:00:00Z'", "orderBy": "createdAt desc", "node": { "fields": ["sendingId", "recipient", "errorMessage", "retryCount", "category"] } }]Calculate Bounce Rate
[ { "edge": "sendings", "alias": "total", "filter": "createdAt >= '2025-10-01T00:00:00Z'", "count": true }, { "edge": "sendings", "alias": "bounced", "filter": "createdAt >= '2025-10-01T00:00:00Z' and status == 'bounced'", "count": true }]A bounce rate above 5% may indicate email list quality issues.
Related Resources
- sendEmail Function - Filtrera function for creating sendings
- Sending Graph Node - Query syntax and patterns
- Sending Emails Guide - Complete guide with use cases and examples
- Custom Fields - Define queryable fields on dynamic data