API Tokens

SpoofWard provides a comprehensive REST API for automating DMARC management, integrating with your tools, and building custom workflows. This guide explains how to create and manage API tokens.

What is the SpoofWard API?

The API allows you to programmatically:

  • Retrieve DMARC reports - Integrate report data into your systems
  • Manage domains - Add, update, and delete domains
  • Manage senders - Authorize, block, or investigate senders
  • Update DNS records - Configure SPF, DKIM, DMARC programmatically
  • Trigger scans - Initiate domain scans on demand
  • Export data - Bulk export reports and analytics
  • Manage team members - Add/remove users programmatically
  • Create webhooks - Listen for real-time events

Getting Started

Step 1: Create an API Token

  1. Log in to SpoofWard
  2. Go to Settings → API Tokens
  3. Click Create Token
  4. Name your token (e.g., "Slack Integration" or "Report Export")
  5. Select scopes (permissions) needed
  6. Click Generate

Step 2: Copy Your Token

Important: Copy the token immediately. You won't see it again.


swapi_1a2b3c4d5e6f7g8h9i0j

Store it securely:

  • Never commit to Git
  • Never share in Slack/email
  • Store in environment variable or secrets manager
  • Only share with trusted integrations

Step 3: Use in API Calls

Include token in request header:


curl -H "Authorization: Bearer swapi_1a2b3c4d5e6f7g8h9i0j" \
  https://api.spoofward.com/v1/domains

Or in your code:


import requests

headers = {
    "Authorization": "Bearer swapi_1a2b3c4d5e6f7g8h9i0j"
}

response = requests.get(
    "https://api.spoofward.com/v1/domains",
    headers=headers
)

Token Scopes (Permissions)

Each token has scopes that limit what it can do:

Domains

  • domains:read - View domains
  • domains:write - Create/update/delete domains
  • domains:scan - Trigger domain scans

Reports

  • reports:read - View DMARC reports
  • reports:export - Export reports to CSV/JSON

Senders

  • senders:read - View email sources
  • senders:write - Authorize/block/investigate senders

DNS

  • dns:read - View DNS records
  • dns:write - Update DNS records (Hosted DNS only)

Team

  • team:read - View team members
  • team:write - Invite/remove/manage team members

Webhooks

  • webhooks:read - View webhooks
  • webhooks:write - Create/update/delete webhooks

Best practice: Use minimal scopes. If integration only reads reports, only grant reports:read.

Common Use Cases

Use Case 1: Export Reports

Export DMARC reports to your data warehouse:


import requests
import json

api_token = "swapi_1a2b3c4d5e6f7g8h9i0j"
domain = "example.com"

headers = {"Authorization": f"Bearer {api_token}"}

# Get reports for last 30 days
response = requests.get(
    f"https://api.spoofward.com/v1/domains/{domain}/reports",
    headers=headers,
    params={"days": 30}
)

reports = response.json()

# Save to file
with open("dmarc_reports.json", "w") as f:
    json.dump(reports, f)

Use Case 2: Slack Notifications

Get alerts when senders change:


from flask import Flask, request
import requests

app = Flask(__name__)

@app.route("/webhook/senders", methods=["POST"])
def sender_webhook():
    data = request.json

    if data["event"] == "sender_discovered":
        sender = data["sender"]["name"]
        volume = data["sender"]["volume"]

        # Post to Slack
        slack_message = f"New sender discovered: {sender} ({volume} messages)"
        requests.post(
            os.environ["SLACK_WEBHOOK"],
            json={"text": slack_message}
        )

    return "OK", 200

Use Case 3: Auto-Authorize Known Services

Approve known services automatically:


import requests

api_token = "swapi_1a2b3c4d5e6f7g8h9i0j"
domain = "example.com"

known_services = [
    "SendGrid",
    "Mailchimp",
    "Office 365"
]

headers = {"Authorization": f"Bearer {api_token}"}

# Get all senders
response = requests.get(
    f"https://api.spoofward.com/v1/domains/{domain}/senders",
    headers=headers
)

senders = response.json()

# Authorize known ones
for sender in senders:
    if sender["name"] in known_services:
        requests.post(
            f"https://api.spoofward.com/v1/domains/{domain}/senders/{sender['id']}/authorize",
            headers=headers
        )

Use Case 4: Compliance Reporting

Generate compliance reports automatically:


import requests
from datetime import datetime, timedelta

api_token = "swapi_1a2b3c4d5e6f7g8h9i0j"

headers = {"Authorization": f"Bearer {api_token}"}

# Get all domains
domains_response = requests.get(
    "https://api.spoofward.com/v1/domains",
    headers=headers
)

domains = domains_response.json()

# Generate report for each domain
report = {
    "date": datetime.now().isoformat(),
    "domains": []
}

for domain in domains:
    # Get current score
    score_response = requests.get(
        f"https://api.spoofward.com/v1/domains/{domain['id']}/score",
        headers=headers
    )

    score = score_response.json()

    report["domains"].append({
        "name": domain["name"],
        "dmarc_score": score["dmarc_score"],
        "policy": score["policy"],
        "pass_rate": score["pass_rate"]
    })

print(json.dumps(report, indent=2))

API Endpoints

Domains

List domains:


GET /v1/domains

Get domain details:


GET /v1/domains/{domain_id}

Add domain:


