# Create campaign
Source: https://docs.sendx.io/api-reference/campaign/create-campaign
post /campaign
Creates a new email campaign.
**π― Campaign Features:**
* Target specific lists, tags, and segments
* Schedule campaigns or send immediately
* Smart send optimization
* Time zone aware delivery
* A/B testing capabilities
**π
Schedule Types:**
* `0` - Schedule for later
* `1` - Send immediately
**π§ Advanced Options:**
* **Smart Send**: Optimizes delivery time based on recipient engagement
* **Contact Timezone**: Sends at specified time in each contact's timezone
**π¨ Content Requirements:**
* HTML content is required
* Plain text version recommended for better deliverability
* Preview text improves open rates
* Subject line personalization supported
# Delete campaign
Source: https://docs.sendx.io/api-reference/campaign/delete-campaign
delete /campaign/{identifier}
Deletes a campaign.
**β οΈ Restrictions:**
* Cannot delete sent campaigns (archive instead)
* Cannot delete currently sending campaigns
* Cannot delete scheduled campaigns.
**π‘ Alternatives:**
* Archive campaigns to hide from main list
* Cancel scheduled campaigns before deletion
* Copy and modify instead of deleting sent campaigns
# Get all campaigns
Source: https://docs.sendx.io/api-reference/campaign/get-all-campaigns
get /campaign
Retrieves a paginated list of all campaigns.
**π― Key Features:**
* Filter by campaign type
* Pagination support
* Sort by date or performance
* Include campaign statistics
**π Status Values:**
* `0` - Draft
* `1` - Scheduled
* `2` - Sending
* `3` - Sent
* `4` - Quarantined
* `5` - Evaluating
* `6` - EvaluationFailed
* `7` - WarmingUp
# Get campaign by ID
Source: https://docs.sendx.io/api-reference/campaign/get-campaign-by-id
get /campaign/{identifier}
Retrieves detailed information about a specific campaign.
**π§ Campaign Details Include:**
* Complete campaign configuration
* Content and design information
* Targeting and segmentation rules
* Schedule and timezone settings
**π Use Cases:**
* Preview campaign before sending
* Check campaign status
* Review targeting settings
* Access campaign for editing
# Create a new contact
Source: https://docs.sendx.io/api-reference/contact/create-a-new-contact
post /contact
Creates a new contact in your SendX team with the provided information.
**π― Key Features:**
- Email validation and duplicate detection
- Automatic relationship building with lists and tags
- Smart custom field handling
**π Business Rules:**
- Email is mandatory and must be unique within the team
- Last tracked IP is stored for analytics
# Delete contact
Source: https://docs.sendx.io/api-reference/contact/delete-contact
delete /contact/{identifier}
Soft deletes a contact from your team.
**π― Key Features:**
- Soft delete preserves data
- Removes from all lists
- Cancels pending campaigns
- Maintains historical data
# Get all contacts
Source: https://docs.sendx.io/api-reference/contact/get-all-contacts
get /contact
Retrieves a paginated list of all contacts in your team with optional filtering capabilities.
**π― Key Features:**
- Pagination support with offset/limit
- Search contacts by name or email
- All relationships included (lists, tags, custom fields)
- Prefixed IDs for easy integration
**π Pagination:**
- Default limit: 10 contacts per page
- Maximum limit: 100 contacts per page
- Use offset for page navigation
**π Search:**
- Searches across firstName, lastName, and email fields
- Case-insensitive partial matching
- Combine with pagination for large datasets
# Get contact by ID
Source: https://docs.sendx.io/api-reference/contact/get-contact-by-id
get /contact/{identifier}
Retrieves detailed information about a specific contact.
**π― Key Features:**
- Returns complete contact profile
- Includes all lists and tags
- Shows custom field values
- Provides engagement metrics
# Unsubscribe contact
Source: https://docs.sendx.io/api-reference/contact/unsubscribe-contact
post /contact/unsubscribe/{identifier}
Unsubscribes a contact from all marketing communications.
**π― Key Features:**
- Marks contact as unsubscribed
- Removes from all active campaigns
- Maintains unsubscribe history
- Complies with anti-spam regulations
# Update contact
Source: https://docs.sendx.io/api-reference/contact/update-contact
put /contact/{identifier}
Updates an existing contact's information.
**π― Key Features:**
- Partial updates supported
- Add/remove lists and tags
- Update custom fields
- Change email address
# Create custom field
Source: https://docs.sendx.io/api-reference/custom-field/create-custom-field
post /customfield
Creates a new custom field for storing contact data.
**π― Purpose:**
Custom fields extend the default contact schema with business-specific data:
* Customer preferences and attributes
* Behavioral tracking fields
* Integration-specific identifiers
* Segmentation criteria
**π Field Types:**
* **0 - Text**: Single-line text (max 255 chars)
* **1 - Number**: Integer or decimal values
* **2 - Date**: Date values (YYYY-MM-DD)
* **3 - Boolean**: True/false values
* **4 - Phone number**: International phone number format
**π‘ Use Cases:**
* Customer lifetime value (Number)
* Subscription expiry date (Date)
* Product preferences (Text)
* Account type (Text)
* Last purchase date (Date)
* Loyalty points (Number)
**π Field Usage:**
* Set values during contact creation/update
* Use in segmentation rules
* Personalize email content with merge tags
* Export in contact reports
**β‘ Best Practices:**
* Use descriptive field names
* Choose appropriate field types
* Document field purposes
* Limit total custom fields for performance
# Delete custom field
Source: https://docs.sendx.io/api-reference/custom-field/delete-custom-field
delete /customfield/{identifier}
Deletes a custom field (data is preserved).
**π― Key Features:**
- Remove unused fields
- Data remains on contacts
- Clean up field list
# Get all custom fields
Source: https://docs.sendx.io/api-reference/custom-field/get-all-custom-fields
get /customfield
Retrieves all custom fields defined for your team.
**π Response includes:**
* Field ID
* Field name and type
* Description
# Get custom field by ID
Source: https://docs.sendx.io/api-reference/custom-field/get-custom-field-by-id
get /customfield/{identifier}
Retrieves details about a specific custom field.
# Update custom field
Source: https://docs.sendx.io/api-reference/custom-field/update-custom-field
put /customfield/{identifier}
Updates a custom field definition.
**π Updatable fields:**
* Field name (must remain unique)
* Description
* Type
**β οΈ Important:**
* Existing data is preserved
* Name changes reflect in merge tags
* Updates don't affect historical data
**π‘ Common Updates:**
* Clarify field descriptions
* Rename for consistency
* Toggle visibility in forms
* Enable cross-team sharing
# Create domain
Source: https://docs.sendx.io/api-reference/domain/create-domain
post /domain
Creates a new domain for email sending. After creation, you'll need to configure DNS records (DKIM, SPF, DMARC) to verify the domain.
**π― Purpose:**
Domains are essential for email authentication and deliverability. Creating a domain allows you to:
* Authenticate your email sending domain
* Configure DNS records for email security
* Improve sender reputation and deliverability
* Set up custom tracking domains
**π‘ Use Cases:**
* Branded email sending ([newsletter@yourdomain.com](mailto:newsletter@yourdomain.com))
* Custom tracking domains for analytics
* Multiple domain management for different brands
* Subdomain management (mail.yourdomain.com)
**π§ DNS Configuration:**
After creating a domain, you'll need to configure DNS records:
1. **DKIM** - DomainKeys Identified Mail for email signing
2. **SPF** - Sender Policy Framework for sender authorization
3. **DMARC** - Domain-based Message Authentication for policy enforcement
4. **Return Path** - Bounce handling configuration
5. **Tracking Domain** - Custom tracking for email analytics
**β‘ Best Practices:**
* Use your primary business domain for better reputation
* Complete all DNS verifications before sending
* Monitor verification status regularly
* Keep DNS records updated and valid
* Use subdomains for different email purposes (marketing, transactional)
**π Security Tips:**
* Verify all DNS records are correctly configured
* Regularly check DMARC reports
* Monitor domain reputation
* Keep domain registration active
# Delete domain
Source: https://docs.sendx.io/api-reference/domain/delete-domain
delete /domain/{identifier}
Deletes a domain from the system.
**π― Purpose:**
Delete a domain from your SendX team. This action removes the domain configuration and all associated settings.
**β οΈ Important Considerations:**
* Deleting a domain is permanent and cannot be undone
* Any senders using this domain may be affected
* DNS records should be removed from your DNS provider separately
* Consider the impact on active campaigns
**π‘ Use Cases:**
* Remove unused or test domains
* Clean up domains that are no longer needed
* Replace domains with new configurations
* Remove domains with failed verifications
**π Before Deleting:**
1. Ensure no active campaigns are using this domain
2. Check that no senders depend on this domain
3. Verify you have backups of DNS configurations if needed
4. Consider the impact on email deliverability
**β‘ Best Practices:**
* Only delete domains that are truly no longer needed
* Document DNS configurations before deletion
* Remove DNS records from your DNS provider after deletion
* Update any automation or integrations that reference this domain
# Get all domains
Source: https://docs.sendx.io/api-reference/domain/get-all-domains
get /domain
Retrieves all domains in your team with their verification status and DNS configuration details.
**π― Purpose:**
Retrieve all domains configured in your SendX team with their verification status and DNS configuration details.
**π‘ Use Cases:**
* Monitor domain verification status across all domains
* Review DNS configuration for multiple domains
* Check which domains are ready for sending
* Audit domain setup and compliance
**π Response Information:**
The response includes:
* Domain verification status (verified, dkimVerified, dmarcVerified, etc.)
* DNS record configurations (DKIM, SPF, DMARC, Return Path, Tracking)
* Domain creation and update timestamps
* Verification failure reasons (if any)
**β‘ Best Practices:**
* Regularly check domain verification status
* Use pagination for large numbers of domains
* Filter and sort domains by verification status
* Monitor domains that need attention
# Get domain by ID
Source: https://docs.sendx.io/api-reference/domain/get-domain-by-id
get /domain/{identifier}
Retrieves detailed information about a specific domain including verification status and DNS configuration.
**π― Purpose:**
Retrieve detailed information about a specific domain including all verification statuses and DNS record configurations.
**π‘ Use Cases:**
* Check specific domain verification status
* Review DNS record details for troubleshooting
* Verify domain configuration before sending
* Audit domain setup for compliance
**π Response Information:**
The response includes complete domain details:
* All verification flags (verified, dkimVerified, dmarcVerified, trackVerified, etc.)
* Complete DNS record objects (host, type, textValue) for:
* DKIM configuration
* Return Path (bounce handling)
* Tracking domain
* DMARC policy
* GPT (Google Postmaster Tools)
* DKIM configuration in JSON format
* Domain creation and update timestamps
* DMARC failure reasons (if any)
**π§ DNS Record Details:**
Each DNS record object contains:
* `host` - The DNS hostname to configure
* `type` - DNS record type (TXT, CNAME, etc.)
* `textValue` - The value to set in the DNS record
**β‘ Troubleshooting:**
* Check verification flags to identify which records need attention
* Use DNS record details to configure your DNS provider
* Review dmarcFailureReason if DMARC verification fails
* Verify all DNS records are properly propagated
# Personalization & Merge Tags
Source: https://docs.sendx.io/api-reference/email-sending/personalization
Use merge tags to insert dynamic values β names, custom fields, links, and images β into email templates and transactional emails.
SendX lets you insert dynamic, per-recipient values into your email content using **merge tags**. Use them to greet a contact by name, drop in an order amount, render a dynamic image, or build a personalized button link.
## Syntax
SendX renders email content with **Go's template engine**, so every merge tag is wrapped in double curly braces and **must start with a leading dot (`.`)**:
```
{{.VariableName}}
```
**The leading dot is required.** `{{.FirstName}}` works; `{{FirstName}}` (no dot) does **not** β it will fail to render and your template will appear to "not take effect." This is the single most common personalization mistake.
| You want to insert⦠| Use this | Renders as |
| ------------------------- | ----------------------------------------------- | --------------------------------------------------- |
| A text value | `Hi {{.FirstName}}!` | `Hi Jane!` |
| A value inside a sentence | `Your order {{.orderId}} is confirmed.` | `Your order A12345 is confirmed.` |
| A dynamic image | `
` | `
` |
| A dynamic button/link | `{{.buttonLabel}}` | `Pay now` |
Merge tags work anywhere in the template β in the subject line, in body text, and inside HTML attributes like `src` and `href`.
## Personalizing transactional emails (`POST /send/template`)
When you send a transactional email with a saved template, you supply the per-recipient values in the **`customFields`** object on each `to` entry. Every key you pass becomes a merge tag of the same name.
Keys map **verbatim**: the key `orderId` populates `{{.orderId}}`, `amount` populates `{{.amount}}`, and so on. You do **not** need to pre-define these as custom fields in your account β any ad-hoc key works for transactional sends.
**Template HTML (saved in SendX):**
```html theme={null}
{{.accountName}} update
Hi {{.firstName}}, we received your payment of {{.amount}}.
{{.buttonLabel}}
```
**Request:**
```bash theme={null}
curl -X POST "https://api.sendx.io/api/v1/rest/send/template" \
-H "Content-Type: application/json" \
-H "X-Team-ApiKey: YOUR_API_KEY" \
-d '{
"from": { "email": "support@example.com", "name": "Acme" },
"to": [
{
"email": "jane@acme.com",
"name": "Jane",
"customFields": {
"accountName": "Acme",
"firstName": "Jane",
"amount": "$42.00",
"imageUrl": "https://cdn.example.com/receipt.png",
"buttonUrl": "https://app.example.com/pay/A12345",
"buttonLabel": "View receipt"
}
}
],
"subject": "{{.accountName}} update",
"template": "template_qmK2dMPNoQDobfxI4yMM7k"
}'
```
**Rendered email:**
```html theme={null}
Acme update
Hi Jane, we received your payment of $42.00.
View receipt
```
### Variables available in transactional templates
The transactional send path builds a minimal data context. The following are available in a `/send/template` render:
| Merge tag | Source |
| --------------- | ---------------------------------- |
| `{{.Name}}` | The recipient's `name` field |
| `{{.Email}}` | The recipient's `email` field |
| `{{.}}` | Any key you pass in `customFields` |
In transactional templates, `{{.FirstName}}`, `{{.LastName}}`, and `{{.Company}}` exist but default to **empty** unless you pass them yourself in `customFields`. The richer native tags below (e.g. `{{.ViewInBrowserLink}}`, `{{.GlobalUnsubscribeLink}}`) are **only** populated for campaign, drip, and workflow sends β not transactional sends. For transactional unsubscribe handling, use the `List-Unsubscribe` header.
## Personalizing campaigns & automations
For campaigns, drip sequences, and workflow emails, SendX pulls values from the contact's stored profile, so a richer set of native tags is available automatically:
| Merge tag | Description |
| ---------------------------- | --------------------------------------------------------- |
| `{{.FirstName}}` | Contact's first name |
| `{{.LastName}}` | Contact's last name |
| `{{.Name}}` | First + last name |
| `{{.Email}}` | Contact's email address |
| `{{.Company}}` | Contact's company |
| `{{.CreatedDate}}` | Date the contact was added (`YYYY-MM-DD`) |
| `{{.ViewInBrowserLink}}` | "View in browser" URL |
| `{{.GlobalUnsubscribeLink}}` | Unsubscribe URL |
| `{{.Address}}` | Your account's physical mailing address (CAN-SPAM footer) |
Custom fields are referenced by their **name**, e.g. a custom field named `City` becomes `{{.City}}`. See [Custom field naming rules](#custom-field-naming-rules) below.
## Default (fallback) values
If a value might be missing or blank, wrap it with the `fallback` helper so the email never shows an empty gap:
```
Hi {{fallback .FirstName "there"}}!
```
If `FirstName` is empty, this renders `Hi there!`. The SendX editor inserts this form automatically for every merge tag, using `"there"` as the default β so review the defaults if you want something other than "there" to appear for blank values.
## Conditional content & loops
Because SendX uses Go templates, you can conditionally show content or loop over lists.
**Conditional:**
```html theme={null}
{{if .couponCode}}
Use code {{.couponCode}} for 10% off!
{{else}}
Thanks for being a customer.
{{end}}
```
**Loop** (the values must be passed as a list):
```html theme={null}
{{range .items}}
- {{.name}} β {{.price}}
{{end}}
```
## Helper functions
A few useful helpers are available inside tags (used as `{{helper arg1 arg2}}`):
| Helper | Example | Description |
| ---------------------------------------------- | ------------------------------------ | ----------------------------------------------- |
| `fallback` | `{{fallback .FirstName "there"}}` | Returns the default if the value is empty/blank |
| `capitalize_words` | `{{capitalize_words .city}}` | Title-cases the value |
| `first_character` | `{{first_character .FirstName}}` | First character (e.g. for an avatar initial) |
| `formatdate` | `{{formatdate .date "02 Jan 2006"}}` | Formats a date |
| `todaydate` / `tomorrowdate` / `yesterdaydate` | `{{todaydate "02 Jan 2006"}}` | Relative date helpers |
| `days_until` / `days_since` | `{{days_until .expiry}}` | Day-count helpers |
## Custom field naming rules
When you create a custom field in SendX, the **name** you pick becomes its merge tag. A few rules apply:
* Names are sanitized to letters, digits, and underscores β any other character (including spaces) becomes `_`. A field named `Order ID` becomes the tag `{{.Order_ID}}`.
* These names are **reserved** (they collide with native attributes) and can't be used for custom fields: `email`, `firstname`, `lastname`, `company`, `name`.
* For transactional `customFields` keys, use the same rule of thumb β stick to letters, digits, and underscores, and don't start a key with a digit, so it can be addressed as `{{.key}}`.
The opaque IDs you see in the REST API (e.g. `custom_field_MnuqBAG2NPLm7PZMWbjQxt`) are **not** what you use in templates. Templates always reference custom fields by their human-readable **name**.
## Troubleshooting
The most common cause is a **missing leading dot**. Use `{{.FirstName}}`, not `{{FirstName}}`. Also confirm:
* The variable name matches exactly (it's case-sensitive β `{{.firstName}}` β `{{.FirstName}}`).
* For transactional sends, the key exists in the recipient's `customFields` object.
* You're editing and sending the correct template ID.
The field had no value for that recipient. Pass the value in `customFields` (transactional) or set it on the contact (campaigns). Empty values wrapped in `{{fallback .X "there"}}` render the default β change the default text if "there" isn't what you want.
Those campaign-level system variables aren't injected for transactional `/send/template` sends. Only `{{.Name}}`, `{{.Email}}`, and your `customFields` keys are available there.
# Send email using template
Source: https://docs.sendx.io/api-reference/email-sending/send-email-using-template
post /send/template
Sends emails using a pre-defined template with variable substitution. Per-recipient personalization runs in the worker and is not validated in the API.
The API validates the request synchronously and returns **202 Accepted** when the email is queued. Actual sending and personalization happen asynchronously in a worker. A 202 does not guarantee delivery; it means the request was accepted and queued. Per-recipient success/failure is not returned in the API response.
**Optional headers:** `List-Unsubscribe` (passed through for list-unsubscribe), `X-SendPost-Mock-Email: true` (mock send, if supported).
**π― Key Features:**
* Use saved email templates
* Variable substitution
* Multiple recipients support
* Tracking and analytics
# Send transactional email
Source: https://docs.sendx.io/api-reference/email-sending/send-transactional-email
post /send/email
Sends transactional emails to specified recipients with support for personalization, attachments, and tracking.
The API validates the request synchronously and returns **202 Accepted** when the email is queued. Actual sending and personalization happen asynchronously in a worker. A 202 does not guarantee delivery; it means the request was accepted and queued. Per-recipient success/failure is not returned in the API response.
**Optional headers:** `List-Unsubscribe` (passed through for list-unsubscribe), `X-SendPost-Mock-Email: true` (mock send, if supported).
**π― Key Features:**
* Send to multiple recipients with CC/BCC support
* HTML, plain text, and AMP content
* Custom headers and tracking options
* Webhook notifications for delivery events
**π Rate Limits:**
* Account-based email sending limits apply
# Push custom event
Source: https://docs.sendx.io/api-reference/events/track-custom-event
post /events/custom
Records custom events for advanced tracking.
## Request Properties
| Property | Type | Description |
| ---------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| name | `string` | The name of the custom event. |
| identifier | `string` | A unique identifier for the contact (e.g., an email address). |
| data | `map[string]string` | A set of key-value pairs containing additional event properties. |
| time | `int64` (optional) | Unix timestamp (in seconds since January 1, 1970) representing when the event occurred. If omitted, the current request time will be used. |
### Example Request:
```json theme={null}
{
"name": "abandoned_cart",
"identifier": "john.doe@example.com",
"data": {
"price": "29.99",
"currency": "USD",
"item_count": "3"
},
"time": 1669990400
}
```
# Push revenue event
Source: https://docs.sendx.io/api-reference/events/track-revenue-event
post /events/revenue
Records revenue events for analytics and attribution.
**π― Key Features:**
* Track purchase events
* Revenue attribution
* Custom properties
* Analytics integration
# Track contact
Source: https://docs.sendx.io/api-reference/getting-started/add-tracking-info
post /contact/track
Legacy endpoint for tracking contact behavior through tags.
**π― Key Features:**
- Add or remove tags
- Trigger automations
- Track user behavior
The Track API Method is used to track a contact's actions by managing tags.
### Example Requests:
Add tags:
```json theme={null}
{
"addTags": ["blogger", "female"]
}
```
Add and remove tags:
```json theme={null}
{
"addTags": ["paid user"],
"removeTags": ["trial user"]
}
```
Automation rules can be triggered based on tag additions or removals, e.g.:
* On user registration tag, start onboarding drip campaigns.
* On account upgrade, start account expansion drip campaigns.
* On removal of the trial user tag, initiate upsell campaigns.
# Identify contact
Source: https://docs.sendx.io/api-reference/getting-started/identify-contact
post /contact/identify
Endpoint for identifying contacts. Creates or updates a contact.
**π― Key Features:**
- Creates contact if doesn't exist
- Updates if email already exists
- Supports custom fields, tags and lists
The Identify API Method is used to attach data to a visitor and manage contact creation or updates.
### Example Request:
```json theme={null}
{
"email": "john.doe@gmail.com",
"firstName": "John",
"lastName": "Doe",
"birthday": "1989-03-03",
"customFields": {
"Designation": "Software Engineer",
"Age": "27",
"Experience": "5"
},
"tags": ["Developer", "API Team"]
}
```
* Tags and custom fields that do not exist are created automatically.
* Existing tags and custom fields are updated with the new data.
* Properties are additive: no data is removed based on subsequent Identify calls.
# Identify Bulk Contacts
Source: https://docs.sendx.io/api-reference/getting-started/identify-contact-bulk
post /contact/identify/bulk
Endpoint for identifying bulk contacts. Creates or updates multiple contacts in a single request.
**π― Key Features:**
- Creates contact if doesn't exist
- Updates if email already exists
- Supports custom fields and tags
- Supports batch operations (max 25 contacts per request)
The Identify API Method is used to attach data to a visitor and manage contact creation or updates.
* Tags and custom fields that do not exist are created automatically.
* Existing tags and custom fields are updated with the new data.
* Properties are additive: no data is removed based on subsequent Identify calls.
# Introduction
Source: https://docs.sendx.io/api-reference/introduction
Understand the basics of SendX REST convention and common parameters
## Base URL
The SendX API is organized around **REST**. Our API has predictable resource-oriented URLs, accepts form-encoded request bodies, returns JSON-encoded responses, and uses standard HTTP response codes, authentication, and verbs.
The SendX Rest API doesn't support bulk updates. You can work on only one object per request.
All requests contain the following base URL
```
https://api.sendx.io/api/v1/rest
```
You can also [import](https://god.gw.postman.com/run-collection/33476323-51848bb5-04de-4236-a2ad-0a64a8a83f6a?action=collection%2Ffork\&source=rip_markdown\&collection-url=entityId%3D33476323-51848bb5-04de-4236-a2ad-0a64a8a83f6a%26entityType%3Dcollection%26workspaceId%3D6b1e4f65-96a9-4136-9512-6266c852517e) the postman collection as well.
## Authentication
The SendX API uses API key to authenticate requests. You can check out your API key from your settings page [https://app.sendx.io/setting/connectors/api](https://app.sendx.io/setting/connectors/api) under the section `Team Api Key`.
SendX expects the API key to be included in all API requests to the server in a header that looks like the following:
```
X-Team-ApiKey: HUeDwxLQhZU0V2ColDCy
```
Your API keys carry many privileges, so be sure to keep them secure! Do not share your secret API keys in publicly accessible areas such as GitHub, client-side code, and so forth. All API requests must be made over HTTPS. Calls made over plain HTTP will fail. API requests without authentication will also fail.
## Response Codes
SendX uses conventional HTTP response codes to indicate the success or failure of an API request.
In general: Codes in the 2xx range indicate success. Codes in the 4xx range indicate an error that failed given the information provided (e.g., a required parameter was omitted, a failed resource search, etc.). Codes in the 5xx range indicate an error with SendX's servers (drop us a mail at [support@sendx.io](mailto:support@sendx.io) in case that ever happens). Here's some error codes and what they mean:
| **Status Code** | **Reason** | **Description** |
| --------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| 400 | Bad Request | The request could not be understood by the server due to malformed syntax. |
| 401 | Unauthorized | The request requires user authentication, e.g., due to missing or invalid authentication token. |
| 403 | Forbidden | The request is understood, but it has been refused or access is not allowed. |
| 404 | Not Found | The requested resource could not be found. |
| 406 | Not Acceptable | The requested format is not supported by the requested method. |
| 422 | Unprocessable Entity | The server understood the request, but the request is semantically erroneous (e.g., a request may contain a malformed email address). |
| 500 | Internal Server Error | The server encountered an unexpected condition which prevented it from fulfilling the request. |
## Identifiers
SendX allows user manipulations through ids within the entire REST API, to ensure developer ease, each resource has a prefixed id. Here's an example of all the types of ids:
| **Entity** | **Prefix** |
| ------------- | ---------------- |
| Contact | `contact_` |
| List | `list_` |
| Tag | `tag_` |
| Campaign | `campaign_` |
| Sender | `sender_` |
| Custom Field | `custom_field_` |
| Webhook | `webhook_` |
| Template | `template_` |
| Segment | `segment_` |
| Member | `member_` |
| Post | `post_` |
| Post Category | `post_category_` |
| Post Tag | `post_tag_` |
# Create list
Source: https://docs.sendx.io/api-reference/list/create-list
post /list
Creates a new contact list.
**π― Use Cases:**
* Newsletter subscribers
* Customer segments
* Lead capture lists
* Event registrations
# Delete list
Source: https://docs.sendx.io/api-reference/list/delete-list
delete /list/{identifier}
Deletes a list.
**π― Key Features:**
* Soft delete preserves data
* Contacts remain in system
* Cannot delete system lists
* Maintains historical data
# Get all lists
Source: https://docs.sendx.io/api-reference/list/get-all-lists
get /list
Retrieves all contact lists in your team.
**π― Key Features:**
* View all lists
* Check list settings
# Get list by ID
Source: https://docs.sendx.io/api-reference/list/get-list-by-id
get /list/{identifier}
Retrieves detailed information about a specific list.
**π― Key Features:**
* Complete list details
* Subscriber statistics
* Growth metrics
* List settings
# Update list
Source: https://docs.sendx.io/api-reference/list/update-list
put /list/{identifier}
Updates an existing list's settings.
**π― Key Features:**
* Change list name
# Create post category
Source: https://docs.sendx.io/api-reference/post-category/create-post-category
post /post/category
Creates a new category for organizing blog posts.
**π― Key Features:**
* Organize content
* Hierarchical structure
* SEO friendly
# Delete post category
Source: https://docs.sendx.io/api-reference/post-category/delete-post-category
delete /post/category/{identifier}
Soft deletes a post category.
# Get all post categories
Source: https://docs.sendx.io/api-reference/post-category/get-all-post-categories
get /post/category
Retrieves all blog post categories.
# Get post category by ID
Source: https://docs.sendx.io/api-reference/post-category/get-post-category-by-id
get /post/category/{identifier}
Retrieves a specific post category.
# Update post category
Source: https://docs.sendx.io/api-reference/post-category/update-post-category
put /post/category/{identifier}
Updates a post category.
# Create post tag
Source: https://docs.sendx.io/api-reference/post-tag/create-post-tag
post /post/tag
Creates a new tag for blog posts.
# Delete post tag
Source: https://docs.sendx.io/api-reference/post-tag/delete-post-tag
delete /post/tag/{identifier}
Soft deletes a post tag.
# Get all post tags
Source: https://docs.sendx.io/api-reference/post-tag/get-all-post-tags
get /post/tag
Retrieves all blog post tags.
# Get post tag by ID
Source: https://docs.sendx.io/api-reference/post-tag/get-post-tag-by-id
get /post/tag/{identifier}
Retrieves a specific post tag.
# Update post tag
Source: https://docs.sendx.io/api-reference/post-tag/update-post-tag
put /post/tag/{identifier}
Updates a post tag.
# Create blog post
Source: https://docs.sendx.io/api-reference/post/create-blog-post
post /post
Creates a new blog post.
The post can be saved as a draft (`isPublished: false`) or published immediately (`isPublished: true`).
You can associate it with a category, author, thumbnail, HTML content, tags, and provide SEO/social metadata for enhanced visibility.
**π― Key Features:**
* Rich content editor
* SEO optimization
* Social media settings
* Category and tag support
π Use Cases
1. Create a Draft Post for Future Publishing
Save an unpublished draft with just the title, description, and category.
2. Publish a Post with Complete Metadata
Include SEO tags, author, tags, and publish the post immediately.
3. Save a Post with Custom Slug and Thumbnail
Customize the URL and add branding visuals.
# Delete post
Source: https://docs.sendx.io/api-reference/post/delete-post
delete /post/{identifier}
Soft deletes a blog post.
**π― Key Features:**
- Soft delete
- Preserve data
- Remove from listings
# Get all posts
Source: https://docs.sendx.io/api-reference/post/get-all-posts
get /post
Retrieves all blog posts with pagination.
**π― Key Features:**
- Filter by status
- Search functionality
- Sort options
- Include metadata
# Get post by ID
Source: https://docs.sendx.io/api-reference/post/get-post-by-id
get /post/{identifier}
Retrieves a specific blog post.
**π― Key Features:**
- Full post content
- SEO metadata
- Related posts
- Engagement metrics
# Update post
Source: https://docs.sendx.io/api-reference/post/update-post
put /post/{identifier}
Updates an existing blog post.
**π― Key Features:**
- Edit content
- Update metadata
- Change status
- Modify tags/categories
# Get campaign report
Source: https://docs.sendx.io/api-reference/report/get-campaign-report
get /report/campaign/{identifier}
Retrieves a detailed performance report for a specific campaign.
**π― Key Features:**
* Open and click rates
* Unsubscribe and bounce rates
* Link-level click tracking
* Geolocation data
# Schemas
Source: https://docs.sendx.io/api-reference/schema
Detailed overview of all objects used within SendX REST API
## Contact
The **Contact** is a fundamental resource within SendX. It represents your customers, leads, or any person you wish to communicate with through your marketing campaigns.
Once a contact is added to SendX, you can send personalized marketing campaigns, manage their details, and track their interaction with your marketing activities.
SendX provides several key attributes associated with each contact. Additionally, custom fields allow you to add any extra information that may not be covered by the default fields. You can also categorize contacts using tags, and group them into lists for easier targeting in specific campaigns. Below is a detailed overview of the Contact schema.
| **Field** | **Type** | **Description** | **Example** |
| ------------- | ------------------ | ----------------------------------------------------------------------------------- | --------------------------------------------------- |
| id | string | Unique identifier for the contact. Used to reference a contact in your application. | contact\_xxxxxxxx |
| firstName | string | First name of the contact. | John |
| lastName | string | Last name of the contact. | Doe |
| email | string (email) | Email address of the contact. This field is mandatory. | [john.doe@example.com](mailto:john.doe@example.com) |
| company | string | Company associated with the contact. | Acme Corp |
| customFields | object | A key-value object of custom field IDs and their values. | `{ "field_xabc123": "Developer" }` |
| unsubscribed | boolean | Indicates if the contact has unsubscribed from emails. | true |
| bounced | boolean | Indicates if the contactβs email address bounced. | false |
| spam | boolean | Indicates if the contact marked your emails as spam. | false |
| created | string (date-time) | ISO 8601 date-time when the contact was created. | 2025-06-23T11:01:24.936122Z |
| updated | string (date-time) | ISO 8601 date-time when the contact was last updated. | 2025-06-30T10:40:04.606013Z |
| blocked | boolean | Indicates if the contact is blocked from receiving emails. | false |
| dropped | boolean | Indicates if emails to this contact were dropped. | false |
| ltv | integer | Lifetime value (LTV) of the contact in currency units. | 0 |
| contactSource | integer | Indicates how the contact was added. | 3 |
| pageSource | string | Source page from which the contact was added. | [https://google.com](https://google.com) |
| lastTrackedIp | string | Last known IP address from which the contact was tracked. | 192.168.0.1 |
| lists | \[string] | List of list IDs associated with the contact. | \[ "list\_K9ARTjg9U6ycvFvS8J4uRy" ] |
| tags | \[string] | List of tag IDs associated with the contact. | \[ "tag\_K9ARTjg9U6ycvFvS8J4uRy", "tag\_xyz456" ] |
SendX REST API allows users to perform operations on any contact based on its identifier. Identifier can be either:
* Contact ID of the contact (eg: contact\_xxxxxxx)
* Email of the contact (eg: [linus@example.com](mailto:linus@example.com))
1. ContactSourceUnknown
2. ContactSourceFileImport
3. ContactSourceJSAPI
4. ContactSourceRESTAPI
5. ContactSourceManualAddition
6. ContactSourcePopup
7. ContactSourceForm
8. ContactSourceLandingPage
9. ContactSourceInstaPage
10. ContactSourceSamCart
11. ContactSourceWooCommerce
12. ContactSourceStripe
13. ContactSourcePaypal
14. ContactSourceIntercom
15. ContactSourceShopify
16. ContactSourceWebPush
17. ContactSourceConvertBox
18. ContactSourceClickFunnel
19. ContactSourceTeachable
20. ContactSourceWoorise
## List
A List in SendX is a collection of contacts, similar to organizing a guest list for an event. Depending on how the list is configured, there are two types of opt-in mechanisms:
* **Single Opt-in**: In this type, contacts are directly added to the list once they provide their email address, just like guests who confirm their attendance without any extra steps.
* **Double Opt-in**: In this type, contacts are sent a confirmation email and must verify their subscription before being fully added to the list. This is like sending a "Save the Date" invitation, where the guest needs to RSVP before theyβre officially included.
These opt-in mechanisms help ensure that your contacts are either instantly subscribed (single opt-in) or confirmed (double opt-in) based on their preference. Lists allow you to group your contacts for targeted and personalized marketing campaigns.
| Field | Type | Description | Example |
| ------------------- | ------------------ | ----------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
| id | string | Encrypted identifier for the list. | list\_xxxxxxxx |
| name | string | Name of the list. | Customer List |
| type | integer | Type of the list.**Possible values:**`0` = SingleOptIn`1` = DoubleOptIn | 0 |
| sendThankYouMail | boolean | Indicates if a thank-you email should be sent after subscription. | true |
| thankYouFromName | string | Name shown as the sender for the thank-you email. | Support Team |
| thankYouFromEmail | string | Email address from which the thank-you email is sent. | [support@sendx.io](mailto:support@sendx.io) |
| thankYouMailSubject | string | Subject line of the thank-you email. | Welcome to our newsletter |
| thankYouMailMessage | string | Content of the thank-you email. | Thank you for subscribing! |
| thankYouSender | string | Sender ID for the thank-you email, if applicable. | sender\_xxxxxxxxx |
| confirmFromName | string | Name shown as the sender for the confirmation email. | Support Team |
| confirmFromEmail | string | Email address from which the confirmation email is sent. | [confirm@sendx.io](mailto:confirm@sendx.io) |
| confirmMailSubject | string | Subject line of the confirmation email. | Please confirm your subscription |
| confirmMailMessage | string | Content of the confirmation email. | Click here to confirm! |
| confirmSuccessPage | string | URL of the success page shown after email confirmation. | [https://company.com/success](https://company.com/success) |
| created | string (date-time) | Timestamp when the list was created. | 2025-06-26T05:09:39.485517Z |
| updated | string (date-time) | Timestamp when the list was last updated. | 2025-06-26T05:09:39.485517Z |
| confirmSender | string | Sender ID for the confirmation email, if applicable. | sender\_xxxxxxxx |
| isQuarantined | boolean | Indicates if the list is quarantined. Contact [support@sendx.io](mailto:support@sendx.io) if you encounter this. | false |
## Tag
A Tag in SendX is a versatile tool that allows you to categorize and organize your contacts based on their behaviors, interests, or other attributes. By adding tags to contacts, you can create powerful filters and segments to target specific audiences in your campaigns.
Tags are essential for tracking and understanding your contactsβ journey through your application or business funnel. For instance, if a contact views a product, you can assign a tag like Product X Viewed. Later, you can filter all contacts with this tag to send them personalized follow-up emails or promotional offers. This ability to categorize contacts ensures that your marketing efforts are precise and relevant.
In the world of email marketing, tags are not just a toolβthey are a key utility for creating personalized experiences, improving open rates, and driving higher engagement. By leveraging tags effectively, you can ensure that your contacts receive the right message at the right time.
| **Field** | **Type** | **Description** | **Example** |
| :-------- | :----------------- | :--------------------------------------- | :------------------- |
| id | string | Identifier for the tag. | tag\_xxxxxxxx |
| name | string | Name of the tag. | VIP Customers |
| created | string (Date-Time) | Timestamp when the tag was created. | 2024-10-08T09:30:00Z |
| updated | string (Date-Time) | Timestamp when the tag was last updated. | 2024-10-08T12:45:00Z |
## Campaigns
Campaign is one of the key resources in SendX as an email marketing platform. A campaign allows you to send targeted email messages to specific segments of your audience, helping to engage subscribers, promote products, or share important updates. Why is a Campaign Resource Important? Email campaigns are the cornerstone of email marketing strategies. They help you:
* **Engage Customers:** Send relevant content that resonates with the audience.
* **Automate Communication:** Schedule and automate emails to reach the right people at the right time.
* **Track Performance:** Measure engagement, opens, clicks, and conversions to optimize future campaigns.
\
For example you might create a campaign called "Holiday Discounts" where you target customers who have shown interest in your products over the last three months. The campaign could send personalized emails with special discounts for the holiday season, encouraging recipients to take action.
The Campaign resource in SendX provides you with a powerful toolset to not only communicate with your audience but also to enhance their experience through targeted, automated, and personalized email strategies.
| **Property** | **Type** | **Description** | **Example** |
| :--------------------- | :------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------- |
| id | string | ID of the campaign | campaign\_xxxxxxxx |
| name | string | Name of the campaign | New Year Promotion |
| trackReply | boolean | Indicates if replies to the campaign should be tracked | false |
| status | integer | Current status of the campaign which can have these possible values:
0: Draft
1: Scheduled
2: Sending
3: Sent
4: Quarantined | Scheduled |
| scheduleType | integer | Type of schedule for the campaign
0: Schedule later
1: Send Now
2. Trigger via automation
3. Recurring | 0 |
| scheduleCondition | string | Condition for scheduling the campaign, in case of Send Now this field remains empty. In case of Schedule later, this field denotes the date at which the campaign will be sent in YYYY-MM-DD format | 2024-12-30 |
| timeCondition | string | Condition for scheduling the campaign, in case of Send Now this field remains empty. In case of Schedule later, this field denotes the time at which the campaign will be sent in HH:MM AM/PM format | 9:00 AM |
| timezone | string | Timezone for the scheduled send. See `allowed timezones` for the list of allowed timezones | America/New\_York |
| preferredTimeCondition | string | preferred time condition for the campaign | 9:00 AM |
| preferredTimezone | string | Preferred timezone for sending the campaign | America/Los\_Angeles |
| strategy | string | Strategy for the campaign | Batch sending |
| sendInContactsTimezone | boolean | Indicates if the campaign should be sent in the recipient's timezone | true |
| smartSend | boolean | Indicates if smart sending should be used | false |
| isArchived | boolean | Indicates if the campaign is archived | false |
| sender | string | Unique identifier of the sender of the campaign | sender\_123 |
| campaignScreenshotUrl | string | URL of the campaign's screenshot | [https://example.com/screenshot.png](https://example.com/screenshot.png) |
| includedSegments | array | List of segment IDs that are included in the campaign as receivers | \["segment\_123", "segment\_456"] |
| includedTags | array | List of tag IDs that are included in the campaign as receivers | \["tag\_123", "tag\_456"] |
| includedLists | array | List of list IDs that are included in the campaign as receivers | \["list\_123", "list\_456"] |
| excludedSegments | array | List of segment IDs that are excluded from the campaign as receivers | \["segment\_123", "segment\_456"] |
| excludedTags | array | List of tag IDs that are excluded from the campaign as receivers | \["tag\_123", "tag\_456"] |
| excludedLists | array | List of list IDs that are excluded from the campaign as receivers | \["list\_123", "list\_456"] |
PreferredTimeZone and PreferredTimeCondition can are valid only in cases of SmartSend and SendInContactTimeZones, in case the user data is not available the preferredTimeZone and preferredTimeCondition is used.
# Create sender
Source: https://docs.sendx.io/api-reference/sender/create-sender
post /sender
Adds a new sender email address.
**π― Key Features:**
* Add new sender addresses
* Verify domain ownership before adding senders
* Configure sender names
**π Verification Process for domain ownership:**
1. Create sender with name and email
2. Verification email sent automatically
3. Click verification link in email
4. Sender marked as verified and ready to use
**π Domain Authentication:**
For better deliverability, authenticate your domain:
* Add SPF records
* Configure DKIM signing
* Set up DMARC policy
* Complete domain verification in SendX settings
**π‘ Best Practices:**
* Use real email addresses you have access to
* Maintain consistent sender names for brand recognition
* Regularly check and update inactive senders
* Use role-based addresses sparingly (info@, support@)
**β‘ Pro Tips:**
* Create department-specific senders (sales@, support@, newsletter@)
* Personal senders often have better engagement
* Test sender reputation regularly
# Get all senders
Source: https://docs.sendx.io/api-reference/sender/get-all-senders
get /sender
Retrieves all verified sender addresses.
**π Response includes:**
* Sender ID
* Sender name
* Email address
* isWhitelisted
**π Sender States:**
* false : Pending
* true : Verified
**π‘ Use this endpoint to:**
* Build sender selection dropdowns
* Monitor verification status
* Audit sender inventory
* Check domain authentication
# Create tag
Source: https://docs.sendx.io/api-reference/tag/create-tag
post /tag
Creates a new tag for contact categorization.
**π― Purpose:**
Tags provide flexible contact categorization beyond traditional lists, enabling:
* Dynamic segmentation based on behavior
* Multi-dimensional contact grouping
* Temporary or permanent categorization
* Cross-team tag sharing (with isShareable flag)
**π‘ Use Cases:**
* Customer lifecycle stages (lead, prospect, customer, VIP)
* Behavioral tags (engaged, inactive, power-user)
* Product interests (feature-A-user, beta-tester)
* Event attendance (webinar-2024-Q1, conference-attendee)
**π Tag Assignment:**
Tags can be assigned to contacts through:
* API calls (contact creation/update)
* Automation workflows
* Manual bulk actions
* Import operations
**β‘ Best Practices:**
* Use descriptive tag names
* Establish naming conventions
* Regularly review and clean up unused tags
* Consider tag hierarchies for complex segmentation
# Delete tag
Source: https://docs.sendx.io/api-reference/tag/delete-tag
delete /tag/{identifier}
Deletes a tag from the system.
# Get all tags
Source: https://docs.sendx.io/api-reference/tag/get-all-tags
get /tag
Retrieves all tags in your team.
# Get tag by ID
Source: https://docs.sendx.io/api-reference/tag/get-tag-by-id
get /tag/{identifier}
Retrieves detailed information about a specific tag.
# Update tag
Source: https://docs.sendx.io/api-reference/tag/update-tag
put /tag/{identifier}
Updates an existing tag's name.
# Get all team members
Source: https://docs.sendx.io/api-reference/team-member/get-all-team-member
get /team/member
Retrieves all team members.
# Get a team member by ID
Source: https://docs.sendx.io/api-reference/team-member/get-team-member
get /team/member/{identifier}
Retrieves a single team member by their unique identifier.
# Create email template
Source: https://docs.sendx.io/api-reference/template/create-email-template
post /template/email
Creates a new reusable email template.
**π― Key Features:**
* HTML and text versions
* Personalization variables
* Reusable across campaigns
* Template versioning
**π¨ Editor-Specific Features:**
* **PlainText (0):** Basic text formatting, fast loading
* **DragDrop (1):** Visual components, responsive design using the bee editor
* **SendxEditor (2):** TipTap editor with advanced features like drag & drop, image upload, and more
**β¨ Template Benefits:**
* Reusable email designs
* Consistent branding across campaigns
# Delete template
Source: https://docs.sendx.io/api-reference/template/delete-template
delete /template/email/{identifier}
Deletes an email template.
**β οΈ Deletion Safeguards:**
* Templates used in active campaigns cannot be deleted
* Templates used in scheduled campaigns are protected
* Deletion is permanent and cannot be undone
**π Safety Checks:**
* Checks for campaign dependencies
* Validates template is not system/default template
* Confirms template is not shared with other teams
**π‘ Alternative Actions:**
* Duplicate and modify for similar use cases
* Export template before deletion for backup
# Get all templates
Source: https://docs.sendx.io/api-reference/template/get-all-templates
get /template/email
Retrieves all email templates.
# Get template by ID
Source: https://docs.sendx.io/api-reference/template/get-template-by-id
get /template/email/{identifier}
Retrieves a specific email template.
**π§ Template Details Include:**
* Complete HTML and template code
* Editor type and capabilities
* Template preview and thumbnail
**π§ Developer Integration:**
* Use for template preview in campaign builder
* Load template for editing/duplication
* Access template metadata for UI display
**π― Common Use Cases:**
* Campaign template selection
* Template editing interface
* Template preview modal
* Template duplication workflow
# Update template
Source: https://docs.sendx.io/api-reference/template/update-template
put /template/email/{identifier}
Updates an existing email template.
**π§ Update Capabilities:**
* Modify template name and content
* Change HTML code and template structure
* Update editor type (with validation)
**β οΈ Important Considerations:**
* Editor type changes may affect template compatibility
* Active campaigns using this template will use cached version
* Thumbnails are regenerated automatically
**π― Common Update Scenarios:**
* Fix template bugs or styling issues
* Update branding or design elements
* Add new template variables or sections
* Optimize template for mobile devices
# Create webhook
Source: https://docs.sendx.io/api-reference/webhook/create-webhook
post /webhook
Creates a new webhook for event notifications.
**π― Purpose:**
Webhooks enable real-time integration with external systems by sending HTTP POST requests when specific events occur:
* Contact lifecycle events
* Email engagement tracking
* Campaign performance updates
* List subscription changes
**π Event Types:**
* **contactCreated**: New contact added to system
* **unsubscribed**: Contact opted out
* **dropped**: Email dropped (invalid address)
* **bounced**: Email bounced (hard/soft)
* **markedSpam**: Contact marked email as spam
* **clicked**: Contact clicked a link
* **opened**: Contact opened an email
**β‘ Best Practices:**
* Use HTTPS endpoints for security
* Implement webhook signature verification
* Respond quickly (\< 5 seconds)
* Handle retries gracefully
* Log webhook payloads for debugging
# Delete webhook
Source: https://docs.sendx.io/api-reference/webhook/delete-webhook
delete /webhook/{identifier}
Deletes a webhook configuration.
**π― Key Features:**
- Remove webhooks
- Stop event delivery
- Clean up endpoints
# Get all webhooks
Source: https://docs.sendx.io/api-reference/webhook/get-all-webhooks
get /webhook
Retrieves all configured webhooks.
**π Response includes:**
* Webhook ID with prefix
* Endpoint URL
* Enabled status
* Event subscriptions
* Creation timestamp
# Get webhook by ID
Source: https://docs.sendx.io/api-reference/webhook/get-webhook-by-id
get /webhook/{identifier}
Retrieves details about a specific webhook.
# SendX Webhook Object
Source: https://docs.sendx.io/api-reference/webhook/sendx-webhook-object
webhook SendXWebhooks
SendX webhooks allow you to receive real-time notifications about various events in your team. Every event generated as a SendX webhook will include a type field in the event object that identifies the type of event that occurred.
| **Webhook Event** | **Type Field Value** |
| ------------------------ | -------------------- |
| **Contact Events** | |
| ContactCreated | 74 |
| GlobalUnsubscribe | 73 |
| **Mail Opened Events** | |
| MailOpen (Campaign) | 7 |
| DripStepMailOpen | 32 |
| RssExecMailOpen | 172 |
| WorkflowEmailMailOpen | 189 |
| SeedContactMailOpen | 271 |
| **Link Clicked Events** | |
| LinkClick (Campaign) | 8 |
| DripStepLinkClick | 33 |
| RssExecLinkClick | 173 |
| WorkflowEmailLinkClick | 190 |
| SeedContactLinkClick | 272 |
| **Mail Bounced Events** | |
| MailBounced (Campaign) | 5 |
| DripStepMailBounced | 63 |
| RssExecMailBounced | 180 |
| WorkflowEmailMailBounced | 197 |
| SeedContactMailBounced | 276 |
| **Mail Spam Events** | |
| MailSpam (Campaign) | 6 |
| DripStepMailSpam | 62 |
| RssExecMailSpam | 179 |
| WorkflowEmailMailSpam | 196 |
| SeedContactMailSpam | 275 |
| **Mail Dropped Events** | |
| MailDropped (Campaign) | 60 |
| DripStepMailDropped | 61 |
| RssExecMailDropped | 178 |
| WorkflowEmailMailDropped | 195 |
| SeedContactMailDropped | 278 |
# Update webhook
Source: https://docs.sendx.io/api-reference/webhook/update-webhook
put /webhook/{identifier}
Updates webhook configuration.
**π Updatable fields:**
* Endpoint URL
* Enabled/disabled status
* Event subscriptions
**β οΈ Important:**
* URL changes take effect immediately
* Disabling pauses all deliveries
* Event changes apply to future events only
**π‘ Common Updates:**
* Change endpoint URL
* Enable/disable specific events
* Temporarily pause webhook
* Add new event types
# Verifying SendX Webhook
Source: https://docs.sendx.io/api-reference/webhook/verify-webhook
Making sure your webhooks come from the correct source
When SendX sends webhooks to your endpoint, we include a secure **HMAC-SHA256 signature**. This allows you to verify that the webhook truly came from SendX and that the payload hasnβt been altered in transit.
This article explains how SendX signs webhook requests and how you can verify them in your own server β with ready-to-use examples in **Python** and **Node.js**.
## Why Signature Verification Matters
Webhook signature verification ensures:
* β
The request is **authentic** (it came from SendX).
* β
The payload **has not been altered** during transmission.
* β
You can safely process the event data without risk of spoofing.
## How SendX Signs Webhooks
Every webhook request sent from SendX includes a **cryptographic signature** in its HTTP headers.
Hereβs how the signature is generated:
1. The webhook payload (JSON body) is taken as-is.
2. SendX computes an **HMAC-SHA256** hash of this body using your teamβs unique **API key** as the secret.
3. The result is hex-encoded and added to the request headers.
Example request headers:
```
Content-Type: application/json
X-SendX-Signature: 3e7bda1d2d3c74b5f8a5ce5e7e7efef2df...
X-SendX-Signature-Alg: hmac-sha256
X-SendX-Webhook-Id: 4b1b3f72-8e01-43aa-9cf9-5dc6a8e4e937
X-SendX-Webhook-Attempt: 1
```
## How to Verify a Webhook on Your Server
When your server receives a webhook from SendX:
1. **Capture the raw body** of the POST request (without parsing it).
2. Retrieve the following headers:
* `X-SendX-Signature`
* `X-SendX-Signature-Alg`
3. Recompute the HMAC using your **SendX Team API Key**.
4. Compare the recomputed signature with the one in the header using a constant-time comparison.
If they match β the webhook is valid.
### Example: Verification Script
```python Python theme={null}
import hmac
import hashlib
from flask import Flask, request, jsonify
app = Flask(__name__)
# Replace with your actual Team API Key
TEAM_API_KEY = "YOUR_TEAM_API_KEY_HERE"
@app.route("/webhook", methods=["POST"])
def verify_webhook():
raw_body = request.data
received_sig = request.headers.get("x-sendx-signature", "")
algo = request.headers.get("x-sendx-signature-alg", "")
if algo.lower() != "hmac-sha256":
return jsonify({"error": "unsupported signature algorithm"}), 400
computed_sig = hmac.new(
TEAM_API_KEY.encode("utf-8"),
raw_body,
hashlib.sha256
).hexdigest()
if hmac.compare_digest(computed_sig, received_sig):
print("β
Webhook signature verified successfully!")
return jsonify({"verified": True}), 200
else:
print("β Invalid webhook signature!")
return jsonify({"verified": False}), 400
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
```
```javascript JavaScript theme={null}
import express from 'express';
import crypto from 'crypto';
const app = express();
// Use raw body middleware to get exact payload (important!)
app.use(express.raw({ type: 'application/json' }));
const SENDX_API_KEY = 'your_team_api_key_here';
function verifySignature(payload, headerSignature) {
const computedSignature = crypto
.createHmac('sha256', SENDX_API_KEY)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(computedSignature),
Buffer.from(headerSignature)
);
}
app.post('/webhook', (req, res) => {
const signature = req.headers['x-sendx-signature'];
const payload = req.body;
if (!signature) {
return res.status(400).json({ error: 'Missing signature header' });
}
if (!verifySignature(payload, signature)) {
return res.status(401).json({ error: 'Invalid signature' });
}
const data = JSON.parse(payload);
console.log('β
Verified webhook:', data);
res.status(200).json({ status: 'success' });
});
app.listen(5000, () => console.log('Webhook listener running on port 5000'));
```
### Common Issues & Fixes
| **Issue** | **Possible Cause** | **Solution** |
| :-------------------------------- | :------------------------------------------ | :------------------------------------------------------------------------------- |
| Invalid Signature | Payload was modified or encoded incorrectly | Make sure to use the **raw request body**, not a parsed or re-serialized version |
| Missing header | Endpoint not receiving all headers | Ensure your reverse proxy or framework doesnβt strip custom headers |
| Verification fails intermittently | Using the wrong API Key | Confirm youβre using your **Team API Key**, not a personal or project key |
# Create Your First Contact
Source: https://docs.sendx.io/getting-started/create-contact
Start adding customers to your SendX account
## Welcome to SendX
This quick start guide will help you:
* Set up your SendX account
* Identify your first contact using the REST API
* Get ready to send your first email
Let's dive in!
## 1. Set Up Your SendX Account
Start by creating a SendX account if you havenβt already:
[Create Account β](https://app.sendx.io/register)
After registering, log in and navigate to:
**`Settings β API & Webhooks β Copy your Team API Key`**
This key is required for all API interactions. Keep it safe and never expose it in public code repositories.
## 2. Identify a Contact
Use the `identify` method of the SendX REST API to start adding your contacts to the SendX App, this would allow you to send email to that contact later:
```bash cURL theme={null}
curl --request POST \
--url https://api.sendx.io/api/v1/rest/contact/identify \
--header 'Content-Type: application/json' \
--header 'X-Team-ApiKey: ' \
--data '{
"firstName": "John",
"lastName": "Doe",
"email": "user@example.com",
"newEmail": "user@example.com",
"company": "Acme Inc.",
"tags": [
"new",
"cool"
],
"customFields": {
"favorite_color": "blue",
"favorite_food": "pizza"
}
}'
```
```python Python theme={null}
import requests
url = "https://api.sendx.io/api/v1/rest/contact/identify"
payload = {
"firstName": "John",
"lastName": "Doe",
"email": "user@example.com",
"newEmail": "user@example.com",
"company": "Acme Inc.",
"tags": ["new", "cool"],
"customFields": {
"favorite_color": "blue",
"favorite_food": "pizza"
}
}
headers = {
"X-Team-ApiKey": "",
"Content-Type": "application/json"
}
response = requests.request("POST", url, json=payload, headers=headers)
print(response.text)
```
```Go Golang theme={null}
package main
import (
"fmt"
"strings"
"net/http"
"io/ioutil"
)
func main() {
url := "https://api.sendx.io/api/v1/rest/contact/identify"
payload := strings.NewReader("{\n \"firstName\": \"John\",\n \"lastName\": \"Doe\",\n \"email\": \"user@example.com\",\n \"newEmail\": \"user@example.com\",\n \"company\": \"Acme Inc.\",\n \"tags\": [\n \"new\",\n \"cool\"\n ],\n \"customFields\": {\n \"favorite_color\": \"blue\",\n \"favorite_food\": \"pizza\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Team-ApiKey", "")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
fmt.Println(res)
fmt.Println(string(body))
}
```
```java Java theme={null}
HttpResponse response = Unirest.post("https://api.sendx.io/api/v1/rest/contact/identify")
.header("X-Team-ApiKey", "")
.header("Content-Type", "application/json")
.body("{\n \"firstName\": \"John\",\n \"lastName\": \"Doe\",\n \"email\": \"user@example.com\",\n \"newEmail\": \"user@example.com\",\n \"company\": \"Acme Inc.\",\n \"tags\": [\n \"new\",\n \"cool\"\n ],\n \"customFields\": {\n \"favorite_color\": \"blue\",\n \"favorite_food\": \"pizza\"\n }\n}")
.asString();
```
```java Java theme={null}
HttpResponse response = Unirest.post("https://api.sendx.io/api/v1/rest/contact/identify")
.header("X-Team-ApiKey", "")
.header("Content-Type", "application/json")
.body("{\n \"firstName\": \"John\",\n \"lastName\": \"Doe\",\n \"email\": \"user@example.com\",\n \"newEmail\": \"user@example.com\",\n \"company\": \"Acme Inc.\",\n \"tags\": [\n \"new\",\n \"cool\"\n ],\n \"customFields\": {\n \"favorite_color\": \"blue\",\n \"favorite_food\": \"pizza\"\n }\n}")
.asString();
```
This would create a new contact with the following details:
```
First Name: John
Last Name: Doe
Email: user@example.com
New Email: user@example.com
Company: Acme Inc.
Tags: new, cool
Custom Fields: favorite_color: blue, favorite_food: pizza
```
For more details on the `identify` method, check out the API reference.
Once you have identified your contact, you can start sending emails to them.
## Next Steps
Once your contact is identified, you can start sending emails to them using the SendX API.
### Want to go further?
* Send transactional emails
* Run campaigns and newsletters
* Segment contacts with tags and custom fields
Explore everything in our [API Reference](/api-reference/introduction).
# Record Your First Custom Event
Source: https://docs.sendx.io/getting-started/custom-event
Track user actions by pushing custom events to SendX
## Track Your First Custom Event
Custom events allow you to record specific actions your contacts take β like abandoning a cart or making a purchase β and associate those actions with additional metadata.
This guide walks you through sending your first custom event using the SendX REST API.
## 1. Prerequisites
Before you begin:
* [Create a SendX account](https://app.sendx.io/register)
* [Create a contact](/guides/contacts/create-your-first-contact) (events must be associated with a contact)
* Get your **Team API Key** from\
**`Settings β API & Webhooks β Team API Key`**
Your API Key is required for authentication. Keep it private and secure.
## 2. Push a Custom Event
Use the `/events/custom` endpoint to track a user action with optional metadata.
```bash cURL theme={null}
curl --request POST \
--url https://api.sendx.io/api/v1/rest/events/custom \
--header 'Content-Type: application/json' \
--header 'X-Team-ApiKey: ' \
--data '{
"name": "abandoned_cart",
"identifier": "john.doe@example.com",
"data": {
"price": "29.99",
"currency": "USD",
"item_count": "3"
},
"time": 1669990400
}'
```
```python Python theme={null}
import requests
url = "https://api.sendx.io/api/v1/rest/events/custom"
payload = {
"name": "abandoned_cart",
"identifier": "john.doe@example.com",
"data": {
"price": "29.99",
"currency": "USD",
"item_count": "3"
},
"time": 1669990400 # Optional: Unix timestamp in seconds
}
headers = {
"X-Team-ApiKey": "",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)
```
```go Golang theme={null}
package main
import (
"fmt"
"strings"
"net/http"
"io/ioutil"
)
func main() {
url := "https://api.sendx.io/api/v1/rest/events/custom"
payload := strings.NewReader(`{
"name": "abandoned_cart",
"identifier": "john.doe@example.com",
"data": {
"price": "29.99",
"currency": "USD",
"item_count": "3"
},
"time": 1669990400
}`)
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Team-ApiKey", "")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
HttpResponse response = Unirest.post("https://api.sendx.io/api/v1/rest/events/custom")
.header("X-Team-ApiKey", "")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"abandoned_cart\",\n \"identifier\": \"john.doe@example.com\",\n \"data\": {\n \"price\": \"29.99\",\n \"currency\": \"USD\",\n \"item_count\": \"3\"\n },\n \"time\": 1669990400\n}")
.asString();
```
### What This Does
This request records an event named `abandoned_cart` for the contact `john.doe@example.com`, along with additional metadata:
* **price:** 29.99
* **currency:** USD
* **item\_count:** 3
* **time:** 1669990400 (optional - if omitted, server will use current time)
Learn more about how to track custom events with additional data.
## 3. Next Steps
Once you've recorded events, you can:
* Segment contacts based on event properties
* Trigger automations using event names
* Analyze custom events in your dashboard
* Explore the full API Reference to see whatβs possible.
# Send Email
Source: https://docs.sendx.io/getting-started/send-email
Use the SendX API to send transactional emails with personalization, custom headers, and tracking.
## Send Email
Use this endpoint to send transactional emails to specified recipients with support for personalization, attachments, and tracking.
The API returns **202 Accepted** when your email is queued for delivery. Actual sending happens in the background. A 202 response means your request was acceptedβit does not guarantee delivery. Per-recipient status is not returned in the response.
### Endpoint
`POST https://api.sendx.io/api/v1/rest/send/email`
### Headers
| Header | Value | Required | Description |
| --------------------- | ------------------- | -------- | ----------------------------------- |
| Content-Type | `application/json` | Yes | Request body format |
| X-Team-ApiKey | `YOUR_API_KEY` | Yes | Your SendX Team API key |
| List-Unsubscribe | `mailto:...` or URL | No | Passed through for list-unsubscribe |
| X-SendPost-Mock-Email | `true` | No | Mock send (if supported) |
### Request Body
| Field | Type | Required | Description |
| ---------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `from` | object | Yes | Sender info. Must include `email` (string). Optionally include `name`. If the sending domain is whitelisted (verified), any address at that domain and any display name can be used. |
| `to` | array | Yes | Array of recipients. Each must include `email`. Optionally `name` and `customFields` (key-value pairs). |
| `replyTo` | object | No | Reply-to address. Includes `email` and optionally `name`. |
| `subject` | string | Yes | Email subject line. |
| `htmlBody` | string | Yes | HTML content of the email. |
| `textBody` | string | No | Plain text fallback content. |
| `headers` | object | No | Custom headers as key-value pairs. These are passed through in webhook events. |
**Sender and domain whitelisting:** If a sending domain is whitelisted (verified) in SendX, you can use any `from` email address at that domain and any display `name`. For example, with domain `example.com` verified, both `support@example.com` and `orders@example.com` are valid, with any name.
### Example Request
```bash theme={null}
curl --request POST \
--url https://api.sendx.io/api/v1/rest/send/email \
--header 'Content-Type: application/json' \
--header 'X-Team-ApiKey: ' \
--data '{
"from": {
"email": "support@example.com",
"name": "Support Team"
},
"to": [
{
"email": "jane@example.com",
"name": "Jane Doe",
"customFields": {
"order_id": "A12345"
}
}
],
"replyTo": {
"email": "reply@example.com",
"name": "Reply Name"
},
"subject": "Your Order Confirmation",
"htmlBody": "Hi Jane!
Your order {{order_id}} has been confirmed.
",
"textBody": "Hi Jane! Your order {{order_id}} has been confirmed.",
"headers": {
"X-Custom-Header": "Value"
}
}'
```
### Success Response (202 Accepted)
When all validations pass and the message is successfully queued for delivery:
```json theme={null}
{
"status": "success",
"message": "Email queued for delivery"
}
```
| Field | Type | Description |
| --------- | ------ | ----------------------------- |
| `status` | string | `"success"` |
| `message` | string | `"Email queued for delivery"` |
**Note:** Delivery happens in the background. A 202 does not guarantee delivery. We automatically retry failed sends. You can check delivery status in your SendX dashboard.
### Error Response Format
All error responses use the same JSON shape:
```json theme={null}
{
"status": "error",
"message": ""
}
```
The HTTP status code varies by scenario. Use the exact `message` values below for debugging and programmatic handling.
### Error Scenarios (POST /send/email)
| HTTP Status | Scenario | Response `message` |
| ----------- | ------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| **400** | No recipients | `"no recipients specified"` |
| **400** | From email missing | `"from email is required"` |
| **400** | From email invalid format | `"from email must be a valid email address"` |
| **400** | From email has no valid domain | `"invalid from email domain"` or `"from email must be a valid email address"` |
| **400** | Sender domain not whitelisted | `"From email not whitelisted. Please add and verify the domain first."` |
| **400** | Transactional add-on not active | `"Transactional email add-on is not active. Please activate it first at https://app.sendx.io/setting/addons."` |
| **400** | At least one recipient has invalid email format | `"Invalid recipient email address: invalid email format"` |
| **401** | Missing or invalid team API key | `"The Team ID or API Key specified is not valid"` |
| **422** | Request body is not valid JSON or does not match schema | `"invalid request body"` |
| **429** | Account email limit reached (zero remaining) | `"Account email sending limit exceeded. Please upgrade your plan."` |
| **429** | Recipient count exceeds remaining account limit | `"Account email sending limit exceeded. Current api has {N} contacts, but only {M} emails can be sent."` |
| **429** | Recipient count exceeds contact limit | `"Contact limit exceeded. Current api has {N} contacts, but only {M} emails can be sent."` |
| **500** | Server error | `"error getting account email sending status"` |
| **500** | Server error | `"error getting team add-on"` |
| **500** | Server error | `"error while retrieving domains"` |
| **500** | Server error | `"Error unmarshalling team add-on setting"` |
| **500** | Server error | `"Error getting default provider"` |
| **500** | Server error | `"Failed to prepare email payload"` |
| **500** | Server error | `"Failed to queue email for delivery"` |
### Debugging Error Responses
| If you see... | Likely cause | What to do |
| ------------------------------------------------------- | ----------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `no recipients specified` | `to` array is empty or missing | Ensure `to` has at least one recipient with a valid `email`. |
| `from email is required` | `from.email` is missing | Include `from.email` in the request body. |
| `from email must be a valid email address` | `from.email` format invalid or domain malformed | Use a valid email format (e.g. `user@domain.com`). |
| `invalid from email domain` | `from` has no valid domain | Use a properly formatted email with a valid domain. |
| `From email not whitelisted...` | Sender domain not verified | Add and verify the domain in SendX Settings. |
| `Transactional email add-on is not active` | Add-on not enabled | Activate the transactional add-on at [https://app.sendx.io/setting/addons](https://app.sendx.io/setting/addons). |
| `Invalid recipient email address: invalid email format` | One or more `to` emails are invalid | Validate each recipient email format. |
| `The Team ID or API Key specified is not valid` | Missing or invalid `X-Team-ApiKey` | Check your API key in SendX Settings β Team API Key. |
| `invalid request body` | Invalid request format | Ensure the body is valid JSON and includes all required fields (from, to, subject, htmlBody). |
| `Account email sending limit exceeded...` | Plan limit reached | Upgrade your plan or wait for the limit to reset. |
| `Contact limit exceeded...` | Recipient count exceeds contact limit | Reduce the number of recipients or upgrade. |
| `error getting account email sending status` | Temporary server issue | Retry later; if it persists, contact support. |
| `error getting team add-on` | Temporary server issue | Retry later; if it persists, contact support. |
| `error while retrieving domains` | Temporary server issue | Retry later; if it persists, contact support. |
| `Error unmarshalling team add-on setting` | Temporary server issue | Retry later; if it persists, contact support. |
| `Error getting default provider` | Configuration issue | Check SendX settings; contact support if needed. |
| `Failed to prepare email payload` | Temporary server issue | Retry; if it persists, contact support. |
| `Failed to queue email for delivery` | Temporary server issue | Retry; if it persists, contact support. |
# Send Email With Template
Source: https://docs.sendx.io/getting-started/send-email-with-template
Send emails using pre-defined templates in SendX with variable substitution and tracking.
## Send Email With Template
Use this endpoint to send transactional emails using a pre-defined template in SendX with variable substitution.
The API returns **202 Accepted** when your email is queued for delivery. Actual sending happens in the background. A 202 response means your request was acceptedβit does not guarantee delivery. Per-recipient status is not returned in the response.
### Endpoint
`POST https://api.sendx.io/api/v1/rest/send/template`
### Headers
| Header | Value | Required | Description |
| --------------------- | ------------------- | -------- | ----------------------------------- |
| Content-Type | `application/json` | Yes | Request body format |
| X-Team-ApiKey | `YOUR_API_KEY` | Yes | Your SendX Team API key |
| List-Unsubscribe | `mailto:...` or URL | No | Passed through for list-unsubscribe |
| X-SendPost-Mock-Email | `true` | No | Mock send (if supported) |
### Request Body
| Field | Type | Required | Description |
| ---------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `from` | object | Yes | Sender info. Must include `email` (string). Optionally include `name`. If the sending domain is whitelisted (verified), any address at that domain and any display name can be used. |
| `to` | array | Yes | Array of recipients. Each must include `email`. Optionally `name` and `customFields` (key-value pairs used for personalization β see [Personalization & Merge Tags](/api-reference/email-sending/personalization)). |
| `replyTo` | object | No | Reply-to address. Includes `email` and optionally `name`. |
| `subject` | string | Yes | Override the template's default subject line. |
| `template` | string | Yes | Template identifier (e.g. `template_f3lJvTEhSjKGVb5Lwc5SWS`). |
**Sender and domain whitelisting:** If a sending domain is whitelisted (verified) in SendX, you can use any `from` email address at that domain and any display `name`. For example, with domain `example.com` verified, both `support@example.com` and `orders@example.com` are valid, with any name.
### Example Request
```bash theme={null}
curl -X POST "https://api.sendx.io/api/v1/rest/send/template" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{ \
"from": { \
"email": "support@example.com" \
}, \
"to": [ \
{ \
"email": "user@example.com", \
"customFields": { \
"first_name": "Jane", \
"order_id": "A12345" \
} \
} \
], \
"template": "order-confirmation-template",
"headers": {
"X-Campaign": "order-confirmation",
"List-ID": "template-orders"
},
"trackClicks": true,
"trackOpens": true
}'
```
### Success Response (202 Accepted)
When all validations pass and the message is successfully queued for delivery:
```json theme={null}
{
"status": "success",
"message": "Email queued for delivery"
}
```
| Field | Type | Description |
| --------- | ------ | ----------------------------- |
| `status` | string | `"success"` |
| `message` | string | `"Email queued for delivery"` |
**Note:** Delivery happens in the background. A 202 does not guarantee delivery. We automatically retry failed sends. You can check delivery status in your SendX dashboard.
### Error Response Format
All error responses use the same JSON shape:
```json theme={null}
{
"status": "error",
"message": ""
}
```
The HTTP status code varies by scenario. Use the exact `message` values below for debugging and programmatic handling.
### Error Scenarios (POST /send/template)
Same as **POST /send/email**, plus the following template-specific scenarios:
| HTTP Status | Scenario | Response `message` |
| ----------- | --------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| **202** | Request valid; email queued | `"Email queued for delivery"` (with `"status": "success"`) |
| **400** | No recipients | `"no recipients specified"` |
| **400** | From email missing | `"from email is required"` |
| **400** | From email invalid format | `"from email must be a valid email address"` |
| **400** | Invalid from domain | `"invalid from email domain"` or `"from email must be a valid email address"` |
| **400** | Sender domain not whitelisted | `"From email not whitelisted. Please add and verify the domain first."` |
| **400** | Transactional add-on not active | `"Transactional email add-on is not active. Please activate it first at https://app.sendx.io/setting/addons."` |
| **400** | Template not found, invalid, or missing | `"Template does not exist: template not found or invalid template id"` |
| **400** | Recipient email empty | `"Invalid recipient email address: recipient email is required"` |
| **400** | Recipient email invalid format | `"Invalid recipient email address: invalid email format"` |
| **401** | Missing or invalid team API key | `"The Team ID or API Key specified is not valid"` |
| **422** | Invalid request body | `"invalid request body"` |
| **429** | Sending limit exceeded | Same messages as POST /send/email |
| **500** | Server error | Same messages as POST /send/email |
### Debugging Error Responses
| If you see... | Likely cause | What to do |
| -------------------------------------------------------------------- | ------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `no recipients specified` | `to` array is empty or missing | Ensure `to` has at least one recipient with a valid `email`. |
| `from email is required` | `from.email` is missing | Include `from.email` in the request body. |
| `from email must be a valid email address` | `from.email` format is invalid | Use a valid email format (e.g. `user@domain.com`). |
| `invalid from email domain` | `from` has no valid domain | Use a properly formatted email with a valid domain. |
| `From email not whitelisted...` | Sender domain not verified | Add and verify the domain in SendX Settings. |
| `Transactional email add-on is not active` | Add-on not enabled | Activate the transactional add-on at [https://app.sendx.io/setting/addons](https://app.sendx.io/setting/addons). |
| `Template does not exist: template not found or invalid template id` | Template ID invalid, missing, or template deleted | Verify the template identifier (e.g. `template_f3lJvTEhSjKGVb5Lwc5SWS`) exists in your account. |
| `Invalid recipient email address: recipient email is required` | A recipient has empty email | Ensure each `to` item has a non-empty `email` field. |
| `Invalid recipient email address: invalid email format` | One or more `to` emails are invalid | Validate each recipient email format. |
| `The Team ID or API Key specified is not valid` | Missing or invalid `X-Team-ApiKey` | Check your API key in SendX Settings β Team API Key. |
| `invalid request body` | Invalid request format | Ensure the body is valid JSON and includes all required fields (from, to, subject, template). |
| `Account email sending limit exceeded...` | Plan limit reached | Upgrade your plan or wait for the limit to reset. |
| `Contact limit exceeded...` | Recipient count exceeds contact limit | Reduce the number of recipients or upgrade. |
| 5xx server errors | Temporary server issues | Retry later; if they persist, contact support. |
# Introduction
Source: https://docs.sendx.io/index
Welcome to SendX API Documentation.
You can use SendX API to automate all aspects of email marketing and marketing automation.
Common use-cases include:
* Adding contacts with custom data and tags
* Push custom events or revenue event for a contact
* Sending transactional emails
Note that you can use the contact custom data pushed for personalisation and segmentation of your audience. You can use custom events to trigger visual workflows or automation rules.
Advanced use-cases include:
* Creating and scheduling dynamic email campaigns
* Consuming webhooks and campaign reports to craft custom dashboards
## Getting Started
Add contact, push custom event and send your first email
Integrate and scale using our API SDKs.
## SDKs
We have native SDKs in different programming languages such as Javascript, Python, Ruby, Golang, Java and PHP.
You can integrate with them or create your own SDK with our API specification. In case you need any assistance with respect to API then do reach out to our team from website chat or email us at [hello@sendx.io](mailto:hello@sendx.io)
# Introduction
Source: https://docs.sendx.io/quickstart/golang-sdk
Learn how to configure and add your first contact with SendX golang SDK
## Prerequisites
To get the most out of this guide, youβll need to:
* [**Create a SendX Account**](https://app.sendx.io/register)
* [**Install GoLang >v1.19.0**](https://go.dev/doc/install)
## 1. Install
```shellscript Shell theme={null}
go get github.com/sendx/sendx-go-sdk
```
## 2. Getting Started
```go Go theme={null}
package main
import (
"context"
"fmt"
"os"
sendx "github.com/sendx/sendx-go-sdk"
)
func main() {
ctx := context.WithValue(
context.Background(),
sendx.ContextAPIKeys,
map[string]sendx.APIKey{
"apiKeyAuth": {Key: "YOUR_API_KEY"},
},
)
contactRequest := *sendx.NewContactRequest() // ContactRequest |
contactRequest.Email = sendx.PtrString("jane@doe.com")
contactRequest.FirstName = sendx.PtrString("Jane")
contactRequest.LastName = sendx.PtrString("Doe")
contactRequest.Company = sendx.PtrString("Tech Solutions Inc.")
contactRequest.LastTrackedIp = sendx.PtrString("34.94.159.140")
contactRequest.CustomFields = &map[string]string{"K2mxBVReqBhbwx9e0ItSea": "VIP", "7o3Tl1aY2yKp2X1aflRjOL": "Special Offer Subscriber"}
contactRequest.Lists = []string{"1244"}
contactRequest.Tags = []string{"MKdhTovsTJDetCyrJmRySL"}
configuration := sendx.NewConfiguration()
apiClient := sendx.NewAPIClient(configuration)
resp, r, err := apiClient.ContactAPI.CreateContact(ctx).ContactRequest(contactRequest).Execute()
if err != nil {
fmt.Fprintf(os.Stderr, "Error when calling `ContactAPI.CreateContact``: %v\n", err)
fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r)
}
// response from `CreateContact`: Response
fmt.Fprintf(os.Stdout, "Response from `ContactAPI.CreateContact`: %v\n", resp)
}
```
## 3. Try it for yourself
See detailed sdk example
# Introduction
Source: https://docs.sendx.io/quickstart/java-sdk
Learn how to configure and add your first contact with SendX Java SDK
## Prerequisites
To get the most out of this guide, youβll need to:
* [**Create a SendX Account**](https://app.sendx.io/register)
* [Install Java 1.8+](https://www.oracle.com/java/technologies/downloads/?er=221886)
* [Install Maven (3.8.3+)/Gradle (7.2+)](https://maven.apache.org/download.cgi)
## 1. Install
To install the API client library to your local Maven repository, simply execute:
```shell shell theme={null}
mvn clean install
```
To deploy it to a remote Maven repository instead, configure the settings of the repository and execute:
```shell shell theme={null}
mvn clean deploy
```
### Maven users
Add this dependency to your project's POM:
```xml POM theme={null}
io.sendx
sendx-java-sdk
1.0.1
compile
```
### Gradle users
Add this dependency to your project's build file:
```groovy theme={null}
repositories {
mavenCentral()
mavenLocal()
dependencies {
implementation "io.sendx:sendx-java-sdk:1.0.1"
}
```
### Others
At first generate the JAR by executing:
```shell theme={null}
mvn clean package
```
Then manually install the following JARs:
* `target/sendx-java-sdk-1.0.1.jar`
* `target/lib/*.jar`
## 2. Getting Started
```java Java theme={null}
// Import classes:
import sendx_java_sdk.ApiClient;
import sendx_java_sdk.ApiException;
import sendx_java_sdk.Configuration;
import sendx_java_sdk.auth.*;
import sendx_java_sdk.models.*;
import sendx_java_sdk.CampaignApi;
public class Example {
public static void main(String[] args) {
ApiClient defaultClient = Configuration.getDefaultApiClient();
defaultClient.setBasePath("https://api.sendx.io/api/v1/rest");
// Configure API key authorization: apiKeyAuth
ApiKeyAuth apiKeyAuth = (ApiKeyAuth) defaultClient.getAuthentication("apiKeyAuth");
apiKeyAuth.setApiKey("YOUR API KEY");
// Uncomment the following line to set a prefix for the API key, e.g. "Token" (defaults to null)
//apiKeyAuth.setApiKeyPrefix("Token");
ContactApi apiInstance = new ContactApi(defaultClient);
ContactRequest contactRequest = new ContactRequest(); // ContactRequest |
contactRequest.setFirstName("John")
contactRequest.setLastName("Doe")
contactRequest.setEmail("john.doe@sendx.io")
contactRequest.setCompany("SendX")
contactRequest.setLastTrackedIp("32.342.12.322")
// Set tags as a list of strings
List tags = Arrays.asList("sner1jin3ij34b4", "234bjk2n42ednj32";
contactRequest.setTags(tags)
try {
OperationResponse result = apiInstance.createContact(contactRequest);
System.out.println(result);
} catch (ApiException e) {
System.err.println("Exception when calling CampaignApi#createCampaign");
System.err.println("Status code: " + e.getCode());
System.err.println("Reason: " + e.getResponseBody());
System.err.println("Response headers: " + e.getResponseHeaders());
e.printStackTrace();
}
}
}
```
## 3. Try it for yourself
See detailed sdk example
# Introduction
Source: https://docs.sendx.io/quickstart/javascript-sdk
Learn how to configure and add your first contact with SendX Node JS SDK
## Prerequisites
To get the most out of this guide, youβll need to:
* [**Create a SendX Account**](https://app.sendx.io/register)
* [**Install Node.JS**](https://nodejs.org/en/download)
## 1. Install
```shellscript npm theme={null}
npm install sendx-javascript-sdk --save
```
## 2. Getting Started
```javascript JavaScript theme={null}
import sendx from 'sendx-javascript-sdk';
let defaultClient = sendx.ApiClient.instance;
// Configure API key authorization: apiKeyAuth
let apiKeyAuth = defaultClient.authentications['apiKeyAuth'];
apiKeyAuth.apiKey = 'YOUR API KEY';
let apiInstance = new sendx.ContactApi(); // ContactApi |
let contactRequest = new sendx.ContactRequest(); // ContactRequest |
contactRequest.email = "jane@doe.com";
contactRequest.firstName = "Jane";
contactRequest.lastName = "Doe";
contactRequest.company = "Tech Solutions Inc.";
contactRequest.lastTrackedIp = "34.94.159.140";
contactRequest.customFields = { "1231nfenife213": "VIP", "1434bife23bfij32": "Special Offer Subscriber" };
contactRequest.lists = ["234b324bjed32", "234bij3e2eyv3v2i"];
contactRequest.tags = ["234bijn2ei2jbu4", "2342bijhb2ijneni"];
apiInstance.createContact(contactRequest).then((data) => {
console.log('API called successfully. Contact created: ' + JSON.stringify(data, null, 2));
}, (error) => {
console.error(error);
});
```
## 3. Try it for yourself
See detailed sdk example
# Introduction
Source: https://docs.sendx.io/quickstart/js-api
Learn how to configure and add your first contact with SendX Javascript SDK
The SendX JS Client library enables you to seamlessly capture contacts, assign tags, and update custom fields directly from your website. This guide walks you through installing the snippet, sending asynchronous API requests, and using available methods like identify and track to personalise and automate your marketing workflows.
## Installing Javascript Snippet
To use SendX JS Client library you need to have SendX snippet installed on your website. Each SendX team account has a unique snippet that can be found under [Settings > SendX Snippet](https://app.sendx.io/setting/connectors/api) Snippet.
Here's an example snippet, replace the `YOUR_TEAM_ENCRYPTED_ID` with your team's encrypted Id.
```html theme={null}
```
SendX Javascript snippet gets loaded asynchronously and hence it won't affect page load time of your website.
## Sending API Requests
All requests follow the same pattern.
```javascript theme={null}
_scq.Push(["methodName", { key: "value", ... }]);
```
API requests are executed asynchronously so you can safely place them anywhere on the page. The conventions are similar to what **google analytics** API follows.
## API Methods
SendX Javascript Client library has two methods:
* Identify
* Track
## Identify API Method
Identify API Method is used to attach data to a visitor. If a contact is not yet created then we will create the contact. In case contact already exists then we update it.
```javascript identify.js expandable theme={null}
_scq.push([
"identify",
{
email: "john.doe@gmail.com",
firstName: "John",
lastName: "Doe",
birthday: "1989-03-03",
customFields: {
Designation: "Software Engineer",
Age: "27",
Experience: "5",
},
tags: ["Developer", "API Team"],
},
]);
```
```javascript track.js theme={null}
_scq.push([
"track",
{
addTags: ["blogger", "female"],
success: function () {
console.log("track call successful");
},
failure: function () {
console.log("track call failed");
},
},
]);
_scq.push([
"track",
{
addTags: ["paid user"],
removeTags: ["trial user"],
success: function () {
console.log("track call successful");
},
failure: function () {
console.log("track call failed");
},
},
]);
```
### Tags:
* `tags` is an array of strings.
* If a tag does **not exist**, it is **automatically created** and associated with the contact.
### Custom Fields:
* If a custom field **does not exist**, it will be created with \*\*type \*\*`string` and the value will be set.
* If the field already exists, the **value will be updated**.
* Custom fields can also have type `number`. To modify them incrementally, use:
* `"customField_name": "++34"` β Increases the current value by `34`
* `"customField_name": "--10"` β Decreases the current value by `10`
If the custom field does not already exist, the numeric value (e.g. 34) is directly set as the starting value.
Identify Calls are Additive
The `identify` call does **not delete** any previously set properties.
### API Call A
```javascript identify.js theme={null}
_scq.push([
"identify",
{
email: "john.doe@gmail.com",
firstName: "John",
birthday: "1989-03-03",
customFields: { Designation: "Software Engineer" },
tags: ["Developer"],
success: function () {
console.log("identify call successful");
},
failure: function () {
console.log("identify failed");
},
},
]);
```
### API Call B
```javascript identify.js theme={null}
_scq.push([
"identify",
{
email: "john.doe@gmail.com",
customFields: { Age: "29" },
tags: ["API Team"],
success: function () {
console.log("identify call successful");
},
failure: function () {
console.log("identify failed");
},
},
]);
```
Then the final contact will look like this:
```json theme={null}
{
"firstName": "John",
"email": "john.doe@gmail.com",
"birthday": "1989-03-03",
"customFields": {
"Designation": "Software Engineer",
"Age": "29"
},
"tags": [
"Developer",
"API Team"
]
}
```
Values are **merged**, not overwritten wholesale. You only need to send what you want to **add or update**.
### Identify Properties
| Property | Type | Description |
| :------------- | :---------------------- | :--------------------------------------------------------------------------- |
| `firstName` | `string` | Contactβs first name |
| `lastName` | `string` | Contactβs last name |
| `email` | `string` | Contactβs current email address (used to identify the contact) |
| `newEmail` | `string` | New email address if updating an existing contact |
| `company` | `string` | Company name |
| `birthday` | `string (YYYY-MM-DD)` | Date of birth (e.g., `2016-11-21`) |
| `customFields` | `map[string]string` | Key-value pairs for custom fields (e.g., `{"Designation": "Engineer"}`) |
| `tags` | `array of string` | List of tags associated with the contact (e.g., `["Developer", "API Team"]`) |
| `success` | `function` *(optional)* | Callback executed upon a successful request |
| `failure` | `function` *(optional)* | Callback executed when the request fails or times out |
In case email of an already existing contact needs to be updated then specify current email under email property and updated email under `newEmail` property.
```json response.json theme={null}
{
"status": "200",
"message": "OK",
}
```
## Track API Method
Track API Method is used to track a contact. You can add or remove tags from a contact using this API.
### Track Properties
| Property | Type | Description |
| :----------- | :---------------------- | :------------------------------------------------------------------- |
| `addTags` | `array of string` | Tags to **add** to the contact (e.g., `["Developer", "Onboarding"]`) |
| `removeTags` | `array of string` | Tags to **remove** from the contact |
| `success` | `function` *(optional)* | Callback executed when the request completes successfully |
| `failure` | `function` *(optional)* | Callback executed when the request fails or times out |
# Introduction
Source: https://docs.sendx.io/quickstart/php-sdk
Learn how to configure and add your first contact with SendX PHP SDK
## Prerequisites
To get the most out of this guide, youβll need to:
* [**Create a SendX Account**](https://app.sendx.io/register)
* [**Install PHP 7.4+**](https://www.php.net/downloads.php)
## 1. Install
### **Composer**
To install the bindings via [Composer](https://getcomposer.org/), use the following command on the command line:
```shellscript shell theme={null}
composer require sendx/sendx-php-sdk
```
Or, add the following to `composer.json`:
```json composer.json theme={null}
"require": {
"sendx/sendx-php-sdk": "1.0.0"
}
```
Then run `composer install`
### **Manual Installation**
Download the files and include `autoload.php`:
```php theme={null}
setApiKey('X-Team-ApiKey', 'YOUR_API_KEY');
// Uncomment below to setup prefix (e.g. Bearer) for API key, if needed
// $config = sendx\Configuration::getDefaultConfiguration()->setApiKeyPrefix('X-Team-ApiKey', 'Bearer');
$apiInstance = new sendx\Api\ContactApi(
// If you want use custom http client, pass your client which implements `GuzzleHttp\ClientInterface`.
// This is optional, `GuzzleHttp\Client` will be used as default.
new GuzzleHttp\Client(),
$config
);
$contact_request = new \sendx\model\ContactRequest(); // \sendx\model\ContactRequest
$contact_request->setEmail("john@doe.com"); // Required: Set email
$contact_request->setFirstName("John"); // Optional: Set first name
$contact_request->setLastName("Doe"); // Optional: Set last name
$contact_request->setCompany("SendX"); // Optional: Set company
$contact_request->setLastTrackedIp("192.168.1.1"); // Optional: Set last tracked IP
$contact_request->setCustomFields(["sendf13kn2k3kjm2d" => "Developer", "ckjsnck234nm2kn42" => "Engineering"]); // Optional: Set custom fields
$contact_request->setLists(["list_id_1", "list_id_2"]); // Optional: Subscribe to lists
try {
$result = $apiInstance->createContact($contact_request);
print_r($result);
} catch (Exception $e) {
echo 'Exception when calling ContactApi->createContact: ', $e->getMessage(), PHP_EOL;
}
```
## 3. Try it for yourself
See detailed sdk example
# Introduction
Source: https://docs.sendx.io/quickstart/python-sdk
Learn how to configure and add your first contact with SendX Python SDK
## Prerequisites
To get the most out of this guide, youβll need to:
* [**Create a SendX Account**](https://app.sendx.io/register)
* [**Install Python >v3.0**](https://www.python.org/downloads/)
## 1. Install
Get the python sendx sdk
```pip theme={null}
pip install sendx
```
## 2. Getting Started
```python theme={null}
import sendx_python_sdk
from sendx_python_sdk.models.contact_request import ContactRequest
from sendx_python_sdk.models.response import Response
from sendx_python_sdk.rest import ApiException
from pprint import pprint
configuration = sendx_python_sdk.Configuration()
# Configure API key authorization: apiKeyAuth
configuration.api_key['apiKeyAuth'] = os.environ["API_KEY"]
# Enter a context with an instance of the API client
with sendx_python_sdk.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = sendx_python_sdk.ContactApi(api_client)
contact_request = sendx_python_sdk.ContactRequest() # ContactRequest |
contact_request.email = "johndoe@sendx.io"
contact_request.first_name = "John"
contact_request.last_name = "Doe"
contact_request.company = "SendX"
contact_request.tags = ["12nb32nk43k2", "34njnk42bkj3"]
contact_request.custom_fields = {"1434nfk324kn4d": "VIP", "34njnk42bkj3": "Gold"}
contact_request.last_tracked_ip = "34.212.42.122"
try:
# Create a contact
api_response = api_instance.create_contact(contact_request)
print("The response of ContactApi->create_contact:\n")
pprint(api_response)
except ApiException as e:
print("Exception when calling CampaignApi->create_campaign: %s\n" % e)
```
## 3. Try it yourself
See detailed sdk example
# Introduction
Source: https://docs.sendx.io/quickstart/ruby-sdk
Learn how to configure and add your first contact with SendX Ruby SDK
## Prerequisites
To get the most out of this guide, youβll need to:
* [**Create a SendX Account**](https://app.sendx.io/register)
* [**Install Ruby >v3.0**](https://www.ruby-lang.org/en/downloads/)
## 1. Install
Get the ruby sendx sdk
```shellscript shell theme={null}
gem install sendx-ruby-sdk
```
## 2. Getting Started
```ruby Ruby theme={null}
# Load the gem
require 'time'
require 'sendx-ruby-sdk'
# setup authorization
SendX.configure do |config|
# Configure API key authorization: apiKeyAuth
config.api_key['apiKeyAuth'] = 'YOUR API KEY'
config.server_index = 2
end
api_instance = SendX::ContactApi.new
contact_request = SendX::ContactRequest.new(
email: "john@doe.com",
first_name: "John",
last_name: "Doe",
company: "SendX",
last_tracked_ip: "34.94.159.140",
tags: ["MKdhTovsTJDetCyrJmRySL"],
custom_fields: {
'fnwfnke23kn4kn' => "VIP",
"9i0jinjn0ib0"=> "Subscribers"
},
)
begin
# Create a contact
result = api_instance.create_contact(contact_request)
p result
rescue SendX::ApiError => e
puts "Error when calling ContactApi->create_contact: #{e}"
end
```
## 3. Try it yourself
See detailed sdk example