Cakemail
Cakemail API

Email API

Submit and track individual transactional emails. The Email API provides full control over email content, tracking, and delivery. Each email goes through a lifecycle: submitted, queued, delivered, with events for opens, clicks, bounces, and unsubscribes. Includes statistics, activity logs, and tag-based organization.


Submit an email

POST
https://api.cakemail.dev
/v2/emails

Submit an email to be sent.

Request body

Every request requires a sender and a content object. content must include a subject and exactly one of html / text (with an encoding) or a template.

Beyond that, the body comes in one of five shapes. Which one applies is determined by content.type (marketing or transactional) and how you identify the recipient — by raw email, or by contact_id within a list:

content.typeRequired recipient fieldsWhen to use
transactionalemailTo an address, without list management.
transactionalemail + list_idTo an address, with list management.
transactionallist_id + contact_idTo an existing contact in a list.
marketingemail + list_idTo an address; marketing always requires a list_id.
marketinglist_id + contact_idTo an existing contact in a list.

email and contact_id are mutually exclusive: identify the recipient by one or the other, never both. tags, tracking, additional_headers and attachment are optional in every shape.

Email status lifecycle:

  • submitted: Email has been submitted to the API using this endpoint.
  • queued: Email has been queued for delivery.
  • delivered: Email has been successfully delivered.
  • rejected: Email has been rejected by the API. See the reason in metadata for more information.
  • error: Email has encountered an error. See the error in metadata for more information.
  • open: Email has been opened.
  • click: Email has been clicked.
  • bounce: Email has bounced.
  • spam: Email has been marked as spam.
  • unsubscribe: Email has been unsubscribed.
  • global_unsubscribe: Email has been globally unsubscribed (suppressed by user request).

Required scope(s): emailapi:send

Submit an email › query Parameters

account_id
​integer · min: 1

Optional Account ID to be used for the request

Optional Account ID to be used for the request

Submit an email › Request Body

anyOf
At least one variant must match. Multiple variants may match simultaneously.

Decision Table

VariantMatching Criteria
type = object · requires: sender, content, email +1 more
type = object · requires: sender, content, list_id +1 more
type = object · requires: sender, content, email +1 more
type = object · requires: sender, content, list_id +1 more
type = object · requires: sender, content, email
Properties for SubmitMarketingEmail:
​object · required

Sender name and email address

​object · required

Email content (subject, HTML, text, or template)

email
​string · email · required

Recipient's email address

list_id
​integer · min: 1 · required

List ID.

tags
​string[] · minLength: 1 · maxLength: 255 · pattern: ^[a-zA-Z0-9-_]+$

List of tags to apply to the email

​object

Tracking options for opens and clicks

​AdditionalEmailHeader[]

Custom mail headers

​

One or more file attachments

Submit an email › Responses

Successful Response

email
​string · required

Recipient email address

​object · required

Submitted email details

object
​string

Object type

Default: email
submitted
​boolean

Whether the email was submitted

Default: true

Retrieve a submitted email

GET
https://api.cakemail.dev
/v2/emails/{email_id}

Retrieve the details and current status of a previously submitted email, including delivery events, timestamps, and rendered content URL.

Required scope(s): emailapi:read

Retrieve a submitted email › path Parameters

email_id
​string · uuid · required

Retrieve a submitted email › query Parameters

account_id
​integer · min: 1

Optional Account ID to be used for the request

Optional Account ID to be used for the request

Retrieve a submitted email › Responses

Successful Response

email_id
​string · uuid · required

Unique identifier of the email

status
​string · enum · required

Current delivery status of the email

Enum values:
submitted
processing
click
open
bounce
spam
unsubscribe
unsubscribe_reason
email
​string · required

Recipient email address

submitted_time
​integer · required

Submission timestamp

​object · required

Sender information

​object · required

Email content details

​object · required

Tracking configuration

provider
​string

Email delivery provider

unsubscribed
​boolean

Whether recipient unsubscribed

Default: false
global_unsubscribed
​boolean

Whether recipient globally unsubscribed

Default: false
soft_bounced
​boolean

Whether the email soft bounced

Default: false
hard_bounced
​boolean

Whether the email hard bounced

Default: false
reported_as_spam
​boolean

Whether the email was reported as spam

Default: false
open
​integer

Number of times the email was opened

Default: 0
click
​integer

Number of link clicks in the email

Default: 0
list_id
​integer

ID of the contact list

tags
​string[]

Tags associated with the email

​AdditionalEmailHeader[]

Additional email headers

thumbnail_url
​string

URL to the email thumbnail image


Render a submitted email

