Skip to content

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"] += 1

List 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/domains

Run DNS Checks ​

bash
curl -X POST \
  -H "Authorization: Bearer $MAILSHIELD_API_TOKEN" \
  https://app.mailshield.app/api/v1/domains/550e8400-e29b-41d4-a716-446655440000/checks

Get Score ​

bash
curl -H "Authorization: Bearer $MAILSHIELD_API_TOKEN" \
  https://app.mailshield.app/api/v1/domains/550e8400-e29b-41d4-a716-446655440000/score

Get 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)
	}
}

Monitor and secure your email domains.