Access the SendGrid API with managed OAuth authentication. Send transactional and marketing emails, manage contacts, templates, suppressions, and analyze email performance.
# Get user profile
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/sendgrid/v3/user/profile')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
https://api.maton.ai/sendgrid/{native-api-path}
Maton proxies requests to api.sendgrid.com and automatically injects your OAuth token.
All requests require the Maton API key in the Authorization header:
Authorization: Bearer $MATON_API_KEY
Environment Variable: Set your API key as MATON_API_KEY:
export MATON_API_KEY="YOUR_API_KEY"
Manage your SendGrid OAuth connections at https://api.maton.ai.
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections?app=sendgrid&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'sendgrid'}).encode()
req = urllib.request.Request('https://api.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
{
"connection": {
"connection_id": "{connection_id}",
"status": "ACTIVE",
"creation_time": "2026-02-11T10:53:41.817938Z",
"last_updated_time": "2026-02-11T10:54:05.554084Z",
"url": "https://connect.maton.ai/?session_token=...",
"app": "sendgrid",
"metadata": {}
}
}
Open the returned url in a browser to complete OAuth authorization.
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If you have multiple SendGrid connections, specify which one to use with the Maton-Connection header:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/sendgrid/v3/user/profile')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Maton-Connection', '{connection_id}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If you have multiple connections, always include this header to ensure requests go to the intended account.
All SendGrid API endpoints follow this pattern:
/sendgrid/v3/{resource}
POST /sendgrid/v3/mail/send
Content-Type: application/json
{
"personalizations": [
{
"to": [{"email": "recipient@example.com", "name": "Recipient"}],
"subject": "Hello from SendGrid"
}
],
"from": {"email": "sender@example.com", "name": "Sender"},
"content": [
{
"type": "text/plain",
"value": "This is a test email."
}
]
}
With HTML content:
POST /sendgrid/v3/mail/send
Content-Type: application/json
{
"personalizations": [
{
"to": [{"email": "recipient@example.com"}],
"subject": "HTML Email"
}
],
"from": {"email": "sender@example.com"},
"content": [
{
"type": "text/html",
"value": "<h1>Hello</h1><p>This is an HTML email.</p>"
}
]
}
With template:
POST /sendgrid/v3/mail/send
Content-Type: application/json
{
"personalizations": [
{
"to": [{"email": "recipient@example.com"}],
"dynamic_template_data": {
"first_name": "John",
"order_id": "12345"
}
}
],
"from": {"email": "sender@example.com"},
"template_id": "d-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
GET /sendgrid/v3/user/profile
Response:
{
"type": "user",
"userid": 59796657
}
GET /sendgrid/v3/user/account
GET /sendgrid/v3/marketing/contacts
Response:
{
"result": [],
"contact_count": 0,
"_metadata": {
"self": "https://api.sendgrid.com/v3/marketing/contacts"
}
}
POST /sendgrid/v3/marketing/contacts/search
Content-Type: application/json
{
"query": "email LIKE '%@example.com%'"
}
PUT /sendgrid/v3/marketing/contacts
Content-Type: application/json
{
"contacts": [
{
"email": "contact@example.com",
"first_name": "John",
"last_name": "Doe"
}
]
}
Response:
{
"job_id": "2387e363-4104-4225-8960-4a5758492351"
}
Note: Contact operations are asynchronous. Use the job status endpoint to check progress.
GET /sendgrid/v3/marketing/contacts/imports/{job_id}
Response:
{
"id": "2387e363-4104-4225-8960-4a5758492351",
"status": "pending",
"job_type": "upsert_contacts",
"results": {
"requested_count": 1,
"created_count": 1
},
"started_at": "2026-02-11T11:00:14Z"
}
DELETE /sendgrid/v3/marketing/contacts?ids=contact_id_1,contact_id_2
GET /sendgrid/v3/marketing/contacts/{contact_id}
POST /sendgrid/v3/marketing/contacts/search/emails
Content-Type: application/json
{
"emails": ["contact@example.com"]
}
GET /sendgrid/v3/marketing/lists
Response:
{
"result": [],
"_metadata": {
"self": "https://api.sendgrid.com/v3/marketing/lists?page_size=100&page_token="
}
}
POST /sendgrid/v3/marketing/lists
Content-Type: application/json
{
"name": "My Contact List"
}
Response:
{
"name": "My Contact List",
"id": "b050f139-4231-47c8-bf32-94ad76376d3b",
"contact_count": 0,
"_metadata": {
"self": "https://api.sendgrid.com/v3/marketing/lists/b050f139-4231-47c8-bf32-94ad76376d3b"
}
}
GET /sendgrid/v3/marketing/lists/{list_id}
PATCH /sendgrid/v3/marketing/lists/{list_id}
Content-Type: application/json
{
"name": "Updated List Name"
}
DELETE /sendgrid/v3/marketing/lists/{list_id}
PUT /sendgrid/v3/marketing/contacts
Content-Type: application/json
{
"list_ids": ["list_id"],
"contacts": [
{"email": "contact@example.com"}
]
}
GET /sendgrid/v3/marketing/segments
POST /sendgrid/v3/marketing/segments
Content-Type: application/json
{
"name": "Active Users",
"query_dsl": "email_clicks > 0"
}
GET /sendgrid/v3/marketing/segments/{segment_id}
DELETE /sendgrid/v3/marketing/segments/{segment_id}
GET /sendgrid/v3/templates
With generation filter:
GET /sendgrid/v3/templates?generations=dynamic
POST /sendgrid/v3/templates
Content-Type: application/json
{
"name": "My Template",
"generation": "dynamic"
}
Response:
{
"id": "d-ffcdb43ed8a04beba48a702e1717ddb5",
"name": "My Template",
"generation": "dynamic",
"updated_at": "2026-02-11 11:00:20",
"versions": []
}
GET /sendgrid/v3/templates/{template_id}
PATCH /sendgrid/v3/templates/{template_id}
Content-Type: application/json
{
"name": "Updated Template Name"
}
DELETE /sendgrid/v3/templates/{template_id}
POST /sendgrid/v3/templates/{template_id}/versions
Content-Type: application/json
{
"name": "Version 1",
"subject": "{{subject}}",
"html_content": "<html><body><h1>Hello {{name}}</h1></body></html>",
"active": 1
}
Response:
{
"id": "54230a99-1e89-4edf-821d-d4925b40c64b",
"template_id": "d-ffcdb43ed8a04beba48a702e1717ddb5",
"active": 1,
"name": "Version 1",
"html_content": "<html><body><h1>Hello {{name}}</h1></body></html>",
"plain_content": "Hello {{name}}",
"generate_plain_content": true,
"subject": "{{subject}}",
"editor": "code",
"thumbnail_url": "//..."
}
GET /sendgrid/v3/senders
POST /sendgrid/v3/senders
Content-Type: application/json
{
"nickname": "My Sender",
"from": {"email": "sender@example.com", "name": "Sender Name"},
"reply_to": {"email": "reply@example.com", "name": "Reply To"},
"address": "123 Main St",
"city": "San Francisco",
"country": "USA"
}
Response:
{
"id": 8513177,
"nickname": "My Sender",
"from": {"email": "sender@example.com", "name": "Sender Name"},
"reply_to": {"email": "reply@example.com", "name": "Reply To"},
"address": "123 Main St",
"city": "San Francisco",
"country": "USA",
"verified": {"status": false, "reason": null},
"updated_at": 1770786031,
"created_at": 1770786031,
"locked": false
}
Note: Sender verification is required before use. Check verified.status.
GET /sendgrid/v3/senders/{sender_id}
PATCH /sendgrid/v3/senders/{sender_id}
Content-Type: application/json
{
"nickname": "Updated Sender Name"
}
DELETE /sendgrid/v3/senders/{sender_id}
# List bounces
GET /sendgrid/v3/suppression/bounces
# Get bounce by email
GET /sendgrid/v3/suppression/bounces/{email}
# Delete bounces
DELETE /sendgrid/v3/suppression/bounces
Content-Type: application/json
{
"emails": ["bounce@example.com"]
}
# List blocks
GET /sendgrid/v3/suppression/blocks
# Get block by email
GET /sendgrid/v3/suppression/blocks/{email}
# Delete blocks
DELETE /sendgrid/v3/suppression/blocks
Content-Type: application/json
{
"emails": ["blocked@example.com"]
}
# List invalid emails
GET /sendgrid/v3/suppression/invalid_emails
# Delete invalid emails
DELETE /sendgrid/v3/suppression/invalid_emails
Content-Type: application/json
{
"emails": ["invalid@example.com"]
}
# List spam reports
GET /sendgrid/v3/suppression/spam_reports
# Delete spam reports
DELETE /sendgrid/v3/suppression/spam_reports
Content-Type: application/json
{
"emails": ["spam@example.com"]
}
# List global unsubscribes
GET /sendgrid/v3/suppression/unsubscribes
# Add to global unsubscribes
POST /sendgrid/v3/asm/suppressions/global
Content-Type: application/json
{
"recipient_emails": ["unsubscribe@example.com"]
}
GET /sendgrid/v3/asm/groups
POST /sendgrid/v3/asm/groups
Content-Type: application/json
{
"name": "Weekly Newsletter",
"description": "Weekly newsletter updates"
}
Response:
{
"name": "Weekly Newsletter",
"id": 122741,
"description": "Weekly newsletter updates",
"is_default": false
}
GET /sendgrid/v3/asm/groups/{group_id}
PATCH /sendgrid/v3/asm/groups/{group_id}
Content-Type: application/json
{
"name": "Updated Group Name"
}
DELETE /sendgrid/v3/asm/groups/{group_id}
POST /sendgrid/v3/asm/groups/{group_id}/suppressions
Content-Type: application/json
{
"recipient_emails": ["user@example.com"]
}
GET /sendgrid/v3/asm/groups/{group_id}/suppressions
GET /sendgrid/v3/stats?start_date=2026-02-01
With end date:
GET /sendgrid/v3/stats?start_date=2026-02-01&end_date=2026-02-28
Response:
[
{
"date": "2026-02-01",
"stats": [
{
"metrics": {
"blocks": 0,
"bounce_drops": 0,
"bounces": 0,
"clicks": 0,
"deferred": 0,
"delivered": 0,
"invalid_emails": 0,
"opens": 0,
"processed": 0,
"requests": 0,
"spam_report_drops": 0,
"spam_reports": 0,
"unique_clicks": 0,
"unique_opens": 0,
"unsubscribe_drops": 0,
"unsubscribes": 0
}
}
]
}
]
GET /sendgrid/v3/categories/stats?start_date=2026-02-01&categories=category1,category2
GET /sendgrid/v3/mailbox_providers/stats?start_date=2026-02-01
GET /sendgrid/v3/browsers/stats?start_date=2026-02-01
> Credential management. API key operations create, modify, or delete long-lived SendGrid credentials that persist independently of the Maton OAuth session. A created key can be used outside this integration. Only invoke when the user explicitly requests API key management. Never log or display created key values.
GET /sendgrid/v3/api_keys
Response:
{
"result": [
{
"name": "MatonTest",
"api_key_id": "WJBgv5EKR8y0nn2F8Qfk5w"
}
]
}
POST /sendgrid/v3/api_keys
Content-Type: application/json
{
"name": "New API Key",
"scopes": ["mail.send", "alerts.read"]
}
GET /sendgrid/v3/api_keys/{api_key_id}
PATCH /sendgrid/v3/api_keys/{api_key_id}
Content-Type: application/json
{
"name": "Updated Key Name"
}
DELETE /sendgrid/v3/api_keys/{api_key_id}
SendGrid uses token-based pagination for marketing endpoints:
GET /sendgrid/v3/marketing/lists?page_size=100&page_token={token}
Response includes:
{
"result": [...],
"_metadata": {
"self": "https://api.sendgrid.com/v3/marketing/lists?page_size=100&page_token=",
"next": "https://api.sendgrid.com/v3/marketing/lists?page_size=100&page_token=abc123"
}
}
For suppression endpoints, use limit and offset:
GET /sendgrid/v3/suppression/bounces?limit=100&offset=0
// Send an email
const response = await fetch(
'https://api.maton.ai/sendgrid/v3/mail/send',
{
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.MATON_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
personalizations: [{
to: [{email: 'recipient@example.com'}],
subject: 'Hello'
}],
from: {email: 'sender@example.com'},
content: [{type: 'text/plain', value: 'Hello World'}]
})
}
);
import os
import requests
# Get email stats
response = requests.get(
'https://api.maton.ai/sendgrid/v3/stats',
headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'},
params={'start_date': '2026-02-01'}
)
data = response.json()
for day in data:
metrics = day['stats'][0]['metrics']
print(f"{day['date']}: {metrics['delivered']} delivered, {metrics['opens']} opens")
d-start_time and end_time (Unix timestamps)curl -g when URLs contain brackets to disable glob parsingjq or other commands, environment variables like $MATON_API_KEY may not expand correctly in some shell environments| Status | Meaning |
|---|---|
| -------- | --------- |
| 400 | Bad request or validation error |
| 401 | Invalid or missing Maton API key |
| 403 | Insufficient permissions |
| 404 | Resource not found |
| 429 | Rate limited |
| 500 | Internal server error |
MATON_API_KEY environment variable is set:[ -n "$MATON_API_KEY" ] && echo "MATON_API_KEY is set" || echo "MATON_API_KEY is not set"
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
sendgrid. For example:https://api.maton.ai/sendgrid/v3/user/profilehttps://api.maton.ai/v3/user/profile共 3 个版本