GET
https://api.cakemail.dev
/v2/emails/{email_id}/render

Render the HTML content of a submitted email. By default returns the final rendered version with merge tags replaced. Use as_submitted to see the original content before rendering.

Required scope(s): emailapi:read

Render a submitted email › path Parameters

email_id
​string · uuid · required

Render a submitted email › query Parameters

as_submitted
​boolean

Render the original submitted content of the email

Render the original submitted content of the email

Default: false
tracking
​boolean

Enable tracking

Enable tracking

Default: false
account_id
​integer · min: 1

Optional Account ID to be used for the request

Optional Account ID to be used for the request

Render a submitted email › Responses

Successful Response

string

List Email Tags

GET
https://api.cakemail.dev
/email-tags

Email Tags are used to group sent emails into a logical group or category. This endpoint will return a list of all the Email Tags that have been created for the account.

To create a tag, specify its name at send time in the tags field of the email object. If the tag does not exist, it will be created automatically.

Use the type parameter to filter tags from the emails or events table, optionally combined with start_time, end_time, and a tags filter for complex queries.

Required scope(s): emailapi:read

List Email Tags › query Parameters

type
​string · enum

Query tags from the emails or events table. Required when using start_time, end_time, or tags filters.

Query tags from the emails or events table. Required when using start_time, end_time, or tags filters.

Enum values:
emails
events
start_time
​integer · min: 1 · max: 2147483647
end_time
​integer · min: 1 · max: 2147483647
account_id
​integer · min: 1

Optional Account ID to be used for the request

Optional Account ID to be used for the request

page
​integer · min: 1
Default: 1
per_page
​integer · min: 1
Default: 50
with_count
​boolean

Include count in the response

Include count in the response

Default: true
name
​string

Tag name to filter by, with optional operator.

Operators:

==: Exact match (default) !=: Not equal ~~: Like (anywhere in the email) !~: Not like (anywhere in the email)

Tag name to filter by, with optional operator.

Operators:

==: Exact match (default) !=: Not equal ~~: Like (anywhere in the email) !~: Not like (anywhere in the email)

Example: tag1~~tag
tags
​string

Recursive Filter Query Language

The filter is a JSON object that represents a recursive query structure. It uses the logical operators and, or, not and is as keys, with the following types of values:

  1. object: A nested filter object that defines additional conditions.

  2. string: A condition expressed as a single string.

  3. array: An array of strings (conditions) or nested filter objects.

  • The and and or operators accept object and array

  • The not operator accepts object and string

  • The is operator accepts object and string

Examples

1. Simple condition with a string

JSONCode
{ "is": "condition1" }

2. Array of strings

JSONCode
{ "or": ["condition1", "condition2"] }

3. Nested filter object

JSONCode
{ "not": { "and": ["condition1", "condition2"] } }

4. Complex recursive query

JSONCode
{ "and": [ { "or": ["condition1", "condition2"] }, { "not": { "and": ["condition3", "condition4"] } } ] }

Recursive Filter Query Language

The filter is a JSON object that represents a recursive query structure. It uses the logical operators and, or, not and is as keys, with the following types of values:

  1. object: A nested filter object that defines additional conditions.

  2. string: A condition expressed as a single string.

  3. array: An array of strings (conditions) or nested filter objects.

  • The and and or operators accept object and array

  • The not operator accepts object and string

  • The is operator accepts object and string

Examples

1. Simple condition with a string

JSONCode
{ "is": "condition1" }

2. Array of strings

JSONCode
{ "or": ["condition1", "condition2"] }

3. Nested filter object

JSONCode
{ "not": { "and": ["condition1", "condition2"] } }

4. Complex recursive query

JSONCode
{ "and": [ { "or": ["condition1", "condition2"] }, { "not": { "and": ["condition3", "condition4"] } } ] }

List Email Tags › Responses

Successful Response

​object · required

Pagination details

data
​string[] · required

List of email tags


Show Email API activity logs

GET
https://api.cakemail.dev
/v2/logs/emails

List individual Email API activity events (deliveries, opens, clicks, bounces, etc.). Filterable by time range, log type, tags, and providers.

Required scope(s): logs:read

Show Email API activity logs › query Parameters

log_type
​string · enum

An enumeration.

Enum values:
all
submitted
rejected
error
queued
delivered
open
click
Default: all
email_id
​string · uuid
iso_time
​boolean

Convert timestamps to human readable ISO format

Convert timestamps to human readable ISO format

Default: false
account_id
​integer · min: 1

Optional Account ID to be used for the request

Optional Account ID to be used for the request

page
​integer · min: 1
Default: 1
per_page
​integer · min: 1 · max: 100
Default: 50
start_time
​integer · min: 1 · max: 2147483647

