SendGrid
SendGrid API integration with managed OAuth. Send emails, manage contacts, templates, suppressions, and view email statistics. Use this skill when users want to send transactional or marketing emails,
SendGrid API integration with managed OAuth. Send emails, manage contacts, templates, suppressions, and view email statistics. Use this skill when users want to send transactional or marketing emails,
Real data. Real impact.
Growing
Developers
Per week
Open source
Skills give you superpowers. Install in 30 seconds.
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://gateway.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://gateway.maton.ai/sendgrid/{native-api-path}
Replace
{native-api-path} with the actual SendGrid API endpoint path. The gateway 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://ctrl.maton.ai.
python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.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://ctrl.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://ctrl.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": "943c6cd5-9a56-4f5b-8adf-ecd4a140049f", "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://ctrl.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://gateway.maton.ai/sendgrid/v3/user/profile') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Maton-Connection', '943c6cd5-9a56-4f5b-8adf-ecd4a140049f') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
If omitted, the gateway uses the default (oldest) active connection.
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/bouncesGet 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/blocksGet 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_emailsDelete invalid emails
DELETE /sendgrid/v3/suppression/invalid_emails Content-Type: application/json
{ "emails": ["invalid@example.com"] }
# List spam reports GET /sendgrid/v3/suppression/spam_reportsDelete spam reports
DELETE /sendgrid/v3/suppression/spam_reports Content-Type: application/json
{ "emails": ["spam@example.com"] }
# List global unsubscribes GET /sendgrid/v3/suppression/unsubscribesAdd 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
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://gateway.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 requestsGet email stats
response = requests.get( 'https://gateway.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:echo $MATON_API_KEY
python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.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://gateway.maton.ai/sendgrid/v3/user/profilehttps://gateway.maton.ai/v3/user/profileNo automatic installation available. Please visit the source repository for installation instructions.
View Installation Instructions1,500+ AI skills, agents & workflows. Install in 30 seconds. Part of the Torly.ai family.
© 2026 Torly.ai. All rights reserved.