SendFox API (1.3.0)

Download OpenAPI specification:Download

Introduction

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.

Authentication

Personal Access Token

Create a personal access token at https://sendfox.com/account/oauth. Once created, use it in the Authorization header:

Authorization: Bearer {TOKEN}

OAuth 2.0 Client

For integrations that require user authentication, create an OAuth 2.0 client at https://sendfox.com/account/oauth

Rate Limits

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 minute
  • X-RateLimit-Remaining: Remaining requests in current window
  • Retry-After: Seconds until rate limit resets (only on 429 responses)

Error Responses

All error responses use standard HTTP status codes and Laravel's default error format:

  • message: Human-readable error description
  • errors: Field-level validation errors (on 422 responses)

Plans & API Access

API access requires a Lifetime or Empire plan. Free users cannot use the API.

Contacts

List contacts

Returns a paginated list of contacts (100 per page)

Authorizations:
oauth2
query Parameters
query
string

Search query for filtering contacts

unsubscribed
boolean

Filter unsubscribed contacts

email
string

Filter by specific email

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "current_page": 0,
  • "total": 0,
  • "per_page": 0
}

Create a new contact

Authorizations:
oauth2
Request Body schema: application/json
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

Responses

Request samples

Content type
application/json
{
  • "email": "[email protected]",
  • "first_name": "string",
  • "last_name": "string",
  • "ip_address": "string",
  • "lists": [
    ],
  • "contact_fields": [
    ]
}

Response samples

Content type
application/json
{
  • "id": 0,
  • "email": "[email protected]",
  • "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"
}

Get a specific contact

Authorizations:
oauth2
path Parameters
id
required
integer

Responses

Response samples

Content type
application/json
{
  • "id": 0,
  • "email": "[email protected]",
  • "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 a contact

Update contact details including name, list memberships, and custom fields

Authorizations:
oauth2
path Parameters
id
required
integer
Request Body schema: application/json
first_name
string
last_name
string
lists
Array of integers

Array of list IDs (replaces all current list memberships)

Array of objects

Responses

Request samples

Content type
application/json
{
  • "first_name": "string",
  • "last_name": "string",
  • "lists": [
    ],
  • "contact_fields": [
    ]
}

Response samples

Content type
application/json
{
  • "id": 0,
  • "email": "[email protected]",
  • "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"
}

Delete a contact

Soft-deletes a contact and cancels any scheduled deliverables

Authorizations:
oauth2
path Parameters
id
required
integer

Responses

Response samples

Content type
application/json
{
  • "message": "string"
}

Get email activity for a contact

Returns paginated email deliverables and contact-level engagement summary

Authorizations:
oauth2
path Parameters
id
required
integer

Responses

Response samples

Content type
application/json
{
  • "contact": {
    },
  • "deliverables": {
    }
}

Batch import contacts

Import up to 1,000 contacts in a single request. Creates new contacts or updates existing ones.

Authorizations:
oauth2
Request Body schema: application/json
required
Array of objects <= 1000 items

Responses

Request samples

Content type
application/json
{
  • "contacts": []
}

Response samples

Content type
application/json
{
  • "created": 0,
  • "updated": 0
}

List unsubscribed contacts

Authorizations:
oauth2
query Parameters
query
string

Search query for filtering contacts

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "current_page": 0,
  • "total": 0,
  • "per_page": 0
}

Unsubscribe a contact by email

Authorizations:
oauth2
Request Body schema: application/json
email
required
string <email>

Responses

Request samples

Content type
application/json
{}

Response samples

Content type
application/json
{
  • "id": 0,
  • "email": "[email protected]",
  • "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"
}

Campaigns

List campaigns

Returns a paginated list of campaigns (100 per page)

Authorizations:
oauth2

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "current_page": 0,
  • "total": 0,
  • "per_page": 0
}

Create a new campaign

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.

Authorizations:
oauth2
Request Body schema: application/json
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

Responses

Request samples

Content type
application/json
{
  • "title": "string",
  • "subject": "string",
  • "html": "string",
  • "from_name": "string",
  • "from_email": "[email protected]",
  • "scheduled_at": "2019-08-24T14:15:22Z",
  • "lists": [
    ]
}

Response samples

