HTTP API
Applications that aren't Node can integrate directly over HTTP. The send API is one endpoint, authenticated with a project API key.
Authentication
Pass the key as a bearer token. Keys are project-scoped; the template you reference must belong to the same project.
Authorization: Bearer solen_xxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxPOST /v1/emails
curl -X POST http://localhost:4000/v1/emails \
-H "Authorization: Bearer $SOLEN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"template": "welcome-email",
"to": "student@example.com",
"variables": { "name": "Priya", "school": "Northside High" }
}'| Field | Type | Required | Notes |
|---|---|---|---|
template | string | yes | Template slug within the key's project. |
to | string | yes | Recipient email address. |
variables | object | no | String values substituted into {{placeholders}}. |
Success - 200
{
"id": "log_cmb1xk2...",
"status": "SUCCESS",
"messageId": "re_AbC123..."
}Provider failure - 422
{
"id": "log_cmb1xk9...",
"status": "FAILED",
"error": { "code": "PROVIDER_ERROR", "message": "Domain not verified" }
}Both outcomes write a log row; id is always the log id. Other errors use the standard error shape without an id when nothing was renderable to log (e.g. unknown template).
Error responses
| Status | Code | When |
|---|---|---|
401 | UNAUTHORIZED | Missing, malformed, revoked, or unknown key. |
404 | TEMPLATE_NOT_FOUND | Slug doesn't exist in the key's project. |
409 | TEMPLATE_DISABLED | Template is toggled off. |
400 | INVALID_PAYLOAD | Validation failure; message says which field. |
422 | PROVIDER_ERROR | Provider rejected the send (logged). |
429 | RATE_LIMITED | Over 60 requests/minute on one key. |
GET /v1/health
Unauthenticated liveness probe; returns { "ok": true }.
Rate limits
The send API allows 60 requests per minute per key. Batch and queue sends client-side for now - bulk sending is a Phase 3 roadmap item.