Start time for the report, defaults to 7 days ago.

Start time for the report, defaults to 7 days ago.

end_time
​integer · min: 1 · max: 2147483647

End time for the report, defaults to the current time.

End time for the report, defaults to the current time.

tags
​string

Recursive Filter Query Language

The filter is a JSON object that represents a recursive query structure. It uses the logical operators and, or, not and is as keys, with the following types of values:

  1. object: A nested filter object that defines additional conditions.

  2. string: A condition expressed as a single string.

  3. array: An array of strings (conditions) or nested filter objects.

  • The and and or operators accept object and array

  • The not operator accepts object and string

  • The is operator accepts object and string

Examples

1. Simple condition with a string

JSONCode
{ "is": "condition1" }

2. Array of strings

JSONCode
{ "or": ["condition1", "condition2"] }

3. Nested filter object

JSONCode
{ "not": { "and": ["condition1", "condition2"] } }

4. Complex recursive query

JSONCode
{ "and": [ { "or": ["condition1", "condition2"] }, { "not": { "and": ["condition3", "condition4"] } } ] }

Recursive Filter Query Language

The filter is a JSON object that represents a recursive query structure. It uses the logical operators and, or, not and is as keys, with the following types of values:

  1. object: A nested filter object that defines additional conditions.

  2. string: A condition expressed as a single string.

  3. array: An array of strings (conditions) or nested filter objects.

  • The and and or operators accept object and array

  • The not operator accepts object and string

  • The is operator accepts object and string

Examples

1. Simple condition with a string

JSONCode
{ "is": "condition1" }

2. Array of strings

JSONCode
{ "or": ["condition1", "condition2"] }

3. Nested filter object

JSONCode
{ "not": { "and": ["condition1", "condition2"] } }

4. Complex recursive query

JSONCode
{ "and": [ { "or": ["condition1", "condition2"] }, { "not": { "and": ["condition3", "condition4"] } } ] }
providers
​string

Recursive Filter Query Language

The filter is a JSON object that represents a recursive query structure. It uses the logical operators and, or, not and is as keys, with the following types of values:

  1. object: A nested filter object that defines additional conditions.

  2. string: A condition expressed as a single string.

  3. array: An array of strings (conditions) or nested filter objects.

  • The and and or operators accept object and array

  • The not operator accepts object and string

  • The is operator accepts object and string

Examples

1. Simple condition with a string

JSONCode
{ "is": "condition1" }

2. Array of strings

JSONCode
{ "or": ["condition1", "condition2"] }

3. Nested filter object

JSONCode
{ "not": { "and": ["condition1", "condition2"] } }

4. Complex recursive query

JSONCode
{ "and": [ { "or": ["condition1", "condition2"] }, { "not": { "and": ["condition3", "condition4"] } } ] }

Recursive Filter Query Language

The filter is a JSON object that represents a recursive query structure. It uses the logical operators and, or, not and is as keys, with the following types of values:

  1. object: A nested filter object that defines additional conditions.

  2. string: A condition expressed as a single string.

  3. array: An array of strings (conditions) or nested filter objects.

  • The and and or operators accept object and array

  • The not operator accepts object and string

  • The is operator accepts object and string

Examples

1. Simple condition with a string

JSONCode
{ "is": "condition1" }

2. Array of strings

JSONCode
{ "or": ["condition1", "condition2"] }

3. Nested filter object

JSONCode
{ "not": { "and": ["condition1", "condition2"] } }

4. Complex recursive query

JSONCode
{ "and": [ { "or": ["condition1", "condition2"] }, { "not": { "and": ["condition3", "condition4"] } } ] }
sort
​string

Sort term and direction, using syntax [-|+]term.

Valid terms:

  • id
  • time
  • submitted_time
  • type
  • provider

Sort term and direction, using syntax [-|+]term.

Valid terms:

  • id
  • time
  • submitted_time
  • type
  • provider
Default: -time

Show Email API activity logs › Responses

Successful Response

​object · required

Pagination details

​object · required

Applied filter parameters

​EmailAPILogResponse[] · required

List of Email API log entries


Show Email API activity summary

GET
https://api.cakemail.dev
/logs/emails-summary

Get a per-email summary of Email API activity, showing each email's latest status, engagement, and delivery details. Filterable by email address, status, engagement level, tags, and providers.

Required scope(s): logs:read

Show Email API activity summary › query Parameters

email_id
​string · uuid
engagement
​string · enum

An enumeration.

Enum values:
click
open
none
open_not_click
status
​string · enum

An enumeration.

