Download OpenAPI specification:Download
SendFox's REST API lets you manage contacts, campaigns, lists, automations, and forms programmatically. It uses OAuth 2.0 for authentication.
Compatible with AI agents (Claude, ChatGPT, etc.) via the OpenAPI spec. Available at GET /openapi.yaml.
Create a personal access token at https://sendfox.com/account/oauth. Once created, use it in the Authorization header:
Authorization: Bearer {TOKEN}
For integrations that require user authentication, create an OAuth 2.0 client at https://sendfox.com/account/oauth
API requests are limited to 60 requests per minute per authenticated user. Rate limit status is returned in response headers:
X-RateLimit-Limit: Maximum requests per minuteX-RateLimit-Remaining: Remaining requests in current windowRetry-After: Seconds until rate limit resets (only on 429 responses)All error responses use standard HTTP status codes and Laravel's default error format:
message: Human-readable error descriptionerrors: Field-level validation errors (on 422 responses)API access requires a Lifetime or Empire plan. Free users cannot use the API.
Accounts restricted by SendFox cannot use authenticated API endpoints. These requests return 403 Forbidden with the error code account_restricted and a link to the account status page.
Returns a paginated list of contacts (100 per page by default, up to 1000 via per_page).
Supports engagement filtering through filter[...] query parameters, so you can answer
questions like "who last opened over a year ago" without paging the whole account. All
filter conditions are AND-ed. Pass count_only=true to get just the number of matches —
the cheapest way to size an audience before acting on it.
| query | string Search query for filtering contacts |
| unsubscribed | boolean Filter unsubscribed contacts |
string Filter by specific email | |
| per_page | integer [ 1 .. 1000 ] Default: 100 Contacts per page |
| count_only | boolean Return only the number of matching contacts, with no contact records |
| filter[status] | string Enum: "active" "engaged" "inactive" "new" "unconfirmed" "unsubscribed" "bounced" "invalid" Engagement status |
| filter[last_opened_after] | string <date-time> Contacts whose most recent open is on or after this date |
| filter[last_opened_before] | string <date-time> Contacts whose most recent open is before this date. Excludes contacts who never opened — use filter[never_opened] for those. |
| filter[last_clicked_after] | string <date-time> Contacts whose most recent click is on or after this date |
| filter[last_clicked_before] | string <date-time> Contacts whose most recent click is before this date |
| filter[last_sent_after] | string <date-time> Contacts last sent to on or after this date |
| filter[last_sent_before] | string <date-time> Contacts last sent to before this date |
| filter[created_after] | string <date-time> Contacts created on or after this date |
| filter[created_before] | string <date-time> Contacts created before this date |
| filter[never_opened] | boolean Only contacts who have never opened an email |
| filter[never_clicked] | boolean Only contacts who have never clicked a link |
| filter[never_sent] | boolean Only contacts who have never been sent an email |
| filter[in_list_ids] | Array of integers Only contacts in any of these lists |
| filter[not_in_list_ids] | Array of integers Exclude contacts in any of these lists |
| filter[tag_ids] | Array of integers Only contacts carrying any of these tags |
| filter[not_tag_ids] | Array of integers Exclude contacts carrying any of these tags |
{- "count": 0,
- "filter": "string"
}| email required | string <email> |
| first_name | string |
| last_name | string |
| ip_address | string |
| lists | Array of integers Array of list IDs to add the contact to |
Array of objects |
{- "first_name": "string",
- "last_name": "string",
- "ip_address": "string",
- "lists": [
- 0
], - "contact_fields": [
- {
- "name": "string",
- "value": "string"
}
]
}{- "id": 0,
- "first_name": "string",
- "last_name": "string",
- "ip_address": "string",
- "unsubscribed_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}{- "id": 0,
- "first_name": "string",
- "last_name": "string",
- "ip_address": "string",
- "unsubscribed_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}Update contact details including name, list memberships, and custom fields
| id required | integer |
| first_name | string |
| last_name | string |
| lists | Array of integers Array of list IDs (replaces all current list memberships) |
Array of objects |
{- "first_name": "string",
- "last_name": "string",
- "lists": [
- 0
], - "contact_fields": [
- {
- "name": "string",
- "value": "string"
}
]
}{- "id": 0,
- "first_name": "string",
- "last_name": "string",
- "ip_address": "string",
- "unsubscribed_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}Returns paginated email deliverables and contact-level engagement summary
| id required | integer |
{- "contact": {
- "last_sent_at": "2019-08-24T14:15:22Z",
- "last_opened_at": "2019-08-24T14:15:22Z",
- "last_clicked_at": "2019-08-24T14:15:22Z",
- "unsubscribed_at": "2019-08-24T14:15:22Z",
- "bounced_at": "2019-08-24T14:15:22Z"
}, - "deliverables": {
- "data": [
- {
- "campaign_title": "string",
- "campaign_id": 0,
- "sent_at": "2019-08-24T14:15:22Z",
- "opened_at": "2019-08-24T14:15:22Z",
- "clicked_at": "2019-08-24T14:15:22Z",
- "bounced_at": "2019-08-24T14:15:22Z",
- "unsubscribed_at": "2019-08-24T14:15:22Z",
- "spam_at": "2019-08-24T14:15:22Z"
}
]
}
}Import up to 1,000 contacts in a single request. Creates new contacts or updates existing ones.
required | Array of objects <= 1000 items |
{- "contacts": [
]
}{- "created": 0,
- "updated": 0
}Queues one action against every contact the filter matches, applied in chunks in the background. Returns immediately with an id to poll.
Run with dry_run: true first. A dry run reports how many contacts match and changes
nothing — it is the only way to catch a filter that matches more than intended, and a bulk
write is not undoable. An empty filter (which would match the whole account) is rejected
unless it is a dry run.
Per-campaign conditions (opened_campaign_id, not_opened_campaign_id,
clicked_campaign_id) are available here but not on GET /contacts, because they are
resolved in the background rather than inside a request.
Bulk delete and bulk unsubscribe are deliberately not offered.
| action required | string Enum: "apply_tag" "remove_tag" "add_to_list" "remove_from_list" |
| target_id required | integer The tag id (apply_tag/remove_tag) or list id (add_to_list/remove_from_list) |
| dry_run | boolean Default: false When true, only count the matches — nothing is modified |
object (ContactFilter) An engagement filter over the account's contacts. Every condition is AND-ed. Omitting the object entirely means "all contacts". |
{- "action": "apply_tag",
- "target_id": 0,
- "dry_run": false,
- "filter": {
- "status": "active",
- "last_opened_after": "2019-08-24T14:15:22Z",
- "last_opened_before": "2019-08-24T14:15:22Z",
- "last_clicked_after": "2019-08-24T14:15:22Z",
- "last_clicked_before": "2019-08-24T14:15:22Z",
- "last_sent_after": "2019-08-24T14:15:22Z",
- "last_sent_before": "2019-08-24T14:15:22Z",
- "created_after": "2019-08-24T14:15:22Z",
- "created_before": "2019-08-24T14:15:22Z",
- "never_opened": true,
- "never_clicked": true,
- "never_sent": true,
- "in_list_ids": [
- 0
], - "not_in_list_ids": [
- 0
], - "tag_ids": [
- 0
], - "not_tag_ids": [
- 0
], - "opened_campaign_id": 0,
- "not_opened_campaign_id": 0,
- "clicked_campaign_id": 0
}
}{- "id": 0,
- "status": "pending",
- "action": "apply_tag",
- "target_id": 0,
- "dry_run": true,
- "filter": "string",
- "matched_count": 0,
- "processed_count": 0,
- "error": "string",
- "started_at": "2019-08-24T14:15:22Z",
- "completed_at": "2019-08-24T14:15:22Z"
}For a dry run, matched_count is the answer and nothing was modified. A run whose match set exceeds the per-request ceiling fails without applying anything.
| id required | integer |
{- "id": 0,
- "status": "pending",
- "action": "apply_tag",
- "target_id": 0,
- "dry_run": true,
- "filter": "string",
- "matched_count": 0,
- "processed_count": 0,
- "error": "string",
- "started_at": "2019-08-24T14:15:22Z",
- "completed_at": "2019-08-24T14:15:22Z"
}| query | string Search query for filtering contacts |
{- "data": [
- {
- "id": 0,
- "first_name": "string",
- "last_name": "string",
- "ip_address": "string",
- "unsubscribed_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "current_page": 0,
- "total": 0,
- "per_page": 0
}| email required | string <email> |
{- "email": "[email protected]"
}{- "id": 0,
- "first_name": "string",
- "last_name": "string",
- "ip_address": "string",
- "unsubscribed_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}{- "data": [
- {
- "id": 0,
- "title": "string",
- "subject": "string",
- "preview_text": "string",
- "html": "string",
- "from_name": "string",
- "scheduled_at": "2019-08-24T14:15:22Z",
- "sent_at": "2019-08-24T14:15:22Z",
- "timezone": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "current_page": 0,
- "total": 0,
- "per_page": 0
}Creates a campaign as a draft. To send it, use the send endpoint or provide scheduled_at. Subject lines cannot start with "RE:" or "FWD:". At least one list is required if scheduled_at is provided.
| title required | string <= 191 characters |
| subject required | string <= 191 characters |
| preview_text | string or null <= 191 characters Inbox preview snippet shown beneath the subject line. Optional. |
| html required | string <= 1000000 characters Email body HTML content |
| from_name required | string <= 191 characters |
| from_email required | string <email> <= 191 characters |
| scheduled_at | string <date-time> Schedule send time (omit for draft). Must include at least one list. |
| lists | Array of integers Array of list IDs to send to |
| excluded_lists | Array of integers List IDs whose contacts should be excluded from the send. Exclusion wins over inclusion. |
| to_contact_tags | Array of integers Tag IDs whose contacts should receive the campaign. Can be combined with lists. |
| excluded_contact_tags | Array of integers Tag IDs whose contacts should be excluded from the send. Exclusion wins over inclusion. |
{- "title": "string",
- "subject": "string",
- "preview_text": "string",
- "html": "string",
- "from_name": "string",
- "scheduled_at": "2019-08-24T14:15:22Z",
- "lists": [
- 0
], - "excluded_lists": [
- 0
], - "to_contact_tags": [
- 0
], - "excluded_contact_tags": [
- 0
]
}{- "id": 0,
- "title": "string",
- "subject": "string",
- "preview_text": "string",
- "html": "string",
- "from_name": "string",
- "scheduled_at": "2019-08-24T14:15:22Z",
- "sent_at": "2019-08-24T14:15:22Z",
- "timezone": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}{- "id": 0,
- "title": "string",
- "subject": "string",
- "preview_text": "string",
- "html": "string",
- "from_name": "string",
- "scheduled_at": "2019-08-24T14:15:22Z",
- "sent_at": "2019-08-24T14:15:22Z",
- "timezone": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}Only draft campaigns (not yet sent) can be updated. All fields are optional.
| id required | integer |
| title | string <= 191 characters |
| subject | string <= 191 characters |
| preview_text | string or null <= 191 characters Inbox preview snippet. Pass null to clear. |
| html | string <= 1000000 characters |
| from_name | string <= 191 characters |
| from_email | string <email> <= 191 characters |
| scheduled_at | string or null <date-time> Set to null to unschedule, or a datetime to schedule |
| lists | Array of integers Replaces all list assignments |
| excluded_lists | Array of integers Replaces the excluded lists (contacts in these lists are removed from the send). |
| to_contact_tags | Array of integers Replaces the included tag audience (contacts carrying these tags receive the campaign). |
| excluded_contact_tags | Array of integers Replaces the excluded tag audience (contacts carrying these tags are removed from the send). |
{- "title": "string",
- "subject": "string",
- "preview_text": "string",
- "html": "string",
- "from_name": "string",
- "scheduled_at": "2019-08-24T14:15:22Z",
- "lists": [
- 0
], - "excluded_lists": [
- 0
], - "to_contact_tags": [
- 0
], - "excluded_contact_tags": [
- 0
]
}{- "id": 0,
- "title": "string",
- "subject": "string",
- "preview_text": "string",
- "html": "string",
- "from_name": "string",
- "scheduled_at": "2019-08-24T14:15:22Z",
- "sent_at": "2019-08-24T14:15:22Z",
- "timezone": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}Schedules a draft campaign for immediate sending. The campaign must:
All existing abuse prevention applies automatically: content approval workflow, sending throttles, spam detection, and bounce rate monitoring.
| id required | integer |
{- "id": 0,
- "title": "string",
- "subject": "string",
- "preview_text": "string",
- "html": "string",
- "from_name": "string",
- "scheduled_at": "2019-08-24T14:15:22Z",
- "sent_at": "2019-08-24T14:15:22Z",
- "timezone": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}Returns sent count and open/click/bounce/unsubscribe/spam counts and rates, all read from stored counters.
Pass include_link_stats=true to also get link_stats — the campaign's links ranked by click count. That part is opt-in because it counts rows in email_link_clicks once per link rather than reading a counter, so leaving it off keeps this endpoint as cheap as it has always been.
| id required | integer |
| include_link_stats | boolean Default: false When true, include the link_stats breakdown in the response |
| link_limit | integer [ 1 .. 100 ] Default: 50 How many links to return in link_stats, most-clicked first. Ignored unless include_link_stats is true. |
{- "link_stats": [
- {
- "url": "string",
- "clicks": 0
}
], - "sent_count": 0,
- "unique_open_count": 0,
- "unique_click_count": 0,
- "unsubscribe_count": 0,
- "bounce_count": 0,
- "spam_count": 0,
- "open_rate": 0,
- "click_rate": 0,
- "unsubscribe_rate": 0,
- "bounce_rate": 0,
- "spam_rate": 0
}Returns the contacts in one of a sent campaign's engagement groups. non_openers covers contacts the campaign actually sent to who did not open it — queued and cancelled deliverables are excluded, since they never had the chance.
| id required | integer |
| type required | string Enum: "openers" "clickers" "non_openers" "bounced" "unsubscribed" Which engagement group to list |
| per_page | integer [ 1 .. 1000 ] Default: 100 Records per page |
{- "data": [
- {
- "id": 0,
- "contact_id": 0,
- "email": "string",
- "first_name": "string",
- "last_name": "string",
- "sent_at": "2019-08-24T14:15:22Z",
- "opened_at": "2019-08-24T14:15:22Z",
- "clicked_at": "2019-08-24T14:15:22Z",
- "bounced_at": "2019-08-24T14:15:22Z",
- "unsubscribed_at": "2019-08-24T14:15:22Z"
}
], - "current_page": 0,
- "total": 0,
- "per_page": 0
}Creates a new draft with the original's content, sender, and exclusions, aimed at the chosen slice of the original audience. Omit scheduled_at to leave it as a draft. The source campaign's lists are deliberately not carried over — the engagement segment is the audience.
| id required | integer |
| audience required | string Enum: "non_openers" "openers" "clickers" |
| subject | string <= 191 characters Optional new subject line; defaults to the original's |
| title | string <= 191 characters Optional internal name; defaults to "Resend: |
| scheduled_at | string <date-time> Optional send time; omit to leave the resend as a draft |
{- "audience": "non_openers",
- "subject": "string",
- "title": "string",
- "scheduled_at": "2019-08-24T14:15:22Z"
}{- "id": 0,
- "title": "string",
- "subject": "string",
- "preview_text": "string",
- "html": "string",
- "from_name": "string",
- "scheduled_at": "2019-08-24T14:15:22Z",
- "sent_at": "2019-08-24T14:15:22Z",
- "timezone": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}| query | string Search query for filtering lists |
{- "data": [
- {
- "id": 0,
- "name": "string",
- "user_id": 0,
- "average_email_open_percent": 0,
- "average_email_click_percent": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "current_page": 0,
- "total": 0,
- "per_page": 0
}| name required | string |
{- "name": "string"
}{- "id": 0,
- "name": "string",
- "user_id": 0,
- "average_email_open_percent": 0,
- "average_email_click_percent": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}Returns list details including average open and click rates
| id required | integer |
{- "id": 0,
- "name": "string",
- "user_id": 0,
- "average_email_open_percent": 0,
- "average_email_click_percent": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}| id required | integer |
| name required | string <= 191 characters |
{- "name": "string"
}{- "id": 0,
- "name": "string",
- "user_id": 0,
- "average_email_open_percent": 0,
- "average_email_click_percent": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}| list_id required | integer |
| query | string Search query for filtering contacts |
{- "data": [
- {
- "id": 0,
- "first_name": "string",
- "last_name": "string",
- "ip_address": "string",
- "unsubscribed_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "current_page": 0,
- "total": 0,
- "per_page": 0
}Adds an existing contact to a list. If the contact is already in the list, no duplicate is created.
| list_id required | integer |
| contact_id required | integer ID of the contact to add |
{- "contact_id": 0
}{- "id": 0,
- "first_name": "string",
- "last_name": "string",
- "ip_address": "string",
- "unsubscribed_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}| list_id required | integer |
| contact_id required | integer |
{- "id": 0,
- "first_name": "string",
- "last_name": "string",
- "ip_address": "string",
- "unsubscribed_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}| query | string Search query for filtering forms |
{- "data": [
- {
- "id": 0,
- "title": "string",
- "landing_page_id": 0,
- "redirect_url": "string",
- "gdpr_required": true,
- "url": "string",
- "lists": [
- {
- "id": 0,
- "name": "string",
- "user_id": 0,
- "average_email_open_percent": 0,
- "average_email_click_percent": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "current_page": 0,
- "total": 0,
- "per_page": 0
}Creates a subscription form linked to one or more lists. Free users are limited to 1 form.
| title required | string <= 191 characters |
| lists required | Array of integers Array of list IDs to attach |
| redirect_url | string or null <uri> URL to redirect to after subscription |
| gdpr_required | boolean Whether GDPR consent checkbox is required |
{- "title": "string",
- "lists": [
- 0
], - "gdpr_required": true
}{- "id": 0,
- "title": "string",
- "landing_page_id": 0,
- "redirect_url": "string",
- "gdpr_required": true,
- "url": "string",
- "lists": [
- {
- "id": 0,
- "name": "string",
- "user_id": 0,
- "average_email_open_percent": 0,
- "average_email_click_percent": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}{- "id": 0,
- "title": "string",
- "landing_page_id": 0,
- "redirect_url": "string",
- "gdpr_required": true,
- "url": "string",
- "lists": [
- {
- "id": 0,
- "name": "string",
- "user_id": 0,
- "average_email_open_percent": 0,
- "average_email_click_percent": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}| id required | integer |
| title | string <= 191 characters |
| lists | Array of integers Replaces all list assignments |
| redirect_url | string or null <uri> |
| gdpr_required | boolean |
{- "title": "string",
- "lists": [
- 0
], - "gdpr_required": true
}{- "id": 0,
- "title": "string",
- "landing_page_id": 0,
- "redirect_url": "string",
- "gdpr_required": true,
- "url": "string",
- "lists": [
- {
- "id": 0,
- "name": "string",
- "user_id": 0,
- "average_email_open_percent": 0,
- "average_email_click_percent": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}{- "data": [
- {
- "id": 0,
- "user_id": 0,
- "title": "string",
- "active": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "automation_triggers": [
- {
- "id": 0,
- "automation_id": 0,
- "type": "apply_list",
- "list_id": 0,
- "campaign_id": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "automation_items": [
- {
- "id": 0,
- "automation_id": 0,
- "campaign_id": 0,
- "delay_hours": 0,
- "send_order": 0,
- "campaign": {
- "id": 0,
- "title": "string",
- "subject": "string",
- "preview_text": "string",
- "html": "string",
- "from_name": "string",
- "scheduled_at": "2019-08-24T14:15:22Z",
- "sent_at": "2019-08-24T14:15:22Z",
- "timezone": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}
], - "current_page": 0,
- "total": 0,
- "per_page": 0
}| title required | string |
| trigger_type | string Enum: "apply_list" "open_campaign" "click_campaign" |
| trigger_list_id | integer Required when trigger_type is apply_list |
| trigger_campaign_id | integer Required when trigger_type is open_campaign or click_campaign |
| active | boolean |
{- "title": "string",
- "trigger_type": "apply_list",
- "trigger_list_id": 0,
- "trigger_campaign_id": 0,
- "active": true
}{- "id": 0,
- "user_id": 0,
- "title": "string",
- "active": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "automation_triggers": [
- {
- "id": 0,
- "automation_id": 0,
- "type": "apply_list",
- "list_id": 0,
- "campaign_id": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "automation_items": [
- {
- "id": 0,
- "automation_id": 0,
- "campaign_id": 0,
- "delay_hours": 0,
- "send_order": 0,
- "campaign": {
- "id": 0,
- "title": "string",
- "subject": "string",
- "preview_text": "string",
- "html": "string",
- "from_name": "string",
- "scheduled_at": "2019-08-24T14:15:22Z",
- "sent_at": "2019-08-24T14:15:22Z",
- "timezone": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}Returns automation with triggers, items, and campaign stats
| id required | integer |
{- "id": 0,
- "user_id": 0,
- "title": "string",
- "active": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "automation_triggers": [
- {
- "id": 0,
- "automation_id": 0,
- "type": "apply_list",
- "list_id": 0,
- "campaign_id": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "automation_items": [
- {
- "id": 0,
- "automation_id": 0,
- "campaign_id": 0,
- "delay_hours": 0,
- "send_order": 0,
- "campaign": {
- "id": 0,
- "title": "string",
- "subject": "string",
- "preview_text": "string",
- "html": "string",
- "from_name": "string",
- "scheduled_at": "2019-08-24T14:15:22Z",
- "sent_at": "2019-08-24T14:15:22Z",
- "timezone": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}Update title, trigger, or active status. Activating reschedules stale deliverables.
| id required | integer |
| title | string |
| active | boolean |
| trigger_type | string Enum: "apply_list" "open_campaign" "click_campaign" |
| trigger_list_id | integer |
| trigger_campaign_id | integer |
{- "title": "string",
- "active": true,
- "trigger_type": "apply_list",
- "trigger_list_id": 0,
- "trigger_campaign_id": 0
}{- "id": 0,
- "user_id": 0,
- "title": "string",
- "active": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "automation_triggers": [
- {
- "id": 0,
- "automation_id": 0,
- "type": "apply_list",
- "list_id": 0,
- "campaign_id": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "automation_items": [
- {
- "id": 0,
- "automation_id": 0,
- "campaign_id": 0,
- "delay_hours": 0,
- "send_order": 0,
- "campaign": {
- "id": 0,
- "title": "string",
- "subject": "string",
- "preview_text": "string",
- "html": "string",
- "from_name": "string",
- "scheduled_at": "2019-08-24T14:15:22Z",
- "sent_at": "2019-08-24T14:15:22Z",
- "timezone": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}| id required | integer |
| subject required | string |
| html required | string |
| from_name required | string |
| from_email required | string <email> |
| delay_hours | integer [ 0 .. 5000 ] Hours to wait before sending (default 24, first email defaults to 0) |
{- "subject": "string",
- "html": "string",
- "from_name": "string",
- "delay_hours": 5000
}{- "id": 0,
- "automation_id": 0,
- "campaign_id": 0,
- "delay_hours": 0,
- "send_order": 0,
- "campaign": {
- "id": 0,
- "title": "string",
- "subject": "string",
- "preview_text": "string",
- "html": "string",
- "from_name": "string",
- "scheduled_at": "2019-08-24T14:15:22Z",
- "sent_at": "2019-08-24T14:15:22Z",
- "timezone": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}| id required | integer |
| subject | string |
| html | string |
| from_name | string |
| from_email | string <email> |
| delay_hours | integer [ 0 .. 5000 ] |
| send_order | integer >= 1 |
{- "subject": "string",
- "html": "string",
- "from_name": "string",
- "delay_hours": 5000,
- "send_order": 1
}{- "id": 0,
- "automation_id": 0,
- "campaign_id": 0,
- "delay_hours": 0,
- "send_order": 0,
- "campaign": {
- "id": 0,
- "title": "string",
- "subject": "string",
- "preview_text": "string",
- "html": "string",
- "from_name": "string",
- "scheduled_at": "2019-08-24T14:15:22Z",
- "sent_at": "2019-08-24T14:15:22Z",
- "timezone": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}Returns a paginated list of the user's whitelabel/sender domains
{- "data": [
- {
- "id": 0,
- "domain": "string",
- "sendgrid_whitelabel_domain_id": 0,
- "validated_at": "2019-08-24T14:15:22Z",
- "dns": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "current_page": 0,
- "total": 0,
- "per_page": 0
}Adds a new sender domain and creates the corresponding SendGrid whitelabel domain. Requires an active subscription and SendGrid subuser.
| domain required | string <= 191 characters Domain name (e.g., example.com). Do not include @ or protocol. |
{- "domain": "string"
}{- "id": 0,
- "domain": "string",
- "sendgrid_whitelabel_domain_id": 0,
- "validated_at": "2019-08-24T14:15:22Z",
- "dns": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}Returns domain details including DNS records needed for verification
| id required | integer |
{- "id": 0,
- "domain": "string",
- "sendgrid_whitelabel_domain_id": 0,
- "validated_at": "2019-08-24T14:15:22Z",
- "dns": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}Triggers DNS validation for the domain via SendGrid. Returns whether validation passed and any errors for specific DNS records.
| id required | integer |
{- "message": "string",
- "valid": true,
- "domain": {
- "id": 0,
- "domain": "string",
- "sendgrid_whitelabel_domain_id": 0,
- "validated_at": "2019-08-24T14:15:22Z",
- "dns": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}{- "id": 0,
- "name": "string",
- "contacts_count": 0,
- "contact_limit": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}Creates a custom field for contacts. The name is auto-generated from the label as a slug.
Valid field type IDs: text, number, date (use the UUID constants from the contact_field_types table).
| label required | string <= 191 characters Human-readable field label |
| contact_field_type_id required | string UUID of the field type (text, number, or date) |
{- "label": "string",
- "contact_field_type_id": "string"
}{- "id": 0,
- "label": "string",
- "name": "string",
- "type": "text"
}Updates the label and auto-regenerates the name slug.
Note: contact_field_type_id is immutable and cannot be changed after creation.
| id required | integer |
| label required | string <= 191 characters |
{- "label": "string"
}{- "id": 0,
- "label": "string",
- "name": "string",
- "type": "text"
}