Content type
application/json
{
  • "id": 0,
  • "title": "string",
  • "subject": "string",
  • "html": "string",
  • "from_name": "string",
  • "from_email": "[email protected]",
  • "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"
}

Get a specific campaign

Authorizations:
oauth2
path Parameters
id
required
integer

Responses

Response samples

Content type
application/json
{
  • "id": 0,
  • "title": "string",
  • "subject": "string",
  • "html": "string",
  • "from_name": "string",
  • "from_email": "[email protected]",
  • "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"
}

Update a draft campaign

Only draft campaigns (not yet sent) can be updated. All fields are optional.

Authorizations:
oauth2
path Parameters
id
required
integer
Request Body schema: application/json
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

Responses

Request samples

Content type
application/json
{
  • "title": "string",
  • "subject": "string",
  • "html": "string",
  • "from_name": "string",
  • "from_email": "[email protected]",
  • "scheduled_at": "2019-08-24T14:15:22Z",
  • "lists": [
    ]
}

Response samples

Content type
application/json
{
  • "id": 0,
  • "title": "string",
  • "subject": "string",
  • "html": "string",
  • "from_name": "string",
  • "from_email": "[email protected]",
  • "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"
}

Delete a draft campaign

Only draft campaigns (not yet sent) can be deleted. Uses soft delete.

Authorizations:
oauth2
path Parameters
id
required
integer

Responses

Response samples

Content type
application/json
{
  • "message": "string"
}

Send a campaign immediately

Schedules a draft campaign for immediate sending. The campaign must:

  • Not already be sent or scheduled
  • Have at least one list assigned
  • The user must not be in a warmup/throttle period

All existing abuse prevention applies automatically: content approval workflow, sending throttles, spam detection, and bounce rate monitoring.

Authorizations:
oauth2
path Parameters
id
required
integer

Responses

Response samples

Content type
application/json
{
  • "id": 0,
  • "title": "string",
  • "subject": "string",
  • "html": "string",
  • "from_name": "string",
  • "from_email": "[email protected]",
  • "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"
}

Get campaign performance statistics

Returns sent count, open/click/bounce/unsubscribe/spam counts and rates

Authorizations:
oauth2
path Parameters
id
required
integer

Responses

Response samples

Content type
application/json
{
  • "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
}

Lists

List contact lists

Authorizations:
oauth2
query Parameters
query
string

Search query for filtering lists

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "current_page": 0,
  • "total": 0,
  • "per_page": 0
}

Create a new contact list

Authorizations:
oauth2
Request Body schema: application/json
name
required
string

Responses

Request samples

Content type
application/json
{
  • "name": "string"
}

Response samples

Content type
application/json
{
  • "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"
}

Get a specific contact list

Returns list details including average open and click rates

Authorizations:
oauth2
path Parameters
id
required
integer

Responses

Response samples

Content type
application/json
{
  • "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"
}

Update a contact list

Authorizations:
oauth2
path Parameters
id
required
integer
Request Body schema: application/json
name
required
string <= 191 characters

Responses

Request samples

Content type
application/json
{
  • "name": "string"
}

Response samples

Content type
application/json
{
  • "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"
}

Delete a contact list

Soft-deletes a list. Returns 409 if the list is used by forms, landing pages, or automations.

Authorizations:
oauth2
path Parameters
id
required
integer

Responses

Response samples

Content type
application/json
{
  • "message": "string"
}

Get contacts in a list

Authorizations:
oauth2
path Parameters
list_id
required
integer
query Parameters
query
string

Search query for filtering contacts

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "current_page": 0,
  • "total": 0,
  • "per_page": 0
}

Add a contact to a list

Adds an existing contact to a list. If the contact is already in the list, no duplicate is created.

Authorizations:
oauth2
path Parameters
list_id
required
integer
Request Body schema: application/json
contact_id
required
integer

ID of the contact to add

Responses

Request samples

Content type
application/json
{
  • "contact_id": 0
}

Response samples

Content type
application/json
{
  • "id": 0,
  • "email": "[email protected]",
  • "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"
}

Remove a contact from a list

Authorizations:
oauth2
path Parameters
list_id
required
integer
contact_id
required
integer

Responses

Response samples

Content type
application/json
{
  • "id": 0,
  • "email": "[email protected]",
  • "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"
}

Forms

List forms

Authorizations:
oauth2
query Parameters
query
string