Enum values:
submitted
delivered
queued
rejected
error
bounced
spam
unsubscribed
iso_time
​boolean

Convert timestamps to human readable ISO format

Convert timestamps to human readable ISO format

Default: false
account_id
​integer · min: 1

Optional Account ID to be used for the request

Optional Account ID to be used for the request

page
​integer · min: 1
Default: 1
per_page
​integer · min: 1 · max: 100
Default: 50
start_time
​integer · min: 1 · max: 2147483647

Start time for the report, defaults to 7 days ago.

Start time for the report, defaults to 7 days ago.

end_time
​integer · min: 1 · max: 2147483647

End time for the report, defaults to the current time.

End time for the report, defaults to the current time.

tags
​string

Recursive Filter Query Language

The filter is a JSON object that represents a recursive query structure. It uses the logical operators and, or, not and is as keys, with the following types of values:

  1. object: A nested filter object that defines additional conditions.

  2. string: A condition expressed as a single string.

  3. array: An array of strings (conditions) or nested filter objects.

  • The and and or operators accept object and array

  • The not operator accepts object and string

  • The is operator accepts object and string

Examples

1. Simple condition with a string

JSONCode
{ "is": "condition1" }

2. Array of strings

JSONCode
{ "or": ["condition1", "condition2"] }

3. Nested filter object

JSONCode
{ "not": { "and": ["condition1", "condition2"] } }

4. Complex recursive query

JSONCode
{ "and": [ { "or": ["condition1", "condition2"] }, { "not": { "and": ["condition3", "condition4"] } } ] }

Recursive Filter Query Language

The filter is a JSON object that represents a recursive query structure. It uses the logical operators and, or, not and is as keys, with the following types of values:

  1. object: A nested filter object that defines additional conditions.

  2. string: A condition expressed as a single string.

  3. array: An array of strings (conditions) or nested filter objects.

  • The and and or operators accept object and array

  • The not operator accepts object and string

  • The is operator accepts object and string

Examples

1. Simple condition with a string

JSONCode
{ "is": "condition1" }

2. Array of strings

JSONCode
{ "or": ["condition1", "condition2"] }

3. Nested filter object

JSONCode
{ "not": { "and": ["condition1", "condition2"] } }

4. Complex recursive query

JSONCode
{ "and": [ { "or": ["condition1", "condition2"] }, { "not": { "and": ["condition3", "condition4"] } } ] }
providers
​string

Recursive Filter Query Language

The filter is a JSON object that represents a recursive query structure. It uses the logical operators and, or, not and is as keys, with the following types of values:

  1. object: A nested filter object that defines additional conditions.

  2. string: A condition expressed as a single string.

  3. array: An array of strings (conditions) or nested filter objects.

  • The and and or operators accept object and array

  • The not operator accepts object and string

  • The is operator accepts object and string

Examples

1. Simple condition with a string

JSONCode
{ "is": "condition1" }

2. Array of strings

JSONCode
{ "or": ["condition1", "condition2"] }

3. Nested filter object

JSONCode
{ "not": { "and": ["condition1", "condition2"] } }

4. Complex recursive query

JSONCode
{ "and": [ { "or": ["condition1", "condition2"] }, { "not": { "and": ["condition3", "condition4"] } } ] }

Recursive Filter Query Language

The filter is a JSON object that represents a recursive query structure. It uses the logical operators and, or, not and is as keys, with the following types of values:

  1. object: A nested filter object that defines additional conditions.

  2. string: A condition expressed as a single string.

  3. array: An array of strings (conditions) or nested filter objects.

  • The and and or operators accept object and array

  • The not operator accepts object and string

  • The is operator accepts object and string

Examples

1. Simple condition with a string

JSONCode
{ "is": "condition1" }

2. Array of strings

JSONCode
{ "or": ["condition1", "condition2"] }

3. Nested filter object

JSONCode
{ "not": { "and": ["condition1", "condition2"] } }

4. Complex recursive query

JSONCode
{ "and": [ { "or": ["condition1", "condition2"] }, { "not": { "and": ["condition3", "condition4"] } } ] }
sort
​string

Sort term and direction, using syntax [-|+]term.

Valid terms:

  • submitted_time

Sort term and direction, using syntax [-|+]term.

Valid terms:

  • submitted_time
Default: -submitted_time
email
​string

Email address to filter by, with optional operator.

Operators:

==: Exact match (default) !=: Not equal ~~: Like (anywhere in the email) !~: Not like (anywhere in the email)

Email address to filter by, with optional operator.

Operators:

==: Exact match (default) !=: Not equal ~~: Like (anywhere in the email) !~: Not like (anywhere in the email)

