Worked request and response samples
Copy a request body as written, substitute your own ids, and compare the response envelope. Errors follow Devotel Orbit’s{ error, meta } envelope, shown once below under Error envelope.
Check DNC status for a phone number
GET /api/v1/compliance/dnc/check403 DNC_SYNC_NOT_ENABLED.
Request
cURL
curl -X GET "https://api.orbit.devotel.io/api/v1/compliance/dnc/check" \
-H "X-API-Key: dv_live_sk_your_key_here"
Node.js
import { Orbit } from '@devotel-orbit/node'
const orbit = new Orbit({
apiKey: process.env.ORBIT_API_KEY!,
})
const res = await fetch('https://api.orbit.devotel.io/api/v1/compliance/dnc/check', {
method: 'GET',
headers: {
'X-API-Key': process.env.ORBIT_API_KEY!,
},
})
console.log(await res.json())
Python
import os, requests
headers = {"X-API-Key": os.environ["ORBIT_API_KEY"]}
r = requests.get("https://api.orbit.devotel.io/api/v1/compliance/dnc/check", headers=headers)
print(r.json())
Go
package main
import (
"bytes"
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("GET", "https://api.orbit.devotel.io/api/v1/compliance/dnc/check", nil)
req.Header.Set("X-API-Key", os.Getenv("ORBIT_API_KEY"))
http.DefaultClient.Do(req)
}
Ruby
require 'net/http'
require 'json'
uri = URI('https://api.orbit.devotel.io/api/v1/compliance/dnc/check')
req = Net::HTTP::Get.new(uri)
req['X-API-Key'] = ENV['ORBIT_API_KEY']
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
puts res.body
PHP
<?php
$ch = curl_init('https://api.orbit.devotel.io/api/v1/compliance/dnc/check');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-API-Key: ' . getenv('ORBIT_API_KEY'),
]);
echo curl_exec($ch);
{
"data": {
"phone": "+14155551234",
"on_dnc": true,
"sources": ["tenant_contacts.dnc"]
},
"meta": {
"request_id": "req_dnc_check",
"timestamp": "2026-08-01T12:00:00.000Z"
}
}
Run a preflight check on a destination
POST /api/v1/compliance/10dlc/preflightcURL
curl -X POST "https://api.orbit.devotel.io/api/v1/compliance/10dlc/preflight" \
-H "X-API-Key: dv_live_sk_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"brand_id": "brnd_1a2b3c4d5e6f7081",
"campaign_id": "cmp_1a2b3c4d5e6f7081a2b3c4d5"
}'
Node.js
import { Orbit } from '@devotel-orbit/node'
const orbit = new Orbit({
apiKey: process.env.ORBIT_API_KEY!,
})
const res = await fetch('https://api.orbit.devotel.io/api/v1/compliance/10dlc/preflight', {
method: 'POST',
headers: {
'X-API-Key': process.env.ORBIT_API_KEY!,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"brand_id": "brnd_1a2b3c4d5e6f7081",
"campaign_id": "cmp_1a2b3c4d5e6f7081a2b3c4d5"
}),
})
console.log(await res.json())
Python
import os, requests
headers = {"X-API-Key": os.environ["ORBIT_API_KEY"]}
headers["Content-Type"] = "application/json"
r = requests.post("https://api.orbit.devotel.io/api/v1/compliance/10dlc/preflight", headers=headers, json={
"brand_id": "brnd_1a2b3c4d5e6f7081",
"campaign_id": "cmp_1a2b3c4d5e6f7081a2b3c4d5"
})
print(r.json())
Go
package main
import (
"bytes"
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("POST", "https://api.orbit.devotel.io/api/v1/compliance/10dlc/preflight", bytes.NewBuffer([]byte(`{
"brand_id": "brnd_1a2b3c4d5e6f7081",
"campaign_id": "cmp_1a2b3c4d5e6f7081a2b3c4d5"
}`)))
req.Header.Set("X-API-Key", os.Getenv("ORBIT_API_KEY"))
req.Header.Set("Content-Type", "application/json")
http.DefaultClient.Do(req)
}
Ruby
require 'net/http'
require 'json'
uri = URI('https://api.orbit.devotel.io/api/v1/compliance/10dlc/preflight')
req = Net::HTTP::Post.new(uri)
req['X-API-Key'] = ENV['ORBIT_API_KEY']
req['Content-Type'] = 'application/json'
req.body = {
"brand_id": "brnd_1a2b3c4d5e6f7081",
"campaign_id": "cmp_1a2b3c4d5e6f7081a2b3c4d5"
}.to_json
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
puts res.body
PHP
<?php
$ch = curl_init('https://api.orbit.devotel.io/api/v1/compliance/10dlc/preflight');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-API-Key: ' . getenv('ORBIT_API_KEY'),
'Content-Type: application/json',
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, <<<JSON
{
"brand_id": "brnd_1a2b3c4d5e6f7081",
"campaign_id": "cmp_1a2b3c4d5e6f7081a2b3c4d5"
}
JSON);
echo curl_exec($ch);
{
"data": {
"brand_id": "brnd_1a2b3c4d5e6f7081",
"eligible": true,
"blocking_checks": []
},
"meta": {
"request_id": "req_preflight",
"timestamp": "2026-08-01T12:01:00.000Z"
}
}
Record an opt-in or opt-out for a contact
POST /api/v1/compliance/consentcontact_id or a freeform identifier. An opt-in requires purpose and consent_text_version for proof.
Request
cURL
curl -X POST "https://api.orbit.devotel.io/api/v1/compliance/consent" \
-H "X-API-Key: dv_live_sk_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"identifier": "+14155551234",
"channels": [
"sms"
],
"action": "opt_in",
"purpose": "marketing",
"consent_text_version": "2026-08-opt-in"
}'
Node.js
import { Orbit } from '@devotel-orbit/node'
const orbit = new Orbit({
apiKey: process.env.ORBIT_API_KEY!,
})
const res = await fetch('https://api.orbit.devotel.io/api/v1/compliance/consent', {
method: 'POST',
headers: {
'X-API-Key': process.env.ORBIT_API_KEY!,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"identifier": "+14155551234",
"channels": [
"sms"
],
"action": "opt_in",
"purpose": "marketing",
"consent_text_version": "2026-08-opt-in"
}),
})
console.log(await res.json())
Python
import os, requests
headers = {"X-API-Key": os.environ["ORBIT_API_KEY"]}
headers["Content-Type"] = "application/json"
r = requests.post("https://api.orbit.devotel.io/api/v1/compliance/consent", headers=headers, json={
"identifier": "+14155551234",
"channels": [
"sms"
],
"action": "opt_in",
"purpose": "marketing",
"consent_text_version": "2026-08-opt-in"
})
print(r.json())
Go
package main
import (
"bytes"
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("POST", "https://api.orbit.devotel.io/api/v1/compliance/consent", bytes.NewBuffer([]byte(`{
"identifier": "+14155551234",
"channels": [
"sms"
],
"action": "opt_in",
"purpose": "marketing",
"consent_text_version": "2026-08-opt-in"
}`)))
req.Header.Set("X-API-Key", os.Getenv("ORBIT_API_KEY"))
req.Header.Set("Content-Type", "application/json")
http.DefaultClient.Do(req)
}
Ruby
require 'net/http'
require 'json'
uri = URI('https://api.orbit.devotel.io/api/v1/compliance/consent')
req = Net::HTTP::Post.new(uri)
req['X-API-Key'] = ENV['ORBIT_API_KEY']
req['Content-Type'] = 'application/json'
req.body = {
"identifier": "+14155551234",
"channels": [
"sms"
],
"action": "opt_in",
"purpose": "marketing",
"consent_text_version": "2026-08-opt-in"
}.to_json
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
puts res.body
PHP
<?php
$ch = curl_init('https://api.orbit.devotel.io/api/v1/compliance/consent');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-API-Key: ' . getenv('ORBIT_API_KEY'),
'Content-Type: application/json',
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, <<<JSON
{
"identifier": "+14155551234",
"channels": [
"sms"
],
"action": "opt_in",
"purpose": "marketing",
"consent_text_version": "2026-08-opt-in"
}
JSON);
echo curl_exec($ch);
{
"data": {
"identifier": "+14155551234",
"action": "opt_in",
"channels": ["sms"]
},
"meta": {
"request_id": "req_consent",
"timestamp": "2026-08-01T12:02:00.000Z"
}
}
Error envelope
422
{
"error": {
"code": "VALIDATION_ERROR",
"status": 422,
"message": "channels: opt_in requires at least one channel"
},
"meta": {
"request_id": "req_...",
"timestamp": "2026-08-01T12:00:00.000Z"
}
}
DLT-India registration (gated writes)
DLT-India registration must be enabled for your account. The four
DLT-India write endpoints — If you receive this response, contact support to have DLT registration enabled
for your account.
POST /compliance/dlt-india/principal-entities,
POST /compliance/dlt-india/headers, POST /compliance/dlt-india/content-templates,
and POST /compliance/dlt-india/consent-templates — return 503 FEATURE_DISABLED
until DLT registration is enabled for your account. The matching GET endpoints stay
available in every environment, so you can still read existing principal
entities, headers, and templates while writes are disabled.A gated request returns:503 Service Unavailable
{
"error": {
"code": "FEATURE_DISABLED",
"status": 503,
"message": "DLT registration is not yet available for this account."
},
"meta": {
"request_id": "req_...",
"timestamp": "2026-07-02T00:00:00.000Z"
}
}