Sendgrid API
Omnivery API allows you to send messages, retrieve delivery stats, check and configure your sending domains and more in multiple formats. This documentation covers the SendGrid v3 compatible API of Omnivery.
This API follows the SendGrid (v3) API as closely as possible, so existing software or libraries supporting SendGrid (v3) can be used to send email by changing the endpoint and API token, keeping in mind the differences below.
Differences from SendGrid
Endpoints
- Available:
POST /mail/send,POST /mail/batch, the scheduled sends API (/user/scheduled_sends: cancel, list, get),POST /validations/email,GET /scopes,GET /user/account,GET /user/profileand/api_keys(list, create, get, delete). Other SendGrid endpoints (for example suppressions, stats, sender authentication, templates, event webhook settings, Marketing Campaigns and subusers) are not. Manage these in the Omnivery app.
API keys
POST /mail/sendandPOST /validations/emailrequire a sending (domain) API key; the primary (account) API key is not accepted. The sender address must belong to the key's domain.GET /user/account,GET /user/profileand/api_keysrequire the primary (account) API key.GET /scopestakes either; the scopes it returns depend on the key's role.- An API key belongs to one sending domain, so
POST /api_keysneeds adomain, and the key list holds the domain keys only. - The
on-behalf-ofheader is not supported. To act on a sub-account, use that sub-account's own API key.
Sending
- Each personalization is sent as a separate message. If a personalization is rejected, the personalizations before it may already have been sent, so check the error before retrying the whole request.
subjectis required, at the top level or on every personalization, also withtemplate_id: an Omnivery template has no subject of its own (SendGrid can take it from the template).template_idrefers to a template stored in Omnivery.- These fields are not supported and are ignored:
categories,reply_to_list,personalizations[].headers,asm,ip_pool_name,mail_settingsother thansandbox_mode,tracking_settings.subscription_tracking,tracking_settings.ganalytics,tracking_settings.click_tracking.enable_textandtracking_settings.open_tracking.substitution_tag. - Attachments with
disposition: inlineand acontent_idare sent as regular attachments; inline (cid:) images are not supported. send_atmust be less than 72 hours in the future.- Scheduled sends can be cancelled, not paused: the scheduled messages of a batch are deleted from the queue, so
status: pauseis rejected with 400, there is nothing to resume, andDELETE /user/scheduled_sends/{batch_id}(which removes a pause or cancellation) always answers 400. Each cancelled message produces a soft-bounce event (554 5.7.1 [internal] Campaign cancelled) and a bounce notification to the sender, and the recipient is not added to a suppression list (SendGrid's cancelled messages are silently discarded). Cancelling is asynchronous (201means it is queued, 503 that it could not be queued). The 10-minute cut-off applies to the earliestsend_atof a batch with messages at different times, andPATCHalso cancels a batch that has no status yet. Theon-behalf-ofheader and the limit of 100 batches per call (a call takes one batch) do not apply. batch_idmust come fromPOST /mail/batchand be one of your own batches that can still be cancelled; an unknown, expired or foreign ID is rejected with 400. A batch can be cancelled until 10 minutes before the earliestsend_atof its messages, so a batch ID stops being valid then. A cancelled batch accepts no more messages.- With
mail_settings.sandbox_mode.enableset totruethe request returns200 OKand nothing is delivered, as in SendGrid. The difference: the message is not stopped at the API. It is sent in test mode (like Mailguno:testmode), and our MTA accepts and discards it. - Besides SendGrid's own reserved headers,
Sender,Return-Path,DomainKey-Signature,ARC-*,Authentication-Results,MIME-Versionand our system headersX-OV-Ident,X-OV-SubmissionandX-OV-APIFormatare refused inheaders. - A successful request returns
202 Acceptedwithout anX-Message-Idheader. - The maximum message size, including attachments, is 10 MB unless a different limit is set for your domain.
- A rejected message returns HTTP status code 400 with
{"errors": [{"message", "field", "help"}]}, as SendGrid does.fieldnames the request field when the error is about one (for examplefromorpersonalizations.0.to) and isnullotherwise;helpis alwaysnull. This covers a missingfromor recipient, a disallowed attachment and a rejection of the content by the mail server. A message over the size limit returns 413.
Email validation
- The response is returned as a flat object, as documented below, rather than wrapped in
result.
Event webhook
- Event webhooks in SendGrid format are set up in the Omnivery app. Signed event webhooks (
X-Twilio-Email-Event-Webhook-Signature) are not supported. - Temporary delivery failures are reported with the event name
blocked, notdeferred.
This REST API requires all requests to be authenticated using the Authorization header with your access token as a Bearer token (Authorization: Bearer <access token>). API tokens can be found in the UI under Credentials menu in API Keys tab (for domain specific/sending tokens) or under API keys menu. For security reasons we strongly suggest using domain specific API keys rather than account API keys whenever possible.
All data to the API endpoint must be posted in JSON format.
Authentication
- API Key: HTTP bearer
Enter your credentials below to use the Try it feature:
Generates a batch ID that groups scheduled messages. Pass it as batch_id to POST /mail/send, then cancel the whole batch with POST /user/scheduled_sends.
A batch ID can be used for 72 hours. Once a message is scheduled with it, the batch can be cancelled until 10 minutes before the earliest send_at of its messages; after that the ID is no longer valid.
Requires a sending (domain) API key. A batch belongs to that key's domain and cannot be used by another key.
Responses
Created
{
"batch_id": "0b0c3c0e-5a0e-4f43-8f56-0a1f9d4a7c11"
}
Unauthorized
{
"errors": [
{
"message": "Unauthorized"
}
]
}
Code Samples
curl -X POST 'https://sg-api.omnivery.net/v3/mail/batch' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_TOKEN'
package main
import (
"fmt"
"net/http"
)
func main() {
req, _ := http.NewRequest("POST", "https://sg-api.omnivery.net/v3/mail/batch", nil)
req.Header.Set("Authorization", "Bearer YOUR_TOKEN")
resp, _ := http.DefaultClient.Do(req)
fmt.Println(resp.Status)
}
const response = await fetch('https://sg-api.omnivery.net/v3/mail/batch', {
method: 'POST',
headers: {'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TOKEN'},
});
const data = await response.json();
<?php
$ch = curl_init('https://sg-api.omnivery.net/v3/mail/batch');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer YOUR_TOKEN']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
import requests
response = requests.post(
'https://sg-api.omnivery.net/v3/mail/batch',
headers={'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TOKEN'},
)
print(response.json())
Response
This endpoint allows you to send email using SendGrid v3 compatible API
- Top level parameters are referred to as "global".
- Individual fields within the personalizations array will override any other global, or "message level", parameters that are defined outside of personalizations.
This endpoint requires use of domain level API credentials and can not be used with account level API key.
Scheduled delivery
Set
send_atto a unix timestamp to hold the message and deliver it at that time. A globalsend_atapplies to every personalization; asend_atinside a personalization overrides it for that personalization only.
- The time must be less than 72 hours in the future. A later time is rejected with HTTP status code 400.
- A time that is now or already past sends the message immediately.
- A value that is not an integer unix timestamp is rejected with HTTP status code 400.
- Every
send_atin the request is checked before anything is sent, so one invalid value rejects the whole request. The error'sfieldnames the offending value, e.g.send_atorpersonalizations.1.send_at(0-based).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Accept |
header | string | No | |
Content-Type |
header | string | No |
Request Body application/json
| Field | Type | Required | Description | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
attachments |
array | No | An array of attachment objects to be included in the message. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
batch_id |
string | No | A batch ID generated with |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
callback_url |
string | No | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
categories |
array | No | Not supported: categories are ignored (see Differences from SendGrid). |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
content |
array | No | An array where you can specify the content of your email. Required unless a |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
custom_args |
object | No | Custom values are key/value pairs attached to the message. Key/value pairs must be strings. Substitutions will not be made on custom arguments, so any string that is entered into this parameter will be assumed to be the custom argument that you would like to be used. Custom arguments defined in personalizations will override arguments set on global level. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from |
object | Yes | Email address object with the email address and full name of the sender (from) or recipient (to, cc, bcc or reply-tp). |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
headers |
object | No | An object of custom header names and values to add to every message. Reserved headers are refused with HTTP status code 400 in the SendGrid error format ( |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
mail_settings |
object | No | Only |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
personalizations |
array | Yes | An array of messages and their metadata. Each object within personalizations can be thought of as an envelope - it defines who should receive an individual message and how that message should be handled. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
reply_to |
object | No | Email address object with the email address and full name of the sender (from) or recipient (to, cc, bcc or reply-tp). |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
send_at |
integer | No | A unix timestamp allowing you to specify when you want your email to be delivered. Applies to every personalization that does not set its own |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
subject |
string | No | The subject of your email. Required unless every personalization sets its own |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
substitutions |
object | No | An object of key/value pairs following the pattern |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
template_id |
string | No | The ID of a template stored in Omnivery. When it is set, |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tracking_settings |
object | No | A collection of different settings that you can use to override domain defaults. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Responses
OK: sandbox mode (mail_settings.sandbox_mode.enable: true). The message is sent in test mode and not delivered. Empty body.
Accepted. Empty body.
Bad Request
Payload Too Large - the message, including attachments, is over the size limit
Code Samples
curl -X POST 'https://sg-api.omnivery.net/v3/mail/send' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_TOKEN' \
-d '{"attachments": [], "batch_id": 0b0c3c0e-5a0e-4f43-8f56-0a1f9d4a7c11, "callback_url": "string", "categories": [], "content": [], "custom_args": {"id": "string"}, "from": {"email": "string", "name": "string"}, "headers": map[X-Accept-Language:en], "mail_settings": {"sandbox_mode": {"enable": false}}, "personalizations": [], "reply_to": {"email": "string", "name": "string"}, "send_at": 1.6172604e+09, "subject": "string", "substitutions": {"key": "string"}, "template_id": "string", "tracking_settings": {"click_tracking": {"enable": false, "enable_text": false}, "open_tracking": {"enable": false, "substitution_tag": "string"}}}'
package main
import (
"fmt"
"net/http"
)
func main() {
req, _ := http.NewRequest("POST", "https://sg-api.omnivery.net/v3/mail/send", nil)
req.Header.Set("Authorization", "Bearer YOUR_TOKEN")
resp, _ := http.DefaultClient.Do(req)
fmt.Println(resp.Status)
}
const response = await fetch('https://sg-api.omnivery.net/v3/mail/send', {
method: 'POST',
headers: {'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TOKEN'},
body: JSON.stringify({"attachments": [], "batch_id": 0b0c3c0e-5a0e-4f43-8f56-0a1f9d4a7c11, "callback_url": "string", "categories": [], "content": [], "custom_args": {"id": "string"}, "from": {"email": "string", "name": "string"}, "headers": map[X-Accept-Language:en], "mail_settings": {"sandbox_mode": {"enable": false}}, "personalizations": [], "reply_to": {"email": "string", "name": "string"}, "send_at": 1.6172604e+09, "subject": "string", "substitutions": {"key": "string"}, "template_id": "string", "tracking_settings": {"click_tracking": {"enable": false, "enable_text": false}, "open_tracking": {"enable": false, "substitution_tag": "string"}}})
});
const data = await response.json();
<?php
$ch = curl_init('https://sg-api.omnivery.net/v3/mail/send');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer YOUR_TOKEN']);
curl_setopt($ch, CURLOPT_POSTFIELDS, '{"attachments": [], "batch_id": 0b0c3c0e-5a0e-4f43-8f56-0a1f9d4a7c11, "callback_url": "string", "categories": [], "content": [], "custom_args": {"id": "string"}, "from": {"email": "string", "name": "string"}, "headers": map[X-Accept-Language:en], "mail_settings": {"sandbox_mode": {"enable": false}}, "personalizations": [], "reply_to": {"email": "string", "name": "string"}, "send_at": 1.6172604e+09, "subject": "string", "substitutions": {"key": "string"}, "template_id": "string", "tracking_settings": {"click_tracking": {"enable": false, "enable_text": false}, "open_tracking": {"enable": false, "substitution_tag": "string"}}}');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
import requests
response = requests.post(
'https://sg-api.omnivery.net/v3/mail/send',
headers={'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TOKEN'},
json={"attachments": [], "batch_id": 0b0c3c0e-5a0e-4f43-8f56-0a1f9d4a7c11, "callback_url": "string", "categories": [], "content": [], "custom_args": {"id": "string"}, "from": {"email": "string", "name": "string"}, "headers": map[X-Accept-Language:en], "mail_settings": {"sandbox_mode": {"enable": false}}, "personalizations": [], "reply_to": {"email": "string", "name": "string"}, "send_at": 1.6172604e+09, "subject": "string", "substitutions": {"key": "string"}, "template_id": "string", "tracking_settings": {"click_tracking": {"enable": false, "enable_text": false}, "open_tracking": {"enable": false, "substitution_tag": "string"}}}
)
print(response.json())
Response
Address
Email Address Validation provides real-time detailed information on the validity of email addresses. You can integrate this validation process into your platform's signup form and customize the best use of email address validation for your use case.
Email validation must be enabled in the domain settings requires use of domain level API credentials.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Accept |
header | string | No | |
Content-Type |
header | string | No |
Request Body application/json
| Field | Type | Required | Description |
|---|---|---|---|
email |
string | Yes | Email address to validate |
Responses
OK
Code Samples
curl -X POST 'https://sg-api.omnivery.net/v3/validations/email' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_TOKEN' \
-d '{"email": "string"}'
package main
import (
"fmt"
"net/http"
)
func main() {
req, _ := http.NewRequest("POST", "https://sg-api.omnivery.net/v3/validations/email", nil)
req.Header.Set("Authorization", "Bearer YOUR_TOKEN")
resp, _ := http.DefaultClient.Do(req)
fmt.Println(resp.Status)
}
const response = await fetch('https://sg-api.omnivery.net/v3/validations/email', {
method: 'POST',
headers: {'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TOKEN'},
body: JSON.stringify({"email": "string"})
});
const data = await response.json();
<?php
$ch = curl_init('https://sg-api.omnivery.net/v3/validations/email');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer YOUR_TOKEN']);
curl_setopt($ch, CURLOPT_POSTFIELDS, '{"email": "string"}');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
import requests
response = requests.post(
'https://sg-api.omnivery.net/v3/validations/email',
headers={'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TOKEN'},
json={"email": "string"}
)
print(response.json())
Response
Scheduled sends
Returns the cancelled batches of the key's domain.
Requires a sending (domain) API key. A batch belongs to the domain of the key that generated it; another key gets
404.
Differences from SendGrid: there are no paused batches. A cancelled batch is listed until its ID expires (10 minutes before the earliest send_at of its messages).
Responses
OK
[
{
"batch_id": "0b0c3c0e-5a0e-4f43-8f56-0a1f9d4a7c11",
"status": "cancel"
}
]
Unauthorized
{
"errors": [
{
"field": null,
"help": null,
"message": "Unauthorized"
}
]
}
Code Samples
curl -X GET 'https://sg-api.omnivery.net/v3/user/scheduled_sends' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_TOKEN'
package main
import (
"fmt"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET", "https://sg-api.omnivery.net/v3/user/scheduled_sends", nil)
req.Header.Set("Authorization", "Bearer YOUR_TOKEN")
resp, _ := http.DefaultClient.Do(req)
fmt.Println(resp.Status)
}
const response = await fetch('https://sg-api.omnivery.net/v3/user/scheduled_sends', {
method: 'GET',
headers: {'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TOKEN'},
});
const data = await response.json();
<?php
$ch = curl_init('https://sg-api.omnivery.net/v3/user/scheduled_sends');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer YOUR_TOKEN']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
import requests
response = requests.get(
'https://sg-api.omnivery.net/v3/user/scheduled_sends',
headers={'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TOKEN'},
)
print(response.json())
Response
Cancels the scheduled messages of a batch (see POST /mail/batch): they are deleted and never delivered.
Requires a sending (domain) API key. A batch belongs to the domain of the key that generated it; another key gets
404.
The cancellation is queued and carried out in the background; 201 means it is queued, and 503 that it could not be queued (nothing changed, try again). A batch can be cancelled until 10 minutes before the earliest send_at of its messages; after that its ID is no longer valid and the call returns 404.
Differences from SendGrid: only the status cancel exists. pause is rejected with 400, because the messages are deleted and cannot be resumed.
Request Body application/json
| Field | Type | Required | Description |
|---|---|---|---|
batch_id |
string | Yes | |
status |
string | Yes |
Responses
Created
{
"batch_id": "0b0c3c0e-5a0e-4f43-8f56-0a1f9d4a7c11",
"status": "cancel"
}
Invalid request - a missing or invalid batch_id or status, the status pause, or a batch that is already cancelled
{
"errors": [
{
"field": "status",
"help": null,
"message": "The status pause is not supported, it must be cancel"
}
]
}
Unauthorized
{
"errors": [
{
"field": null,
"help": null,
"message": "Unauthorized"
}
]
}
Batch not found - unknown, expired, or not a batch of this key
{
"errors": [
{
"field": "batch_id",
"help": null,
"message": "Batch not found"
}
]
}
The cancellation could not be queued, try again
{
"errors": [
{
"field": null,
"help": null,
"message": "Unable to queue the cancellation, please try again"
}
]
}
Code Samples
curl -X POST 'https://sg-api.omnivery.net/v3/user/scheduled_sends' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_TOKEN' \
-d '{"batch_id": "string", "status": "string"}'
package main
import (
"fmt"
"net/http"
)
func main() {
req, _ := http.NewRequest("POST", "https://sg-api.omnivery.net/v3/user/scheduled_sends", nil)
req.Header.Set("Authorization", "Bearer YOUR_TOKEN")
resp, _ := http.DefaultClient.Do(req)
fmt.Println(resp.Status)
}
const response = await fetch('https://sg-api.omnivery.net/v3/user/scheduled_sends', {
method: 'POST',
headers: {'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TOKEN'},
body: JSON.stringify({"batch_id": "string", "status": "string"})
});
const data = await response.json();
<?php
$ch = curl_init('https://sg-api.omnivery.net/v3/user/scheduled_sends');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer YOUR_TOKEN']);
curl_setopt($ch, CURLOPT_POSTFIELDS, '{"batch_id": "string", "status": "string"}');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
import requests
response = requests.post(
'https://sg-api.omnivery.net/v3/user/scheduled_sends',
headers={'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TOKEN'},
json={"batch_id": "string", "status": "string"}
)
print(response.json())
Response
Returns the status of a cancelled batch.
Requires a sending (domain) API key. A batch belongs to the domain of the key that generated it; another key gets
404.
Responses
OK
[
{
"batch_id": "0b0c3c0e-5a0e-4f43-8f56-0a1f9d4a7c11",
"status": "cancel"
}
]
Unauthorized
{
"errors": [
{
"field": null,
"help": null,
"message": "Unauthorized"
}
]
}
Batch not found, not cancelled, or not a batch of this key
{
"errors": [
{
"field": "batch_id",
"help": null,
"message": "Batch not found"
}
]
}
Code Samples
curl -X GET 'https://sg-api.omnivery.net/v3/user/scheduled_sends/{batch_id}' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_TOKEN'
package main
import (
"fmt"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET", "https://sg-api.omnivery.net/v3/user/scheduled_sends/{batch_id}", nil)
req.Header.Set("Authorization", "Bearer YOUR_TOKEN")
resp, _ := http.DefaultClient.Do(req)
fmt.Println(resp.Status)
}
const response = await fetch('https://sg-api.omnivery.net/v3/user/scheduled_sends/{batch_id}', {
method: 'GET',
headers: {'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TOKEN'},
});
const data = await response.json();
<?php
$ch = curl_init('https://sg-api.omnivery.net/v3/user/scheduled_sends/{batch_id}');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer YOUR_TOKEN']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
import requests
response = requests.get(
'https://sg-api.omnivery.net/v3/user/scheduled_sends/{batch_id}',
headers={'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TOKEN'},
)
print(response.json())
Response
Cancels the scheduled messages of the batch, like POST /user/scheduled_sends.
Requires a sending (domain) API key. A batch belongs to the domain of the key that generated it; another key gets
404.
Differences from SendGrid: only the status cancel exists, and it also applies to a batch that has no status yet. pause is rejected with 400; a batch that is already cancelled returns 400.
Request Body application/json
| Field | Type | Required | Description |
|---|---|---|---|
status |
string | Yes |
Responses
No Content - the cancellation is queued
Invalid status, or the batch is already cancelled
{
"errors": [
{
"field": "batch_id",
"help": null,
"message": "The scheduled send already has a status"
}
]
}
Unauthorized
{
"errors": [
{
"field": null,
"help": null,
"message": "Unauthorized"
}
]
}
Batch not found - unknown, expired, or not a batch of this key
{
"errors": [
{
"field": "batch_id",
"help": null,
"message": "Batch not found"
}
]
}
The cancellation could not be queued, try again
{
"errors": [
{
"field": null,
"help": null,
"message": "Unable to queue the cancellation, please try again"
}
]
}
Code Samples
curl -X PATCH 'https://sg-api.omnivery.net/v3/user/scheduled_sends/{batch_id}' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_TOKEN' \
-d '{"status": "string"}'
package main
import (
"fmt"
"net/http"
)
func main() {
req, _ := http.NewRequest("PATCH", "https://sg-api.omnivery.net/v3/user/scheduled_sends/{batch_id}", nil)
req.Header.Set("Authorization", "Bearer YOUR_TOKEN")
resp, _ := http.DefaultClient.Do(req)
fmt.Println(resp.Status)
}
const response = await fetch('https://sg-api.omnivery.net/v3/user/scheduled_sends/{batch_id}', {
method: 'PATCH',
headers: {'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TOKEN'},
body: JSON.stringify({"status": "string"})
});
const data = await response.json();
<?php
$ch = curl_init('https://sg-api.omnivery.net/v3/user/scheduled_sends/{batch_id}');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PATCH');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer YOUR_TOKEN']);
curl_setopt($ch, CURLOPT_POSTFIELDS, '{"status": "string"}');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
import requests
response = requests.patch(
'https://sg-api.omnivery.net/v3/user/scheduled_sends/{batch_id}',
headers={'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TOKEN'},
json={"status": "string"}
)
print(response.json())
Response
Not supported: a cancelled batch has had its messages deleted, so the cancellation cannot be undone. The call answers 400 for a cancelled batch and 404 for any other.
Requires a sending (domain) API key. A batch belongs to the domain of the key that generated it; another key gets
404.
Responses
A cancellation cannot be removed
{
"errors": [
{
"field": "batch_id",
"help": null,
"message": "A cancellation cannot be removed: the messages of the batch have been deleted"
}
]
}
Unauthorized
{
"errors": [
{
"field": null,
"help": null,
"message": "Unauthorized"
}
]
}
Batch not found, not cancelled, or not a batch of this key
{
"errors": [
{
"field": "batch_id",
"help": null,
"message": "Batch not found"
}
]
}
Code Samples
curl -X DELETE 'https://sg-api.omnivery.net/v3/user/scheduled_sends/{batch_id}' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_TOKEN'
package main
import (
"fmt"
"net/http"
)
func main() {
req, _ := http.NewRequest("DELETE", "https://sg-api.omnivery.net/v3/user/scheduled_sends/{batch_id}", nil)
req.Header.Set("Authorization", "Bearer YOUR_TOKEN")
resp, _ := http.DefaultClient.Do(req)
fmt.Println(resp.Status)
}
const response = await fetch('https://sg-api.omnivery.net/v3/user/scheduled_sends/{batch_id}', {
method: 'DELETE',
headers: {'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TOKEN'},
});
const data = await response.json();
<?php
$ch = curl_init('https://sg-api.omnivery.net/v3/user/scheduled_sends/{batch_id}');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer YOUR_TOKEN']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
import requests
response = requests.delete(
'https://sg-api.omnivery.net/v3/user/scheduled_sends/{batch_id}',
headers={'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TOKEN'},
)
print(response.json())
Response
Account
Returns the scopes of the API key used for the request. Libraries and plugins call it to check that a key may send mail.
- A sending (domain) API key returns
["mail.send"]. - A primary (account) API key returns
user.account.read,user.profile.read,api_keys.create,api_keys.readandapi_keys.delete.
Differences from SendGrid: the scopes are fixed by the key's role (there are no custom scope sets), and email validation is not advertised as a scope although a sending key can use it.
Responses
OK
{
"scopes": [
"mail.send"
]
}
Unauthorized
{
"errors": [
{
"field": null,
"help": null,
"message": "Unauthorized"
}
]
}
Code Samples
curl -X GET 'https://sg-api.omnivery.net/v3/scopes' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_TOKEN'
package main
import (
"fmt"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET", "https://sg-api.omnivery.net/v3/scopes", nil)
req.Header.Set("Authorization", "Bearer YOUR_TOKEN")
resp, _ := http.DefaultClient.Do(req)
fmt.Println(resp.Status)
}
const response = await fetch('https://sg-api.omnivery.net/v3/scopes', {
method: 'GET',
headers: {'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TOKEN'},
});
const data = await response.json();
<?php
$ch = curl_init('https://sg-api.omnivery.net/v3/scopes');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer YOUR_TOKEN']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
import requests
response = requests.get(
'https://sg-api.omnivery.net/v3/scopes',
headers={'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TOKEN'},
)
print(response.json())
Response
Returns {"type": "paid"} or {"type": "free"} for the account of the API key. Primary (account) API key only.
Differences from SendGrid: reputation is not returned, Omnivery has no account-level reputation score (reputation is reported per domain in the app).
Responses
OK
{
"type": "paid"
}
Unauthorized - the key is missing or not allowed to use this endpoint
{
"errors": [
{
"field": null,
"help": null,
"message": "Unauthorized - this endpoint requires a \"primary\" API credential role"
}
]
}
Code Samples
curl -X GET 'https://sg-api.omnivery.net/v3/user/account' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_TOKEN'
package main
import (
"fmt"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET", "https://sg-api.omnivery.net/v3/user/account", nil)
req.Header.Set("Authorization", "Bearer YOUR_TOKEN")
resp, _ := http.DefaultClient.Do(req)
fmt.Println(resp.Status)
}
const response = await fetch('https://sg-api.omnivery.net/v3/user/account', {
method: 'GET',
headers: {'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TOKEN'},
});
const data = await response.json();
<?php
$ch = curl_init('https://sg-api.omnivery.net/v3/user/account');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer YOUR_TOKEN']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
import requests
response = requests.get(
'https://sg-api.omnivery.net/v3/user/account',
headers={'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TOKEN'},
)
print(response.json())
Response
Returns the profile of the account of the API key, with SendGrid's fields. Primary (account) API key only.
Differences from SendGrid: first_name, last_name, address2, state and website are not stored by Omnivery and are returned as empty strings; country is the ISO 3166-1 alpha-2 code. zip is always a string.
Responses
OK
{
"address": "Main 1",
"address2": "",
"city": "Praha",
"company": "Alpha s.r.o.",
"country": "CZ",
"first_name": "",
"last_name": "",
"phone": "+420111222333",
"state": "",
"website": "",
"zip": "01008"
}
Unauthorized - the key is missing or not allowed to use this endpoint
{
"errors": [
{
"field": null,
"help": null,
"message": "Unauthorized - this endpoint requires a \"primary\" API credential role"
}
]
}
Code Samples
curl -X GET 'https://sg-api.omnivery.net/v3/user/profile' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_TOKEN'
package main
import (
"fmt"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET", "https://sg-api.omnivery.net/v3/user/profile", nil)
req.Header.Set("Authorization", "Bearer YOUR_TOKEN")
resp, _ := http.DefaultClient.Do(req)
fmt.Println(resp.Status)
}
const response = await fetch('https://sg-api.omnivery.net/v3/user/profile', {
method: 'GET',
headers: {'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TOKEN'},
});
const data = await response.json();
<?php
$ch = curl_init('https://sg-api.omnivery.net/v3/user/profile');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer YOUR_TOKEN']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
import requests
response = requests.get(
'https://sg-api.omnivery.net/v3/user/profile',
headers={'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TOKEN'},
)
print(response.json())
Response
API Keys
Lists the sending API keys of the account's domains as {"result": [{"api_key_id", "name"}]}. Primary (account) API key only. The key values are never returned.
Differences from SendGrid: an Omnivery API key belongs to one sending domain, so the list holds the domain (sending) keys; account (primary) keys and webhook signing keys are not listed. api_key_id is the key's numeric id as a string.
Responses
OK
{
"result": [
{
"api_key_id": "1234",
"name": "Shop mailer"
}
]
}
Unauthorized - the key is missing or not allowed to use this endpoint
{
"errors": [
{
"field": null,
"help": null,
"message": "Unauthorized - this endpoint requires a \"primary\" API credential role"
}
]
}
Code Samples
curl -X GET 'https://sg-api.omnivery.net/v3/api_keys' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_TOKEN'
package main
import (
"fmt"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET", "https://sg-api.omnivery.net/v3/api_keys", nil)
req.Header.Set("Authorization", "Bearer YOUR_TOKEN")
resp, _ := http.DefaultClient.Do(req)
fmt.Println(resp.Status)
}
const response = await fetch('https://sg-api.omnivery.net/v3/api_keys', {
method: 'GET',
headers: {'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TOKEN'},
});
const data = await response.json();
<?php
$ch = curl_init('https://sg-api.omnivery.net/v3/api_keys');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer YOUR_TOKEN']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
import requests
response = requests.get(
'https://sg-api.omnivery.net/v3/api_keys',
headers={'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TOKEN'},
)
print(response.json())
Response
Creates a sending API key and returns it. The api_key is shown only in this response. Primary (account) API key only.
Differences from SendGrid: a key belongs to one sending domain of your account, so the request must carry domain. scopes is accepted and ignored: the key is a sending key with the scope mail.send.
Request Body application/json
| Field | Type | Required | Description |
|---|---|---|---|
domain |
string | Yes | Sending domain of your account the key is bound to. Omnivery-specific, required. |
name |
string | Yes | Name of the key |
scopes |
array | No | Accepted and ignored. |
Responses
Created
{
"api_key": "0123456789abcdef0123456789abcdef",
"api_key_id": "1234",
"name": "Shop mailer",
"scopes": [
"mail.send"
]
}
Bad Request - name or domain is missing, or the domain is not available
{
"errors": [
{
"field": "domain",
"help": null,
"message": "domain is required: an Omnivery API key belongs to one sending domain"
}
]
}
Unauthorized - the key is missing or not allowed to use this endpoint
{
"errors": [
{
"field": null,
"help": null,
"message": "Unauthorized - this endpoint requires a \"primary\" API credential role"
}
]
}
Code Samples
curl -X POST 'https://sg-api.omnivery.net/v3/api_keys' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_TOKEN' \
-d '{"domain": "string", "name": "string", "scopes": []}'
package main
import (
"fmt"
"net/http"
)
func main() {
req, _ := http.NewRequest("POST", "https://sg-api.omnivery.net/v3/api_keys", nil)
req.Header.Set("Authorization", "Bearer YOUR_TOKEN")
resp, _ := http.DefaultClient.Do(req)
fmt.Println(resp.Status)
}
const response = await fetch('https://sg-api.omnivery.net/v3/api_keys', {
method: 'POST',
headers: {'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TOKEN'},
body: JSON.stringify({"domain": "string", "name": "string", "scopes": []})
});
const data = await response.json();
<?php
$ch = curl_init('https://sg-api.omnivery.net/v3/api_keys');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer YOUR_TOKEN']);
curl_setopt($ch, CURLOPT_POSTFIELDS, '{"domain": "string", "name": "string", "scopes": []}');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
import requests
response = requests.post(
'https://sg-api.omnivery.net/v3/api_keys',
headers={'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TOKEN'},
json={"domain": "string", "name": "string", "scopes": []}
)
print(response.json())
Response
Returns the key as {"result": [{"api_key_id", "name", "scopes"}]}: result is an array, as in SendGrid. Primary (account) API key only. A key of another account, an account (primary) key or an unknown id answers 404.
Responses
OK
{
"result": [
{
"api_key_id": "1234",
"name": "Shop mailer",
"scopes": [
"mail.send"
]
}
]
}
Unauthorized - the key is missing or not allowed to use this endpoint
{
"errors": [
{
"field": null,
"help": null,
"message": "Unauthorized - this endpoint requires a \"primary\" API credential role"
}
]
}
Not Found
{
"errors": [
{
"field": null,
"help": null,
"message": "API key not found"
}
]
}
Code Samples
curl -X GET 'https://sg-api.omnivery.net/v3/api_keys/{api_key_id}' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_TOKEN'
package main
import (
"fmt"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET", "https://sg-api.omnivery.net/v3/api_keys/{api_key_id}", nil)
req.Header.Set("Authorization", "Bearer YOUR_TOKEN")
resp, _ := http.DefaultClient.Do(req)
fmt.Println(resp.Status)
}
const response = await fetch('https://sg-api.omnivery.net/v3/api_keys/{api_key_id}', {
method: 'GET',
headers: {'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TOKEN'},
});
const data = await response.json();
<?php
$ch = curl_init('https://sg-api.omnivery.net/v3/api_keys/{api_key_id}');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer YOUR_TOKEN']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
import requests
response = requests.get(
'https://sg-api.omnivery.net/v3/api_keys/{api_key_id}',
headers={'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TOKEN'},
)
print(response.json())
Response
Deletes the key. Primary (account) API key only. A key of another account, an account (primary) key or an unknown id answers 404 and nothing is deleted.
Differences from SendGrid: updating a key (PUT / PATCH) is not available.
Responses
No Content
Unauthorized - the key is missing or not allowed to use this endpoint
{
"errors": [
{
"field": null,
"help": null,
"message": "Unauthorized - this endpoint requires a \"primary\" API credential role"
}
]
}
Not Found
{
"errors": [
{
"field": null,
"help": null,
"message": "API key not found"
}
]
}
Code Samples
curl -X DELETE 'https://sg-api.omnivery.net/v3/api_keys/{api_key_id}' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_TOKEN'
package main
import (
"fmt"
"net/http"
)
func main() {
req, _ := http.NewRequest("DELETE", "https://sg-api.omnivery.net/v3/api_keys/{api_key_id}", nil)
req.Header.Set("Authorization", "Bearer YOUR_TOKEN")
resp, _ := http.DefaultClient.Do(req)
fmt.Println(resp.Status)
}
const response = await fetch('https://sg-api.omnivery.net/v3/api_keys/{api_key_id}', {
method: 'DELETE',
headers: {'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TOKEN'},
});
const data = await response.json();
<?php
$ch = curl_init('https://sg-api.omnivery.net/v3/api_keys/{api_key_id}');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer YOUR_TOKEN']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
import requests
response = requests.delete(
'https://sg-api.omnivery.net/v3/api_keys/{api_key_id}',
headers={'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TOKEN'},
)
print(response.json())