Send Individual Emails
This method sends an email to a set of addresses you pass in, or schedules it. Behind the scenes it creates a campaign in the brand your API key belongs to (it appears in your dashboard with the subject as its title). Unless you pass list_ids, the addresses are added to a new list named API Send - <date and time> and the campaign is sent to that list.
Before anything is created, Skrybe checks the brand's sending quota, that the from_email domain is one of the brand's allowed From domains and is verified, and that the brand isn't under review.
URL
https://dashboard.skry.be/api/emails/send.php
PARAMETERS(POST)
api_keyyour API key.from_namethe 'From name' of your emailfrom_emailthe 'From email' of your email. Its domain must be allowed for the brand.reply_tothe 'Reply to' of your emailsubjectthe 'Subject' of your email (also used as the campaign title in your dashboard)plain_textthe 'Plain text version' of your email (optional)html_textthe 'HTML version' of your emailtoa JSON-encoded array of email addresses, eg.["user@example.com","user2@example.com"]. At most 250 addresses per request. Required, even when you passlist_ids.recipient-variablesa JSON-encoded object with per-recipient values, keyed by email address. Format:{"user@example.com": {"first":"John", "id":1}, "user2@example.com": {"first":"Jane", "id":2}}. Each key becomes a custom field on the new list, so you can use it in your email like any custom field's personalization tag, eg.[first,fallback=there]. Only used when nolist_idsare passed. (optional)list_idssend to these existing lists instead of creating a new one. Single or comma-separated. Use the encrypted ids returned by Get lists (numeric list ids are also accepted). Every list must belong to the brand. (optional)segment_idsalso send to these segments. Single or comma-separated numeric segment ids, which can be found in the segments setup page; every segment must belong to the brand. (optional)exclude_list_idslists whose subscribers are left out, in the same format aslist_ids. (optional)exclude_segments_idssegments whose subscribers are left out, in the same format assegment_ids. (optional)query_stringeg. Google Analytics tags (optional)track_opensSet to 0 to disable, 1 to enable and 2 for anonymous opens tracking. Default is 1.track_clicksSet to 0 to disable, 1 to enable and 2 for anonymous clicks tracking. Default is 1.schedule_date_timeEmail will be scheduled if a date/time is passed, eg.June 15, 2027 6:05pmor2027-06-15 18:05. Anything PHP'sstrtotime()understands is accepted. The email goes out at that time inschedule_timezone. (optional)schedule_timezoneEg.America/New_York. See the list of PHP's supported timezones. This parameter only applies if you're scheduling your email withschedule_date_time. Skrybe will use your default timezone if this parameter is empty.
The number of addresses in to is what's checked against, and charged to, the brand's sending quota.
RESPONSE (JSON)
Every response is JSON. Success returns HTTP status 200 with the ID of the campaign that was created:
{
"ok": true,
"message": "Campaign created and now sending",
"data": { "campaign_id": 1234 },
"timestamp": "2026-10-15 14:03:11"
}
When schedule_date_time is passed, message is Campaign scheduled.
Errors return ok: false and an error message, with an HTTP error status:
{
"ok": false,
"error": "Subject not passed",
"timestamp": "2026-10-15 14:03:11"
}
Error (400): No data passed
Error (400): API key not passed
Error (400): Invalid API key
Error (429): Too many failed attempts. Try again later. (after 10 failed API key attempts from your IP address within 15 minutes, it is blocked for 15 minutes)
Error (400): From name not passed
Error (400): From email not passed
Error (400): Reply to email not passed
Error (400): Subject not passed
Error (400): HTML not passed
Error (400): No recipient emails provided (also returned when to isn't valid JSON)
Error (400): Maximum 250 recipients per API request.
Error (400): Invalid email address format
Error (400): schedule_timezone is invalid
Error (400): schedule_date_time is invalid
Error (402): Subscription expired or monthly quota exceeded
Error (400): Unauthorised From email domain
Error (400): Domain "<domain>" is not verified in SES. Full domain verification is required.
Error (403): Account under review: <reason>. Sending is disabled.
Error (400): One or more list IDs are invalid (a list id that is unknown, can't be decoded, or belongs to another brand, in list_ids or exclude_list_ids)
Error (400): One or more segment IDs are invalid
Error (500): Unable to create campaign: <database error>
EXAMPLES
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/x-www-form-urlencoded");
var urlencoded = new URLSearchParams();
urlencoded.append("api_key", "<YOUR_API_KEY>");
urlencoded.append("from_name", "Mayo");
urlencoded.append("from_email", "contact@example.com");
urlencoded.append("reply_to", "contact@example.com");
urlencoded.append("subject", "Q4 Newsletter");
urlencoded.append("html_text", "<html><body>Hello [first,fallback=there]!</body></html>");
urlencoded.append("to", JSON.stringify(["user@example.com", "user2@example.com"]));
urlencoded.append("recipient-variables", JSON.stringify({
"user@example.com": {"first": "John"},
"user2@example.com": {"first": "Jane"}
}));
urlencoded.append("track_opens", "1");
urlencoded.append("track_clicks", "1");
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: urlencoded,
redirect: 'follow'
};
fetch("https://dashboard.skry.be/api/emails/send.php", requestOptions)
.then(response => response.json())
.then(result => console.log(result))
.catch(error => console.log('error', error));
const axios = require('axios');
const qs = require('qs');
let data = qs.stringify({
'api_key': '<YOUR_API_KEY>',
'from_name': 'Mayo',
'from_email': 'contact@example.com',
'reply_to': 'contact@example.com',
'subject': 'Q4 Newsletter',
'html_text': '<html><body>Hello [first,fallback=there]!</body></html>',
'to': JSON.stringify(['user@example.com', 'user2@example.com']),
'recipient-variables': JSON.stringify({
'user@example.com': { 'first': 'John' },
'user2@example.com': { 'first': 'Jane' }
}),
'track_opens': '1',
'track_clicks': '1'
});
let config = {
method: 'post',
maxBodyLength: Infinity,
url: 'https://dashboard.skry.be/api/emails/send.php',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data : data
};
axios.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
// Error responses use HTTP error statuses; the JSON body is in error.response.data
console.log(error.response ? error.response.data : error);
});