Skip to content

SendGrid v3 REST API: Full API Reference for Email Operations

DodaTech Updated 2026-06-28 4 min read

In this tutorial, you will learn about SendGrid v3 REST API: Full API Reference for Email Operations. We cover key concepts, practical examples, and best practices to help you master this topic.

SendGrid v3 REST API provides endpoints for managing every aspect of your account — contacts, lists, templates, settings, IP pools, subusers, and detailed email operations.

What You'll Learn

How to use SendGrid's v3 API endpoints beyond mail/send: manage contacts and lists, create and manage templates, configure mail settings, manage IP pools, and work with subusers.

Why It Matters

The mail/send endpoint is just the start. Managing contacts, templates, and settings via API enables automation of the entire email infrastructure. DodaTech manages 500K+ contacts and 20+ templates entirely through the API.

Real-World Use

A sign-up flow creates a contact via API, adds them to the "new-users" list, and triggers a welcome email — all in one automated workflow.

flowchart LR
    A["API Call\nPOST /v3/marketing/contacts"] --> B["Manage\nContacts"]
    A --> C["POST /v3/templates\nManage Templates"]
    A --> D["GET /v3/stats\nAnalytics"]
    A --> E["POST /v3/asm/groups\nSuppressions"]
    B --> F["Add to List\nSegment Users"]
    C --> G["Create Version\nActivate"]
    style A fill:#dbeafe,stroke:#2563eb
    style B fill:#fef3c7,stroke:#d97706
    style C fill:#bbf7d0,stroke:#16a34a

Managing Contacts

import requests

API_KEY = os.environ["SENDGRID_API_KEY"]
BASE_URL = "https://api.sendgrid.com/v3"
HEADERS = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json"
}

def create_contact(email, first_name, last_name, custom_fields):
    data = {
        "contacts": [{
            "email": email,
            "first_name": first_name,
            "last_name": last_name,
            "custom_fields": custom_fields
        }]
    }
    response = requests.put(
        f"{BASE_URL}/marketing/contacts",
        headers=HEADERS,
        json=data
    )
    print(f"Contact created: {response.status_code}")
    return response.json()

create_contact(
    "alice@example.com", "Alice", "Smith",
    {"subscription_tier": "pro", "device_count": 3}
)
# Expected output: Contact created: 202

Creating Lists and Segments

def create_list(name):
    data = {"name": name}
    response = requests.post(
        f"{BASE_URL}/marketing/lists",
        headers=HEADERS,
        json=data
    )
    list_data = response.json()
    print(f"List created: {list_data['id']} ({list_data['name']})")
    return list_data

def create_segment(name, query):
    # Segment query DSL: https://docs.sendgrid.com/ui/managing-contacts/segmenting-your-contacts
    data = {
        "name": name,
        "query": query  # e.g., "last_clicked > 30 days ago"
    }
    response = requests.post(
        f"{BASE_URL}/marketing/segments",
        headers=HEADERS,
        json=data
    )
    print(f"Segment created: {response.json()['id']}")

free_users = create_list("Free Tier Users")
pro_users = create_list("Pro Tier Users")
inactive_segment = create_segment("Inactive 30 Days", "last_opened < '2026-05-28'")
# Expected output: List created: 12345 (Free Tier Users)

Managing Templates via API

def create_template(name):
    data = {"name": name}
    response = requests.post(
        f"{BASE_URL}/templates",
        headers=HEADERS,
        json=data
    )
    template = response.json()
    print(f"Template: {template['id']}")
    return template

def create_template_version(template_id, name, html_content, subject):
    data = {
        "template_id": template_id,
        "name": name,
        "html_content": html_content,
        "subject": subject,
        "active": 1
    }
    response = requests.post(
        f"{BASE_URL}/templates/{template_id}/versions",
        headers=HEADERS,
        json=data
    )
    print(f"Version created: {response.json()['id']}")

template = create_template("weekly-report")
create_template_version(
    template["id"],
    "v1",
    "<h1>Hi {{name}}</h1><p>Your report: {{report_url}}</p>",
    "Weekly Security Report for {{name}}"
)

Mail Settings API

def update_mail_settings():
    # Update bounce forwarding
    data = {"enabled": True, "email": "bounces@dodatech.com"}
    response = requests.patch(
        f"{BASE_URL}/mail_settings/bounce_push",
        headers=HEADERS,
        json=data
    )
    print(f"Bounce settings: {response.status_code}")

    # Update spam check
    data = {"enabled": True, "spam_threshold": 5}
    response = requests.patch(
        f"{BASE_URL}/mail_settings/spam_check",
        headers=HEADERS,
        json=data
    )
    print(f"Spam check: {response.status_code}")

    # Get current settings
    response = requests.get(f"{BASE_URL}/mail_settings", headers=HEADERS)
    settings = response.json()
    for setting in settings.get("result", []):
        print(f"  {setting['name']}: {'ON' if setting['enabled'] else 'OFF'}")

Common Mistakes

1. Rate Limiting

The v3 API has rate limits (varies by endpoint). Check X-RateLimit-Remaining headers and implement backoff when approaching limits.

2. Using PUT Instead of PATCH

Some endpoints require PATCH for partial updates. Using PUT replaces the entire resource. Check the API docs for the correct method.

3. Not Handling Pagination

List endpoints return paginated results. Use _metadata.next or offset/limit parameters to iterate through all results.

4. API Key Permission Mismatch

Not all API keys have access to all endpoints. Mail Send keys can't manage contacts. Create separate keys with appropriate scopes for each use case.

5. Ignoring API Version Changes

The v3 API evolves. Subscribe to SendGrid changelog and test API calls after updates. Deprecated endpoints are announced with Migration timelines.

Practice Questions

  1. How do you create a new contact via the API?
  2. How do you manage template versions programmatically?
  3. How do you handle rate limits in the v3 API?
  4. How do you retrieve paginated results?

Answers:

  1. PUT /v3/marketing/contacts with contacts array. Use upsert to update existing contacts.
  2. POST /v3/templates/{id}/versions to create, PATCH to update, DELETE to remove. Set active: 1 to activate.
  3. Check X-RateLimit-Remaining and X-RateLimit-Reset headers. Implement exponential backoff with jitter on 429 responses.
  4. Use limit and offset query parameters. Check _metadata.next in responses for the next page URL.

Challenge: Build a contact management system: create contacts via API, assign to lists (free/pro based on subscription), create segments for inactive users, manage templates programmatically, and automate list cleanup via the API.

FAQ

What is the base URL for the v3 API?

https://api.sendgrid.com/v3

How do I authenticate with the v3 API?

Include Authorization: Bearer YOUR_API_KEY header in all requests.

Can I manage subusers via the API?

Yes, endpoints under POST /v3/subusers for creating and managing subusers.

What content types does the v3 API accept?

Request body must be application/json. File uploads for templates use multipart/form-data.

How do I test API calls without affecting production?

Create a separate SendGrid account or subuser for testing. Use different API keys per environment.

Mini Project

Build a full contact management workflow: create contacts via API (with custom fields), organize into lists (free/pro/enterprise), create segments (inactive 30 days), manage dynamic templates, and integrate with the mail/send endpoint for targeted campaigns.

What's Next

Subuser Management — manage multi-account email sending with subusers.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro