Notix
API reference

Emails.

Send one email or a batch, read them back, and change or cancel a scheduled send. Every request needs an API key in the Authorization header; the reference overview covers keys, errors and rate limits.

Send an email

POST/v1/emailsSending or full access key

Send one transactional email. The response carries the emailId every webhook event for the message refers to.

Limits

Every send request is bounded. The checks run before the email is stored, so a request that breaks one of them costs nothing and creates nothing.

FieldLimit
Request body20 MB, applied at the edge
to, cc, bcc50 recipients across the three fields, counted on distinct addresses
subject998 characters
html2,000,000 characters
text2,000,000 characters
attachments10 files
attachments[].filename255 characters
attachments[].content7 MB per file, once decoded from base64
attachments total10 MB per email, once decoded from base64

Attachment sizes are measured after base64 decoding, so a 7 MB file is about 9.4 MB of base64 in the request body.

Recipients

to, cc and bcc each take a single address or an array of them, and the three together may name at most 50 distinct recipients. The same address in two fields is one recipient: addresses are compared case insensitively, and a display-name form (Ada Lovelace <ada@example.com>) is compared on the address inside it.

Every recipient counts as one email against the team's daily and monthly send limits and on the bill. A recipient on the team's suppression list is not sent to and is not counted. A message naming more than 50 is refused with 422 before anything is sent:

json
{
  "error": {
    "code": "UNPROCESSABLE_ENTITY",
    "message": "A message can name at most 50 recipients across to, cc and bcc; this one names 63."
  }
}

Errors

StatusCodeMeaning
400BAD_REQUESTThe request is invalid, including any size limit above. The body names the field and the limit.
401UNAUTHORIZEDThe API key is missing or not valid.
403FORBIDDENThe API key is restricted to a domain other than the from address.
413The request body is over 20 MB. It is refused at the edge, with no JSON body.
422UNPROCESSABLE_ENTITYThe message names more than 50 recipients across to, cc and bcc.
429RATE_LIMITEDThe per second rate limit or the team's send limit was reached.
Headers
FieldTypeAbout
Idempotency-Keystring

Pass the optional Idempotency-Key header to make the request safe to retry. The key can be up to 256 characters. The server stores the canonical request body and behaves as follows: - Same key + same request body → returns the original emailId with 200 OK without re-sending. - Same key + different request body → returns 409 Conflict with code: NOT_UNIQUE so you can detect the mismatch. - Same key while another request is still being processed → returns 409 Conflict; retry after a short delay or once the first request completes. Entries expire after 24 hours. Use a unique key per logical send (for example, an order or signup ID).

Request body (JSON)
FieldTypeAbout
tostring or string[]

The visible recipients. Optional when cc or bcc names somebody, which is how a Bcc-only message is sent. At most 50 distinct addresses across to, cc and bcc, and every one of them counts as an email against the team's quota.

fromrequiredstring
subjectstring

Optional when templateId is provided. At most 998 characters.

At most 998 characters.

templateIdstring

ID of a template from the dashboard. A template carries its own subject, preview text and type (transactional or marketing); pass `variables` to fill it. A link that is exactly one variable, such as `{{actionUrl}}`, is only filled with an http(s), mailto or tel address.

variablesmap of string

Values for the template's variables: at most 200, each at most 10000 characters.

replyTostring or string[]
ccstring or string[]

Copied recipients. Counted with to and bcc against the 50 recipient cap and against the team's quota.

bccstring or string[]

Blind copied recipients. Counted with to and cc against the 50 recipient cap and against the team's quota.

textstring

Plain text body. At most 2,000,000 characters.

At most 2,000,000 characters. Can be null.

htmlstring

HTML body. At most 2,000,000 characters.

At most 2,000,000 characters. Can be null.

headersmap of string

Custom headers to included with the emails

attachmentsobject[]

Up to 10 files, each at most 7 MB decoded, and at most 10 MB decoded in total.

attachments[].filenamerequiredstring

At most 255 characters.

attachments[].contentrequiredstring
scheduledAtstring (date-time)
inReplyToIdstring

Can be null.

terminal
curl -X POST "https://app.usenotix.dev/api/v1/emails" \
  -H "Authorization: Bearer $NOTIX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "from": "Acme <receipts@acme.com>"
}'

Responses

200The email was accepted and queued.
200 response fields
FieldTypeAbout
emailIdstring
422The message names more than 50 distinct recipients across to, cc and bcc.
422 response fields
FieldTypeAbout
errorrequiredobject
error.coderequiredstring

One of UNPROCESSABLE_ENTITY.

error.messagerequiredstring

Send a batch of emails

POST/v1/emails/batchSending or full access key

Send up to 100 emails in one request. Every email in the batch carries the same limits as a single send.

ScopeLimit
Request body20 MB, applied at the edge
Emails per request100
Recipients per message50 across to, cc and bcc
attachments total across the batch40 MB, once decoded from base64

The recipient cap is per message, not per request: a batch of 100 messages naming three people each is fine, and one message in it naming 51 refuses the whole batch with 422. Every recipient counts as one email against the team's quota, so that batch reserves and is billed 300.

Errors

StatusCodeMeaning
400BAD_REQUESTThe request is invalid, including any size limit above.
401UNAUTHORIZEDThe API key is missing or not valid.
403FORBIDDENThe API key is restricted to a domain other than a from address.
413The request body is over 20 MB.
422UNPROCESSABLE_ENTITYA message in the batch names more than 50 recipients.
429RATE_LIMITEDThe per second rate limit or the team's send limit was reached.
Headers
FieldTypeAbout
Idempotency-Keystring

Pass the optional Idempotency-Key header to make the request safe to retry. The key can be up to 256 characters. The server stores the canonical request body and behaves as follows: - Same key + same request body → returns the original emailId with 200 OK without re-sending. - Same key + different request body → returns 409 Conflict with code: NOT_UNIQUE so you can detect the mismatch. - Same key while another request is still being processed → returns 409 Conflict; retry after a short delay or once the first request completes. Entries expire after 24 hours. Use a unique key per logical send (for example, an order or signup ID).

Request body (JSON)
FieldTypeAbout
tostring or string[]

The visible recipients. Optional when cc or bcc names somebody, which is how a Bcc-only message is sent. At most 50 distinct addresses across to, cc and bcc, and every one of them counts as an email against the team's quota.

fromrequiredstring
subjectstring

Optional when templateId is provided. At most 998 characters.

At most 998 characters.

templateIdstring

ID of a template from the dashboard. A template carries its own subject, preview text and type (transactional or marketing); pass `variables` to fill it. A link that is exactly one variable, such as `{{actionUrl}}`, is only filled with an http(s), mailto or tel address.

variablesmap of string

Values for the template's variables: at most 200, each at most 10000 characters.

replyTostring or string[]
ccstring or string[]

Copied recipients. Counted with to and bcc against the 50 recipient cap and against the team's quota.

bccstring or string[]

Blind copied recipients. Counted with to and cc against the 50 recipient cap and against the team's quota.

textstring

Plain text body. At most 2,000,000 characters.

At most 2,000,000 characters. Can be null.

htmlstring

HTML body. At most 2,000,000 characters.

At most 2,000,000 characters. Can be null.

headersmap of string

Custom headers to included with the emails

attachmentsobject[]

Up to 10 files, each at most 7 MB decoded, and at most 10 MB decoded in total.

attachments[].filenamerequiredstring

At most 255 characters.

attachments[].contentrequiredstring
scheduledAtstring (date-time)
inReplyToIdstring

Can be null.

terminal
curl -X POST "https://app.usenotix.dev/api/v1/emails/batch" \
  -H "Authorization: Bearer $NOTIX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '[
  {
    "from": "Acme <receipts@acme.com>"
  }
]'

Responses