Search query for filtering forms

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "current_page": 0,
  • "total": 0,
  • "per_page": 0
}

Create a new form

Creates a subscription form linked to one or more lists. Free users are limited to 1 form.

Authorizations:
oauth2
Request Body schema: application/json
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

Responses

Request samples

Content type
application/json
{}

Response samples

Content type
application/json
{
  • "id": 0,
  • "title": "string",
  • "landing_page_id": 0,
  • "redirect_url": "string",
  • "gdpr_required": true,
  • "url": "string",
  • "lists": [
    ],
  • "created_at": "2019-08-24T14:15:22Z",
  • "updated_at": "2019-08-24T14:15:22Z"
}

Get a specific form

Authorizations:
oauth2
path Parameters
id
required
integer

Responses

Response samples

Content type
application/json
{
  • "id": 0,
  • "title": "string",
  • "landing_page_id": 0,
  • "redirect_url": "string",
  • "gdpr_required": true,
  • "url": "string",
  • "lists": [
    ],
  • "created_at": "2019-08-24T14:15:22Z",
  • "updated_at": "2019-08-24T14:15:22Z"
}

Update a form

Authorizations:
oauth2
path Parameters
id
required
integer
Request Body schema: application/json
title
string <= 191 characters
lists
Array of integers

Replaces all list assignments

redirect_url
string or null <uri>
gdpr_required
boolean

Responses

Request samples

Content type
application/json
{}

Response samples

Content type
application/json
{
  • "id": 0,
  • "title": "string",
  • "landing_page_id": 0,
  • "redirect_url": "string",
  • "gdpr_required": true,
  • "url": "string",
  • "lists": [
    ],
  • "created_at": "2019-08-24T14:15:22Z",
  • "updated_at": "2019-08-24T14:15:22Z"
}

Delete a form

Soft-deletes the form

Authorizations:
oauth2
path Parameters
id
required
integer

Responses

Response samples

Content type
application/json
{
  • "message": "string"
}

Automations

List automations

Authorizations:
oauth2

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "current_page": 0,
  • "total": 0,
  • "per_page": 0
}

Create an automation

Authorizations:
oauth2
Request Body schema: application/json
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

Responses

Request samples

Content type
application/json
{
  • "title": "string",
  • "trigger_type": "apply_list",
  • "trigger_list_id": 0,
  • "trigger_campaign_id": 0,
  • "active": true
}

Response samples

Content type
application/json
{
  • "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": [
    ],
  • "automation_items": [
    ]
}

Get a specific automation

Returns automation with triggers, items, and campaign stats

Authorizations:
oauth2
path Parameters
id
required
integer

Responses

Response samples

Content type
application/json
{
  • "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": [
    ],
  • "automation_items": [
    ]
}

Update an automation

Update title, trigger, or active status. Activating reschedules stale deliverables.

Authorizations:
oauth2
path Parameters
id
required
integer
Request Body schema: application/json
title
string
active
boolean
trigger_type
string
Enum: "apply_list" "open_campaign" "click_campaign"
trigger_list_id
integer
trigger_campaign_id
integer

Responses

Request samples

Content type
application/json
{
  • "title": "string",
  • "active": true,
  • "trigger_type": "apply_list",
  • "trigger_list_id": 0,
  • "trigger_campaign_id": 0
}

Response samples

Content type
application/json
{
  • "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": [
    ],
  • "automation_items": [
    ]
}

Delete an automation

Soft-deletes the automation and cancels all scheduled deliverables

Authorizations:
oauth2
path Parameters
id
required
integer

Responses

Response samples

Content type
application/json
{
  • "message": "string"
}

Add an email to an automation

Authorizations:
oauth2
path Parameters
id
required
integer
Request Body schema: application/json
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)

Responses

Request samples

Content type
application/json
{
  • "subject": "string",
  • "html": "string",
  • "from_name": "string",
  • "from_email": "[email protected]",
  • "delay_hours": 5000
}

Response samples

Content type
application/json
{
  • "id": 0,
  • "automation_id": 0,
  • "campaign_id": 0,
  • "delay_hours": 0,
  • "send_order": 0,
  • "campaign": {
    },
  • "created_at": "2019-08-24T14:15:22Z",
  • "updated_at": "2019-08-24T14:15:22Z"
}

