API

API endpoints

API endpoints are versioned together. Select an API version to jump to its section. All endpoint content is present in this HTML page.

API v1 Stable

v1 endpoints

GET Stable

Get quota status

/v1/quota

Use this endpoint when an app or coding agent needs to check whether the current environment can keep sending. The response is operational state, not billing authority.

Request

Name Type Required Description Example
Authorization string Yes Bearer API key for the EmailsDone environment. Bearer ed_...

curl

curl -X GET 'https://api.emailsdone.dev/v1/quota' \
  -H 'Authorization: Bearer ed_...'

Response

Name Type Required Description Example
ok boolean Yes True when quota was read. true
quota.tenantId string Yes Tenant identifier. tenant_123
quota.projectId string Yes Project identifier. project_123
quota.environmentId string Yes Environment identifier. production
quota.planId string Yes Plan id from the tenant limits snapshot. build
quota.accessStatus string Yes Billing access state. active
quota.sendingStatus string Yes Environment sending status. active
quota.period.id string Yes Current usage period id. 2026-05
quota.monthly.limit number Yes Monthly included email limit. 1000
quota.monthly.used number Yes Tenant emails sent in the current month. 42
quota.monthly.remaining number Yes Remaining included emails for the month. 958
quota.monthly.status string Yes Quota availability. available
quota.environment.usedThisMonth number Yes Environment emails sent in the current month. 42
{
  "ok": true,
  "quota": {
    "tenantId": "tenant_123",
    "projectId": "project_123",
    "environmentId": "production",
    "planId": "build",
    "accessStatus": "active",
    "sendingStatus": "active",
    "period": {
      "id": "2026-05",
      "startsAt": "2026-05-01T00:00:00.000Z",
      "endsAt": "2026-06-01T00:00:00.000Z"
    },
    "monthly": {
      "limit": 1000,
      "used": 42,
      "remaining": 958,
      "overageAllowed": false,
      "overageEmails": 0,
      "status": "available"
    },
    "environment": {
      "usedThisMonth": 42
    }
  }
}

Errors

StatusCodeMessage
401 missing_api_key Authorization bearer token is missing.
401 invalid_api_key API key is invalid.
402 trial_expired The trial can no longer send email.
403 api_key_revoked API key has been revoked.
403 tenant_not_found Tenant not found for API key.
403 project_inactive Project is disabled by the current plan.
403 environment_inactive Environment is disabled by the current plan.
404 project_not_found Project not found for API key.
404 environment_not_found Environment not found for API key.
405 method_not_allowed Only GET is allowed.
500 internal Unexpected server error.

Notes

  • Use this for operational status in dashboards and agent checks.
  • Do not use the client response as billing authority. Entitlements are backend-owned.
POST Stable

Resubscribe a recipient

/v1/recipients/resubscribe

Use this endpoint only when the recipient has explicitly chosen to receive app notifications again. It writes an audit event and clears the app notification unsubscribe state for the API key environment.

Request

Name Type Required Description Example
Authorization string Yes Bearer API key for the EmailsDone environment. Bearer ed_...
email email Yes Recipient email address to resubscribe. user@example.com
scope string Yes Subscription scope. V1 supports app notifications. app_notifications

curl

curl -X POST 'https://api.emailsdone.dev/v1/recipients/resubscribe' \
  -H 'Authorization: Bearer ed_...' \
  -H 'Content-Type: application/json' \
  -d '{
  "email": "user@example.com",
  "scope": "app_notifications"
}'

Response

Name Type Required Description Example
ok boolean Yes True when the recipient was marked as resubscribed. true
{
  "ok": true
}

Errors

StatusCodeMessage
400 Invalid resubscribe request. Expected a valid email and app_notifications scope.
401 missing_api_key Authorization bearer token is missing.
401 invalid_api_key API key is invalid.
402 trial_expired The trial can no longer send email.
403 api_key_revoked API key has been revoked.
405 method_not_allowed Only POST is allowed.
500 internal Unexpected server error.

Notes

  • Call this after an explicit user action, not automatically after a bounce or complaint.
  • The only V1 scope is app_notifications.
POST Stable

Get recipient status

/v1/recipients/status

Use this endpoint to inspect whether an app can send notifications to a recipient and to display recent delivery state without exposing raw message bodies.

Request

Name Type Required Description Example
Authorization string Yes Bearer API key for the EmailsDone environment. Bearer ed_...
email email Yes Recipient email address to inspect. user@example.com
limit number No Number of recent messages to return. Values are clamped between 1 and 50. 10

curl

curl -X POST 'https://api.emailsdone.dev/v1/recipients/status' \
  -H 'Authorization: Bearer ed_...' \
  -H 'Content-Type: application/json' \
  -d '{
  "email": "user@example.com",
  "limit": 10
}'

Response

