Send via REST API
Send transactional and marketing emails programmatically using the Taifa Mail REST API.
The REST API is the most flexible way to send email through Taifa Mail. All requests go to https://govconnect.ke/v1/ and require an API key.
Authentication
Include your API key in the Authorization header on every request. API keys are prefixed with tfm_k_:
Generate API keys at Settings -> API Keys -> Create Key.
POST /v1/emails/
Send a single email. Note the trailing slash on the path.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
from_ | object | Yes | Sender address. Must be a registered sender on a verified domain. |
from_.email | string | Yes | Sender email address. |
from_.name | string | No | Sender display name. |
to | array | Yes | Array of recipient {email, name} objects. At least one required. |
to[].email | string | Yes | Recipient email address. |
to[].name | string | No | Recipient display name. |
subject | string | Yes | Email subject line. |
html | string | No | HTML body. At least one of html or text is required. |
text | string | No | Plain text body. At least one of html or text is required. |
cc | array | No | Array of {email, name} objects for CC recipients. |
bcc | array | No | Array of {email, name} objects for BCC recipients. |
reply_to | object | No | {email, name} object for the Reply-To header. |
headers | object | No | Key-value pairs of custom email headers. |
tags | array | No | Array of strings for categorization and filtering. |
send_at | string | No | ISO 8601 datetime to schedule delivery. Omit to send immediately. See Scheduling. |
attachments | array | No | Array of attachment objects (see below). |
Attachments
Each attachment is an object with the file body base64-encoded:
| Field | Type | Required | Description |
|---|---|---|---|
filename | string | Yes | File name. Must not contain path separators (/, \) or NUL. |
content_base64 | string | Yes | File body as base64. No data: URL prefix. |
content_type | string | No | MIME type. Defaults to application/octet-stream. |
Each file is capped at 24 MiB, and the combined size of all attachments is also capped at 24 MiB. Oversized attachments return 413.
Example: cURL
Example: Node.js (fetch)
Example: Python (requests)
Response
A successful request returns 202 Accepted:
| Field | Description |
|---|---|
id | The email's UUID. Use this to query status, events, or retry. |
status | queued for an immediate send, scheduled if send_at was provided. |
message_id | RFC 5322 Message-ID header value. |
rejection_reason | Reason the email was rejected, or null if accepted. |
A 202 means the email was accepted for delivery, not that it was delivered. Use webhooks or the events endpoint to track delivery status.
POST /v1/emails/validate
Dry-run validation. Checks whether an email would send without actually sending it. It validates the sender address, domain verification, plan send limits, recipients, content, and account restrictions. The request body is identical to POST /v1/emails/.
Response:
If a check fails, issues contains one or more {field, error} objects and both valid and can_send are false.
GET /v1/emails/:id
Retrieve a single email by its UUID, including its bodies, headers, and event history.
GET /v1/emails/:id/events
List every tracked event for an email (queued, sent, delivered, opened, clicked, bounced, cancelled, and so on). Each event has an event_type, optional metadata, and a created_at timestamp.
POST /v1/emails/:id/retry
Retry a previously failed email. Only emails with status bounced, rejected, or failed can be retried; any other status returns 409 Conflict. The retry creates a new email row linked back to the original; the original is preserved. The response shape matches POST /v1/emails/.
GET /v1/emails/search
Search emails by recipient, sender, subject, status, domain, or tag. The free-text q parameter accepts inline tokens that translate to structured filters:
| Token | Effect |
|---|---|
to:gmail.com | Substring match on the recipient list. |
from:hello@govconnect.ke | Substring match on the sender address. |
status:bounced | Exact status match. |
domain:govconnect.ke | Substring match on the sending domain. |
tag:welcome | Exact tag match. |
Any remaining words become a free-text search across sender, subject, and recipients. Status and tag can also be passed as the separate query parameters status and tag. Results are paginated with page (default 0) and limit (default 20, max 100).
GET /v1/emails/
List emails with an optional status filter and page / limit pagination.
Error handling
| Status | Meaning |
|---|---|
400 Bad Request | Invalid attachment encoding, bad send_at value, or batch size over the plan limit. |
401 Unauthorized | Missing or invalid API key. |
403 Forbidden | Plan feature gate or send limit reached. |
404 Not Found | The referenced email does not exist. |
409 Conflict | The email cannot be retried in its current status. |
413 Payload Too Large | Attachment exceeds the per-file or combined size cap. |
422 Unprocessable Entity | Validation error in the request body. |