Update an automation email

Authorizations:
oauth2
path Parameters
id
required
integer
Request Body schema: application/json
subject
string
html
string
from_name
string
from_email
string <email>
delay_hours
integer [ 0 .. 5000 ]
send_order
integer >= 1

Responses

Request samples

Content type
application/json
{
  • "subject": "string",
  • "html": "string",
  • "from_name": "string",
  • "from_email": "[email protected]",
  • "delay_hours": 5000,
  • "send_order": 1
}

Response samples

Content type
application/json
{
  • "id": 0,
  • "automation_id": 0,
  • "campaign_id": 0,
  • "delay_hours": 0,
  • "send_order": 0,
  • "campaign": {
    },
  • "created_at": "2019-08-24T14:15:22Z",
  • "updated_at": "2019-08-24T14:15:22Z"
}

Remove an email from an automation

Authorizations:
oauth2
path Parameters
id
required
integer

Responses

Response samples

Content type
application/json
{
  • "message": "string"
}

Domains

List sender domains

Returns a paginated list of the user's whitelabel/sender domains

Authorizations:
oauth2

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "current_page": 0,
  • "total": 0,
  • "per_page": 0
}

Add a sender domain

Adds a new sender domain and creates the corresponding SendGrid whitelabel domain. Requires an active subscription and SendGrid subuser.

Authorizations:
oauth2
Request Body schema: application/json
domain
required
string <= 191 characters

Domain name (e.g., example.com). Do not include @ or protocol.

Responses

Request samples

Content type
application/json
{
  • "domain": "string"
}

Response samples

Content type
application/json
{
  • "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"
}

Get domain with DNS records

Returns domain details including DNS records needed for verification

Authorizations:
oauth2
path Parameters
id
required
integer

Responses

Response samples

Content type
application/json
{
  • "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"
}

Delete a sender domain

Removes the domain from SendGrid and soft-deletes locally

Authorizations:
oauth2
path Parameters
id
required
integer

Responses

Response samples

Content type
application/json
{
  • "message": "string"
}

Validate domain DNS records

Triggers DNS validation for the domain via SendGrid. Returns whether validation passed and any errors for specific DNS records.

Authorizations:
oauth2
path Parameters
id
required
integer

Responses

Response samples

Content type
application/json
{
  • "message": "string",
  • "valid": true,
  • "domain": {
    }
}

Users

Get current user information

Authorizations:
oauth2

Responses

Response samples

Content type
application/json
{
  • "id": 0,
  • "name": "string",
  • "email": "[email protected]",
  • "contacts_count": 0,
  • "contact_limit": 0,
  • "created_at": "2019-08-24T14:15:22Z",
  • "updated_at": "2019-08-24T14:15:22Z"
}

Contact Fields

List user contact fields

Returns custom contact fields defined by the user (20 per page)

Authorizations:
oauth2

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "current_page": 0,
  • "total": 0,
  • "per_page": 0
}

Create a custom contact field

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).

Authorizations:
oauth2
Request Body schema: application/json
label
required
string <= 191 characters

Human-readable field label

contact_field_type_id
required
string

UUID of the field type (text, number, or date)

Responses

Request samples

Content type
application/json
{
  • "label": "string",
  • "contact_field_type_id": "string"
}

Response samples

Content type
application/json
{
  • "id": 0,
  • "label": "string",
  • "name": "string",
  • "type": "text"
}

Get a specific contact field

Authorizations:
oauth2
path Parameters
id
required
integer

Responses

Response samples

Content type
application/json
{
  • "id": 0,
  • "label": "string",
  • "name": "string",
  • "type": "text"
}

Update a contact field label

Updates the label and auto-regenerates the name slug. Note: contact_field_type_id is immutable and cannot be changed after creation.

Authorizations:
oauth2
path Parameters
id
required
integer
Request Body schema: application/json
label
required
string <= 191 characters

Responses

Request samples

Content type
application/json
{
  • "label": "string"
}

Response samples

Content type
application/json
{
  • "id": 0,
  • "label": "string",
  • "name": "string",
  • "type": "text"
}

Delete a contact field

Permanently deletes the contact field

Authorizations:
oauth2
path Parameters
id
required
integer

Responses

Response samples

Content type
application/json
{
  • "message": "string"
}