Skip to content

Email

Transactional email over a REST API — plus the surrounding machinery you actually need in production: domain authentication, templates, contact lists, suppression handling, and delivery stats.

Terminal window
curl -X POST https://api.9bits.net/email/ng/v1/messages \
-H "Authorization: Bearer 9bk_xxx" \
-H "Content-Type: application/json" \
-d '{
"from": { "email": "hello@yourdomain.com", "name": "Acme" },
"to": [{ "email": "customer@example.com", "name": "Jane" }],
"subject": "Your receipt",
"html": "<p>Thanks for your order.</p>"
}'

Note that from and to are objects, not bare strings — { "email": …, "name": … }.

Email keys are prefixed 9bk_ and carry scopes, so you can issue a key that reads stats but cannot send:

ScopeGrants
email:readRead endpoints — messages, stats, contacts, domains
email:sendPOST /messages
email:webhooksManage webhook endpoints

Mint them under Email → API Keys. Give each integration the narrowest scope that does its job — your analytics dashboard doesn’t need email:send.

Messages

Send HTML and plain-text email, with attachments and templates. Idempotent via Idempotency-Key.

Domains

Verify sending domains and check SPF/DKIM/DMARC status.

Contacts & lists

Manage recipients and mailing lists.

Suppressions

Bounces and complaints, automatically suppressed. Never re-send to a hard bounce.

Templates

Store and render reusable templates server-side.

Stats

Delivery, open and bounce rates, daily or aggregate.

Every response carries:

  • X-RateLimit-Limit
  • X-RateLimit-Remaining
  • X-RateLimit-Reset

On 429, honour Retry-After (seconds).

{ "error": { "code": "domain_not_verified", "message": "yourdomain.com is not verified" } }

Common codes: missing_auth, invalid_api_key, insufficient_scope, validation_error, insufficient_balance, domain_not_verified, not_found, rate_limit_exceeded.

Some validation errors also carry a fields object pinpointing what was wrong.