200List of successfully created email IDs
200 response fields
FieldTypeAbout
datarequiredobject[]
data[].emailIdrequiredstring
422The message names more than 50 distinct recipients across to, cc and bcc.
422 response fields
FieldTypeAbout
errorrequiredobject
error.coderequiredstring

One of UNPROCESSABLE_ENTITY.

error.messagerequiredstring

Get an email

GET/v1/emails/{emailId}Sending or full access key

Retrieve one email with its latest status. A sending access key can read only the emails it sent.

Path parameters
FieldTypeAbout
emailIdrequiredstring
terminal
curl -X GET "https://app.usenotix.dev/api/v1/emails/<emailId>" \
  -H "Authorization: Bearer $NOTIX_API_KEY"

Responses

200Retrieve the email
200 response fields
FieldTypeAbout
idrequiredstring
teamIdrequirednumber
torequiredstring or string[]
replyTostring or string[]
ccstring or string[]
bccstring or string[]
fromrequiredstring
subjectrequiredstring
htmlrequiredstring

Can be null.

textrequiredstring

Can be null.

createdAtrequiredstring
updatedAtrequiredstring
emailEventsrequiredobject[]
emailEvents[].emailIdrequiredstring
emailEvents[].statusrequiredstring

One of SCHEDULED, QUEUED, SENT, DELIVERY_DELAYED, BOUNCED, REJECTED, RENDERING_FAILURE, DELIVERED, OPENED, CLICKED, COMPLAINED, FAILED, CANCELLED, SUPPRESSED.

emailEvents[].createdAtrequiredstring
emailEvents[].dataany

Can be null.

List emails

GET/v1/emailsFull access key

List the team's emails, newest first, filtered and paged by the query parameters.

Query parameters
FieldTypeAbout
pageinteger

Default 1.

limitinteger

Default 50.

startDatestring
endDatestring
domainIdstring
terminal
curl -X GET "https://app.usenotix.dev/api/v1/emails" \
  -H "Authorization: Bearer $NOTIX_API_KEY"

Responses

200Retrieve a list of emails
200 response fields
FieldTypeAbout
datarequiredobject[]
data[].idrequiredstring
data[].torequiredstring or string[]
data[].replyTostring or string[] or any
data[].ccstring or string[] or any
data[].bccstring or string[] or any
data[].fromrequiredstring
data[].subjectrequiredstring
data[].htmlrequiredstring

Can be null.

data[].textrequiredstring

Can be null.

data[].createdAtrequiredstring
data[].updatedAtrequiredstring
data[].latestStatusrequiredstring

One of SCHEDULED, QUEUED, SENT, DELIVERY_DELAYED, BOUNCED, REJECTED, RENDERING_FAILURE, DELIVERED, OPENED, CLICKED, COMPLAINED, FAILED, CANCELLED, SUPPRESSED. Can be null.

data[].scheduledAtrequiredstring (date-time)

Can be null.

data[].domainIdrequirednumber

Can be null.

countrequirednumber

Reschedule an email

PATCH/v1/emails/{emailId}Full access key

Change scheduledAt on an email that has not been sent yet.

Path parameters
FieldTypeAbout
emailIdrequiredstring
Request body (JSON)
FieldTypeAbout
scheduledAtrequiredstring (date-time)
terminal
curl -X PATCH "https://app.usenotix.dev/api/v1/emails/<emailId>" \
  -H "Authorization: Bearer $NOTIX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "scheduledAt": "2026-10-01T09:00:00Z"
}'

Responses

200The email was rescheduled.
200 response fields
FieldTypeAbout
emailIdstring

Cancel a scheduled email

POST/v1/emails/{emailId}/cancelFull access key

Cancel an email that is scheduled and has not been sent yet.

Path parameters
FieldTypeAbout
emailIdrequiredstring
terminal
curl -X POST "https://app.usenotix.dev/api/v1/emails/<emailId>/cancel" \
  -H "Authorization: Bearer $NOTIX_API_KEY"

Responses

200The scheduled email was cancelled.
200 response fields
FieldTypeAbout
emailIdstring