Appearance
Code Examples
Ready-to-use code examples for common API operations.
Python
Setup
python
import os
import requests
API_BASE = "https://app.mailshield.app/api/v1"
API_TOKEN = os.environ.get("MAILSHIELD_API_TOKEN")
headers = {
"Authorization": f"Bearer {API_TOKEN}",
"Content-Type": "application/json"
}
def api_get(endpoint, params=None):
response = requests.get(f"{API_BASE}{endpoint}", headers=headers, params=params)
response.raise_for_status()
return response.json()["data"]
def api_post(endpoint, data=None):
response = requests.post(f"{API_BASE}{endpoint}", headers=headers, json=data)
response.raise_for_status()
return response.json()["data"]
def api_get_all(endpoint, params=None):
"""Fetch every page of a list endpoint."""
params = {**(params or {}), "limit": 100, "page": 1}
items = []
while True:
response = requests.get(f"{API_BASE}{endpoint}", headers=headers, params=params)
response.raise_for_status()
body = response.json()
items.extend(body["data"])
if not body["meta"]["pagination"]["hasMore"]:
return items
params["page"] += 1List All Domains
python
domains = api_get_all("/domains")
for domain in domains:
print(f"{domain['domain']}: verified={domain['verified']}")Add a Domain
python
new_domain = api_post("/domains", {
"domain": "example.com",
"testEmailLocalPart": "admin",
"usageType": "sends-and-receives"
})
print(f"Created domain: {new_domain['id']}")
record = new_domain["verificationRecord"]
print(f"Verify with a {record['type']} record at {record['hostname']}: {record['value']}")
print(f"Send DMARC reports to: {new_domain['reporting']['ruaAddress']}")Check Domain Security
python
domain_id = "550e8400-e29b-41d4-a716-446655440000"
# Trigger checks
results = api_post(f"/domains/{domain_id}/checks")
print(f"Checked at: {results['checkedAt']}")
# Get score
score = api_get(f"/domains/{domain_id}/score")
print(f"Score: {score['score']} ({score['grade']})")Monitor DMARC Pass Rate
python
from datetime import datetime, timedelta, timezone
domain_id = "550e8400-e29b-41d4-a716-446655440000"
start_date = (datetime.now(timezone.utc) - timedelta(days=7)).isoformat(timespec="seconds")
reports = api_get(f"/domains/{domain_id}/reports/dmarc", {
"startDate": start_date
})
# The summary covers every report since start_date, not just the first page.
# passRate is None when there was nothing to rate (forwarded mail doesn't count)
pass_rate = reports["summary"]["passRate"]
if pass_rate is not None:
print(f"7-day DMARC pass rate: {pass_rate}%")Node.js / TypeScript
Each snippet uses the Setup code: put the setup and the snippets you need in one file, such as mailshield.ts.
Setup
typescript
const API_BASE = 'https://app.mailshield.app/api/v1';
const API_TOKEN = process.env.MAILSHIELD_API_TOKEN;
const headers = {
'Authorization': `Bearer ${API_TOKEN}`,
'Content-Type': 'application/json',
};
interface ApiResponse<T> {
data: T;
meta?: { pagination?: { page: number; limit: number; hasMore: boolean } };
}
async function request<T>(method: string, endpoint: string, body?: unknown): Promise<ApiResponse<T>> {
const response = await fetch(`${API_BASE}${endpoint}`, {
method,
headers,
body: body === undefined ? undefined : JSON.stringify(body),
});
const json = await response.json();
if (!response.ok) {
throw new Error(json.error.message);
}
return json as ApiResponse<T>;
}
async function apiGet<T>(endpoint: string): Promise<T> {
return (await request<T>('GET', endpoint)).data;
}
async function apiPost<T>(endpoint: string, body?: unknown): Promise<T> {
return (await request<T>('POST', endpoint, body)).data;
}
// Fetch every page of a list endpoint
async function apiGetAll<T>(endpoint: string): Promise<T[]> {
const items: T[] = [];
for (let page = 1; ; page++) {
const { data, meta } = await request<T[]>('GET', `${endpoint}?limit=100&page=${page}`);
items.push(...data);
if (!meta?.pagination?.hasMore) return items;
}
}
interface Domain {
id: string;
domain: string;
verified: boolean;
usageType: string;
}List All Domains
typescript
async function listDomains() {
const domains = await apiGetAll<Domain>('/domains');
for (const domain of domains) {
console.log(`${domain.domain}: verified=${domain.verified}`);
}
}
listDomains().catch(console.error);Add and Verify a Domain
typescript
interface CreatedDomain extends Domain {
verificationRecord: { hostname: string; type: string; value: string };
reporting: { ruaAddress: string; rufAddress: string; tlsRptAddress: string };
}
async function addDomain(): Promise<string> {
const newDomain = await apiPost<CreatedDomain>('/domains', {
domain: 'example.com',
testEmailLocalPart: 'admin',
});
const record = newDomain.verificationRecord;
console.log(`Add a ${record.type} record at ${record.hostname}: ${record.value}`);
return newDomain.id;
}
// Later, once the TXT record is published
async function verifyDomain(domainId: string) {
const result = await apiPost<{ verified: boolean; message: string }>(`/domains/${domainId}/verify`);
console.log(result.verified ? 'Verified' : result.message);
}
addDomain().then(verifyDomain).catch(console.error);Get Security Scores for All Domains
typescript
interface Score {
score: number | null;
grade: string | null;
label: string;
}
// One request per domain: with more than about 50 domains, pace the
// requests to stay under 60 per minute (see Rate Limiting)
async function printScores() {
const domains = await apiGetAll<Domain>('/domains');
for (const domain of domains) {
const score = await apiGet<Score>(`/domains/${domain.id}/score`);
if (score.score !== null) {
console.log(`${domain.domain}: ${score.score} (${score.grade})`);
} else {
console.log(`${domain.domain}: Not checked`);
}
}
}
printScores().catch(console.error);cURL
List Domains
bash
curl -H "Authorization: Bearer $MAILSHIELD_API_TOKEN" \
"https://app.mailshield.app/api/v1/domains?limit=100"Create Domain
bash
curl -X POST \
-H "Authorization: Bearer $MAILSHIELD_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"domain": "example.com", "testEmailLocalPart": "admin"}' \
https://app.mailshield.app/api/v1/domainsRun DNS Checks
bash
curl -X POST \
-H "Authorization: Bearer $MAILSHIELD_API_TOKEN" \
https://app.mailshield.app/api/v1/domains/550e8400-e29b-41d4-a716-446655440000/checksGet Score
bash
curl -H "Authorization: Bearer $MAILSHIELD_API_TOKEN" \
https://app.mailshield.app/api/v1/domains/550e8400-e29b-41d4-a716-446655440000/scoreGet DMARC Reports (Last 7 Days)
bash
# GNU date (Linux). On macOS, use: date -u -v-7d +%Y-%m-%d
START=$(date -u -d '7 days ago' +%Y-%m-%d)
curl -H "Authorization: Bearer $MAILSHIELD_API_TOKEN" \
"https://app.mailshield.app/api/v1/domains/550e8400-e29b-41d4-a716-446655440000/reports/dmarc?startDate=$START"Go
Setup
go
package main
import (
"encoding/json"
"fmt"
"net/http"
"os"
)
const apiBase = "https://app.mailshield.app/api/v1"
var apiToken = os.Getenv("MAILSHIELD_API_TOKEN")
// apiGet calls a GET endpoint and decodes the response's "data" into out.
// hasMore reports whether a list endpoint has another page.
func apiGet(endpoint string, out any) (hasMore bool, err error) {
req, err := http.NewRequest(http.MethodGet, apiBase+endpoint, nil)
if err != nil {
return false, err
}
req.Header.Set("Authorization", "Bearer "+apiToken)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return false, err
}
defer resp.Body.Close()
var body struct {
Data json.RawMessage `json:"data"`
Meta struct {
Pagination struct {
HasMore bool `json:"hasMore"`
} `json:"pagination"`
} `json:"meta"`
Error *struct {
Code string `json:"code"`
Message string `json:"message"`
} `json:"error"`
}
if err := json.NewDecoder(resp.Body).Decode(&body); err != nil {
return false, err
}
if body.Error != nil {
return false, fmt.Errorf("%s: %s", resp.Status, body.Error.Message)
}
return body.Meta.Pagination.HasMore, json.Unmarshal(body.Data, out)
}List Domains
go
type Domain struct {
ID string `json:"id"`
Domain string `json:"domain"`
Verified bool `json:"verified"`
}
func main() {
var all []Domain
for page := 1; ; page++ {
var domains []Domain
hasMore, err := apiGet(fmt.Sprintf("/domains?limit=100&page=%d", page), &domains)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
all = append(all, domains...)
if !hasMore {
break
}
}
for _, d := range all {
fmt.Printf("%s: verified=%v\n", d.Domain, d.Verified)
}
}