POST /v1/domains
{
  "name": "example.com",
  "description": "Main domain"
}

Update domain:


PATCH /v1/domains/{domain_id}
{
  "description": "Updated description"
}

Delete domain:


DELETE /v1/domains/{domain_id}

Reports

List reports:


GET /v1/domains/{domain_id}/reports?days=30

Get specific report:


GET /v1/domains/{domain_id}/reports/{report_id}

Export reports:


GET /v1/domains/{domain_id}/reports/export?format=csv&days=30

Senders

List senders:


GET /v1/domains/{domain_id}/senders

Get sender details:


GET /v1/domains/{domain_id}/senders/{sender_id}

Authorize sender:


POST /v1/domains/{domain_id}/senders/{sender_id}/authorize

Block sender:


POST /v1/domains/{domain_id}/senders/{sender_id}/block

Update sender:


PATCH /v1/domains/{domain_id}/senders/{sender_id}
{
  "notes": "Our marketing platform",
  "status": "authorized"
}

DNS Records

Get DNS records:


GET /v1/domains/{domain_id}/dns-records

Update DNS record (Hosted DNS only):


PATCH /v1/domains/{domain_id}/dns-records/{record_id}
{
  "value": "v=spf1 include:sendgrid.net ~all"
}

Team Members

List team members:


GET /v1/organization/team

Invite member:


POST /v1/organization/team/invite
{
  "email": "[email protected]",
  "role": "analyst"
}

Remove member:


DELETE /v1/organization/team/{member_id}

Webhooks

Webhooks deliver real-time events to your system.

Available Events

  • report.received - New DMARC report arrived
  • sender.discovered - New email sender found
  • sender.authorized - Sender marked as authorized
  • sender.blocked - Sender marked as blocked
  • dns.changed - DNS record updated
  • policy.updated - DMARC policy changed
  • threat.detected - Suspicious activity flagged

Setting Up Webhooks

  1. Settings → Webhooks
  2. Click Add Webhook
  3. Enter your webhook URL
  4. Select events to subscribe to
  5. Click Create

SpoofWard will POST to your URL when events occur.

Webhook Payload

Example payload when report arrives:


{
  "event": "report.received",
  "timestamp": "2024-01-15T10:30:00Z",
  "domain_id": "d_123abc",
  "domain_name": "example.com",
  "data": {
    "report_id": "r_456def",
    "period": "2024-01-14",
    "messages": 5000,
    "pass_rate": 0.95,
    "policy": "none"
  }
}

Verifying Webhook Signature

Webhooks include an X-SpoofWard-Signature header for verification:


import hmac
import hashlib

def verify_webhook(payload, signature, secret):
    expected = hmac.new(
        secret.encode(),
        payload.encode(),
        hashlib.sha256
    ).hexdigest()

    return hmac.compare_digest(signature, expected)

Managing Tokens

List Your Tokens

  1. Settings → API Tokens
  2. See all tokens you've created
  3. Shows last 4 digits only (rest hidden for security)
  4. Shows creation date and last used

Revoke a Token

If token is compromised or no longer needed:

  1. Click token in list
  2. Click Revoke
  3. Token immediately becomes invalid
  4. Can't be recovered (generate new one if needed)

Token Rotation

Best practice: Rotate tokens periodically

  1. Create new token
  2. Update your application
  3. Test the new token works
  4. Revoke old token

Recommend rotating yearly or if compromised.

Rate Limits

API has rate limits to prevent abuse:

  • Free plan - 100 requests/hour
  • Pro plan - 1,000 requests/hour
  • Business plan - 10,000 requests/hour
  • Enterprise - Custom limits

Rate limit headers in response:


X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 875
X-RateLimit-Reset: 1641024000

If you exceed limit, requests return 429 status.

Error Handling

API returns standard HTTP status codes:

  • 200 - Success
  • 400 - Bad request (invalid parameters)
  • 401 - Unauthorized (bad token)
  • 403 - Forbidden (insufficient permissions)
  • 404 - Not found
  • 429 - Rate limited
  • 500 - Server error

Error response:


{
  "error": "unauthorized",
  "message": "Invalid API token"
}

Security Best Practices

Store tokens securely:

  • Use environment variables
  • Use secrets manager (AWS Secrets Manager, HashiCorp Vault)
  • Never commit to code

Use minimal scopes:

  • Don't grant all permissions
  • Use only what integration needs
  • Review and remove unused tokens

Rotate tokens regularly:

  • Yearly or after changes
  • Immediately if exposed
  • Keep old token revoked

Monitor usage:

  • Check "last used" timestamp
  • Remove old unused tokens
  • Track which apps use which tokens

Limit distribution:

  • Don't share tokens between apps
  • Create separate token per integration
  • Easier to track and revoke

Documentation

Full API documentation available at:

https://docs.spoofward.com/api/

Includes:

  • Detailed endpoint reference
  • Code examples (Python, JavaScript, Go, etc.)
  • Authentication details
  • Rate limiting info
  • Error codes
  • SDK libraries

Support

For API issues:

  1. Check documentation
  2. Review error message
  3. Contact support with:
  • Error details
  • Request method/endpoint
  • (Don't share actual token)

Related Documentation

Your domain is being tested right now.
Are you watching?

Protect your brand and improve deliverability — automatically, with continuous monitoring and alerts.