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)Returns a paginated list of contacts (100 per page)
| query | string Search query for filtering contacts |
| unsubscribed | boolean Filter unsubscribed contacts |
string Filter by specific email |
{- "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> |
| 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
}| 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",
- "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 |
| 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 |
{- "title": "string",
- "subject": "string",
- "html": "string",
- "from_name": "string",
- "scheduled_at": "2019-08-24T14:15:22Z",
- "lists": [
- 0
]
}{- "id": 0,
- "title": "string",
- "subject": "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",
- "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 |
| 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 |
{- "title": "string",
- "subject": "string",
- "html": "string",
- "from_name": "string",
- "scheduled_at": "2019-08-24T14:15:22Z",
- "lists": [
- 0
]
}{- "id": 0,
- "title": "string",
- "subject": "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",
- "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, open/click/bounce/unsubscribe/spam counts and rates
| id required | integer |
{- "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
}| 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",
- "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",
- "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",
- "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",
- "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",
- "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",
- "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"
}