Example: localpart@domain.com

Show Email API activity summary › Responses

Successful Response

​object · required

Pagination details

​object · required

Applied filter parameters

​EmailAPISummaryItem[] · required

List of email summaries


Show Email API statistics

GET
https://api.cakemail.dev
/v2/reports/emails

Generate email statistics for the Email API.

Statistics are aggregated with a minimum granularity of 5 minutes. As a result, the returned intervals may extend beyond the requested time range. Intervals are always whole, except for the last interval if the requested end time is the current time.

Required scope(s): reports:read

Show Email API statistics › query Parameters

interval
​IntervalEnum · enum

An enumeration.

Enum values:
5m
15m
30m
1h
1d
iso_time
​boolean

Convert timestamps to human readable ISO format

Convert timestamps to human readable ISO format

account_id
​integer · min: 1

Optional Account ID to be used for the request

Optional Account ID to be used for the request

start_time
​integer · min: 1 · max: 2147483647

Start time for the report.

Start time for the report.

end_time
​integer · min: 1 · max: 2147483647

End time for the report.

End time for the report.

providers
​string

Recursive Filter Query Language

The filter is a JSON object that represents a recursive query structure. It uses the logical operators and, or, not and is as keys, with the following types of values:

  1. object: A nested filter object that defines additional conditions.

  2. string: A condition expressed as a single string.

  3. array: An array of strings (conditions) or nested filter objects.

  • The and and or operators accept object and array

  • The not operator accepts object and string

  • The is operator accepts object and string

Examples

1. Simple condition with a string

JSONCode
{ "is": "condition1" }

2. Array of strings

JSONCode
{ "or": ["condition1", "condition2"] }

3. Nested filter object

JSONCode
{ "not": { "and": ["condition1", "condition2"] } }

4. Complex recursive query

JSONCode
{ "and": [ { "or": ["condition1", "condition2"] }, { "not": { "and": ["condition3", "condition4"] } } ] }

Recursive Filter Query Language

The filter is a JSON object that represents a recursive query structure. It uses the logical operators and, or, not and is as keys, with the following types of values:

  1. object: A nested filter object that defines additional conditions.

  2. string: A condition expressed as a single string.

  3. array: An array of strings (conditions) or nested filter objects.

  • The and and or operators accept object and array

  • The not operator accepts object and string

  • The is operator accepts object and string

Examples

1. Simple condition with a string

JSONCode
{ "is": "condition1" }

2. Array of strings

JSONCode
{ "or": ["condition1", "condition2"] }

3. Nested filter object

JSONCode
{ "not": { "and": ["condition1", "condition2"] } }

4. Complex recursive query

JSONCode
{ "and": [ { "or": ["condition1", "condition2"] }, { "not": { "and": ["condition3", "condition4"] } } ] }
tags
​string

Recursive Filter Query Language

The filter is a JSON object that represents a recursive query structure. It uses the logical operators and, or, not and is as keys, with the following types of values:

  1. object: A nested filter object that defines additional conditions.

  2. string: A condition expressed as a single string.

  3. array: An array of strings (conditions) or nested filter objects.

  • The and and or operators accept object and array

  • The not operator accepts object and string

  • The is operator accepts object and string

Examples

1. Simple condition with a string

JSONCode
{ "is": "condition1" }

2. Array of strings

JSONCode
{ "or": ["condition1", "condition2"] }

3. Nested filter object

JSONCode
{ "not": { "and": ["condition1", "condition2"] } }

4. Complex recursive query

JSONCode
{ "and": [ { "or": ["condition1", "condition2"] }, { "not": { "and": ["condition3", "condition4"] } } ] }

Recursive Filter Query Language

The filter is a JSON object that represents a recursive query structure. It uses the logical operators and, or, not and is as keys, with the following types of values:

  1. object: A nested filter object that defines additional conditions.

  2. string: A condition expressed as a single string.

  3. array: An array of strings (conditions) or nested filter objects.

  • The and and or operators accept object and array

  • The not operator accepts object and string

  • The is operator accepts object and string

Examples

1. Simple condition with a string

JSONCode
{ "is": "condition1" }

2. Array of strings

JSONCode
{ "or": ["condition1", "condition2"] }

3. Nested filter object

JSONCode
{ "not": { "and": ["condition1", "condition2"] } }

4. Complex recursive query

JSONCode
{ "and": [ { "or": ["condition1", "condition2"] }, { "not": { "and": ["condition3", "condition4"] } } ] }

Show Email API statistics › Responses

Successful Response

​object · required

Applied filter parameters

​EmailAPIStatsIntervalResponse[] · required

Statistics per interval