Name Type Required Description Example
ok boolean Yes True when recipient status was read. true
recipient.emailMasked string Yes Masked recipient email. u***@example.com
recipient.recipientDomain string Yes Recipient domain. example.com
recipient.state string Yes Recipient delivery/subscription state. clear
recipient.subscription.status string Yes Notification subscription status. subscribed
recipient.delivery.hardBounceCount number Yes Hard bounce count for this recipient. 0
recipient.delivery.complaintCount number Yes Complaint count for this recipient. 0
recipient.canSendNotifications boolean Yes Whether notification templates can currently be sent. true
messages array Yes Recent message metadata for this recipient. []
{
  "ok": true,
  "recipient": {
    "emailMasked": "u***@example.com",
    "recipientDomain": "example.com",
    "state": "clear",
    "subscription": {
      "scope": "app_notifications",
      "status": "subscribed",
      "unsubscribedAt": null,
      "resubscribedAt": null
    },
    "delivery": {
      "hardBounceCount": 0,
      "complaintCount": 0,
      "cooldownUntil": null,
      "complainedAt": null
    },
    "canSendNotifications": true
  },
  "messages": []
}

Errors

StatusCodeMessage
400 invalid_request Expected a valid recipient email.
401 missing_api_key Authorization bearer token is missing.
401 invalid_api_key API key is invalid.
402 trial_expired The trial can no longer send email.
403 api_key_revoked API key has been revoked.
403 project_inactive Project is disabled by the current plan.
403 environment_inactive Environment is disabled by the current plan.
404 project_not_found Project not found for API key.
404 environment_not_found Environment not found for API key.
405 method_not_allowed Only POST is allowed.
500 internal Unexpected server error.

Notes

  • This endpoint returns metadata only. It does not expose email content.
  • Use canSendNotifications before showing notification-specific controls.
POST Stable

Send a transactional email

/v1/send

Use this endpoint for password resets, verification emails, app notifications, billing messages, and other transactional events. A successful response means the message has been accepted and queued, not that SES has already delivered it.

Request

Name Type Required Description Example
Authorization string Yes Bearer API key for the EmailsDone environment. Bearer ed_...
Idempotency-Key string No Optional retry key. Reusing the same key returns the original accepted message for 24 hours.
Max 120 characters
password-reset-user-123-2026-05-26
templateId string Yes Template identifier, for example password-reset or verify-email. password-reset
to email Yes Recipient email address. user@example.com
templateVersion string No Optional template version such as v1. If omitted, EmailsDone uses the latest published version for the template. v1
from email No Optional From address. For custom sending domains, the domain must match the effective project or environment sending domain. If omitted, EmailsDone uses the environment From Email setting, then the project From Email setting, then notifications@domain. notifications@example.com
fromName string No Optional display name for the From header. If omitted, EmailsDone uses the environment setting, then the project setting.
Max 120 characters
Acme App
replyTo email No Optional Reply To email address. If omitted, EmailsDone uses the environment setting, then the project setting. support@example.com
data object Yes Template data. Required and optional fields are derived from the selected template blocks. {"actionButton":{"label":"Reset password","url":"https://app.example.com/reset/token"}}

curl

curl -X POST 'https://api.emailsdone.dev/v1/send' \
  -H 'Authorization: Bearer ed_...' \
  -H 'Content-Type: application/json' \
  -d '{
  "templateId": "password-reset",
  "templateVersion": "v1",
  "to": "user@example.com",
  "from": "notifications@example.com",
  "fromName": "Acme App",
  "replyTo": "support@example.com",
  "data": {
    "actionButton": {
      "label": "Reset password",
      "url": "https://app.example.com/reset/token"
    }
  }
}'

Response

Name Type Required Description Example
ok boolean Yes True when the request was accepted. true
status string Yes Message acceptance state. accepted
messageId string Yes Message record identifier for later operational lookup. msg_abc123
idempotent boolean Yes True when the response is for an earlier request with the same Idempotency-Key. false
{
  "ok": true,
  "status": "accepted",
  "messageId": "msg_abc123",
  "idempotent": false
}

Errors

StatusCodeMessage
400 invalid_request Expected templateId, to, and data.
400 invalid_from_address From address failed validation.
400 invalid_from_name From name failed validation.
400 invalid_reply_to Reply To failed validation.
400 invalid_template_data Template data failed validation.
401 missing_api_key Authorization bearer token is missing.
401 invalid_api_key API key is invalid.
402 trial_expired The trial can no longer send email.
403 api_key_revoked API key has been revoked.
403 monthly_quota_exceeded Tenant has exhausted the monthly quota.
403 app_paused Sending is paused for the app.
403 app_blocked Sending is blocked for the app.
403 recipient_complained Recipient has complained.
403 recipient_unsubscribed Recipient is unsubscribed from notifications.
403 sending_domain_not_ready The configured sending domain is not verified yet.
403 from_domain_not_allowed From address does not match the configured sending domain.
404 project_not_found Project not found for API key.
404 environment_not_found Environment not found for API key.
404 template_not_found Template was not found.
404 template_version_not_found Requested template version was not found.
405 method_not_allowed Only POST is allowed.
500 internal Unexpected server error.

Notes

  • Use Idempotency-Key for password resets, billing emails, and other retry-prone workflows.
  • Do not send HTML. Choose a templateId and pass the required template data.
  • Treat accepted as queued. Delivery and bounce state are recorded asynchronously.