Retrieve activity for a specific SendGrid message with the Email Logs API.
Purpose
This skill is for reading SendGrid Email Logs and per-message activity.
It has two lookup paths:
scripts/get_email_log.shcallsGET /v3/logs/{sg_message_id}for one specific message and computes anevent_summary. If the fullsg_message_idis not known, it can first callPOST /v3/logswith recipient and sent time to resolve the full ID, then automatically call the detail endpoint.scripts/query_email_logs.shcallsPOST /v3/logsto search Email Logs by recipient, status, time, optional subject, raw query, and fuzzy message ID matching.
Inputs:
- full
sg_message_idfrom SendGrid Email Logs for the direct by-ID path, or any useful Email Logs search filters such as recipient, sender, sent time, subject, status, start/end time, raw query, and optional Mail Sendmessage_idfor the search-then-detail path - SendGrid API key from
--api-key,SENDGRID_API_KEY, or the locally saved SendGrid key
Output:
- raw SendGrid JSON by default
- optional
event_summaryadded by the script, including booleans such asopened,clicked,delivered,bounced,deferred,dropped,spam_reported, andunsubscribed log_resolutionwhenget_email_log.shresolves the fullsg_message_idbefore fetching detailsmatched_messages,matched_count, and_match_reasonwhen usingquery_email_logs.shdirectly with--message-id- optional saved JSON file when
--outputis provided - dry-run request metadata when
--dry-runis used
This is a read-only lookup. It does not send email and does not retrieve account-level aggregate stats.
What This Skill Needs
- full
sg_message_id, or recipient and sent-time search criteria for Email Logs - a SendGrid API key, usually
SENDGRID_API_KEY curlbashpython3
API key resolution order:
--api-keyfor the current runSENDGRID_API_KEY- locally saved key at
~/.config/sendgrid-send-email/api_key
The saved key path intentionally matches sendgrid-send-email so users who configured the SendGrid send skill can reuse the same key. If no API key is available and the script is running interactively, prompt once and save it locally for future runs. If no API key is available in a non-interactive run, guide the user to read the SendGrid integration guide: https://frevana.gitbook.io/frevana-docs/email-integrations/sendgrid-integration.
Users can update the saved API key with:
bash <skill-path>/scripts/get_email_log.sh --api-key "SG..." --save-api-key
or clear it with:
bash <skill-path>/scripts/get_email_log.sh --clear-api-key
Execution Order
- Extract full
sg_message_idfor direct by-ID lookups. If the user only has the Mail Sendx-message-id, has an incomplete ID, or does not know the ID, collect as many search filters as available (to,from,sent_at,subject,status,start_time,end_time, or rawquery) and letget_email_log.shresolve the fullsg_message_idfirst. - Prefer
scripts/get_email_log.shorscripts/query_email_logs.shover ad hoccurl. - Use
--dry-runwhen the user wants to inspect the URL before calling SendGrid. - Let the script use
--api-key,SENDGRID_API_KEY, or the locally saved key. - In non-interactive agent runs, fail fast if the API key is missing from all supported sources.
- Return raw JSON when requested; otherwise summarize the
event_summary, matched messages, or recent activity events.
Commands
Check one message
bash <skill-path>/scripts/get_email_log.sh \
--sg-message-id "abc123.recvd-xxxxxxxx"
Check whether it opened or clicked
bash <skill-path>/scripts/get_email_log.sh \
--sg-message-id "abc123.recvd-xxxxxxxx" \
--summary-only
Search Email Logs by recipient, sent time, and fuzzy message ID
Use this when the user has the x-message-id returned by Mail Send but needs to locate the Email Logs sg_message_id first. get_email_log.sh narrows Email Logs with to_email and sg_message_id_created_at >= (--sent-at - 5 seconds) by default, optionally adds an exact subject filter, fuzzy-matches returned messages[].sg_message_id against the Mail Send response x-message-id, then fetches the detail record with GET /v3/logs/{sg_message_id}.
If the user does not know any message ID, omit --message-id; the script uses the first returned Email Logs message after applying the provided filters, so pass more filters to avoid ambiguity.
For dynamic template sends, omit --subject because the template can define or override the final email subject.
bash <skill-path>/scripts/get_email_log.sh \
--to "customer@example.com" \
--sent-at "2026-06-15T10:37:21Z" \
--message-id "abc123..." \
--limit 100
Search Email Logs without a message ID, then fetch details
bash <skill-path>/scripts/get_email_log.sh \
--to "customer@example.com" \
--from "sender@example.com" \
--start-time "2026-06-15T10:00:00Z" \
--end-time "2026-06-15T11:00:00Z" \
--subject "Order update" \
--status delivered \
--limit 20
Search Email Logs with a raw query
Use this lower-level script when the user only wants search results from POST /v3/logs and does not need the detail endpoint.
bash <skill-path>/scripts/query_email_logs.sh \
--query "to_email = 'customer@example.com' AND status IN ('delivered', 'processed')" \
--limit 10
Parent account querying a subuser or customer account
bash <skill-path>/scripts/get_email_log.sh \
--sg-message-id "abc123.recvd-xxxxxxxx" \
--on-behalf-of "subuser-username"
For customer accounts, pass the full header value, such as:
--on-behalf-of "account-id 123456"
Dry-run request metadata
bash <skill-path>/scripts/get_email_log.sh \
--sg-message-id "abc123.recvd-xxxxxxxx" \
--dry-run
Fixed Request Shape
For by-ID activity lookup, the script sends a GET request to:
- global region:
https://api.sendgrid.com/v3/logs/{sg_message_id} - EU region:
https://api.eu.sendgrid.com/v3/logs/{sg_message_id}
Supported headers:
Authorization: Bearer <SENDGRID_API_KEY>- optional
on-behalf-of: <subuser-username>oron-behalf-of: account-id <account-id>
Do not invent query parameters. This endpoint reads one message by ID through the URL path.
For search lookup, the script sends a POST request to:
- global region:
https://api.sendgrid.com/v3/logs - EU region:
https://api.eu.sendgrid.com/v3/logs
Supported body fields:
querylimit- optional
subusers
Do not use custom_args.business_id for Email Logs queries. Use recipient, optional subject, --sent-at, and message ID fuzzy matching, or pass a raw account-supported --query.
Script Options
--sg-message-id ID; full SendGrid Email Logs ID for direct activity retrieval--to EMAIL; recipient email used to resolve the fullsg_message_id--from EMAIL; sender email used to resolve the fullsg_message_id--sent-at ISO_TIME; sent/queued time used as the lower bound for resolving the fullsg_message_id--message-id ID; optional Mail Sendx-message-idused for fuzzy matching during resolution--subject SUBJECT; optional exact subject filter during resolution--status STATUS; optional status filter, repeatable or comma-separated--start-time ISO_TIME; optional lower bound for resolution search--end-time ISO_TIME; optional upper bound for resolution search--query QUERY; raw SendGrid Email Logs query string for resolution search, overriding generated filters--sent-at-lookback-seconds N; default5, allowed0-300--limit N; search-result limit during resolution, default100, allowed1-1000--on-behalf-of VALUE; optional SendGrid parent-account header value--subuser ID; optional numeric SendGrid subuser ID forPOST /v3/logssearch, repeatable or comma-separated--region global|eu; defaultglobal--api-key KEYfor a one-time override--save-api-keyto save the--api-keyvalue for future runs--configure-api-keyto prompt for and save the key--clear-api-keyto remove the locally saved key--output PATHto save JSON--summary-onlyto print only the computed event summary--dry-runto print request metadata without calling SendGrid
scripts/query_email_logs.sh supports:
--query QUERY; raw SendGrid Email Logs query string--status STATUS; repeatable or comma-separated--to EMAIL--sent-at ISO_TIME--sent-at-lookback-seconds N; default5, allowed0-300--message-id ID; fuzzy-matches returnedsg_message_id--subject SUBJECT--start-time ISO_TIME--end-time ISO_TIME--limit N; default10, allowed1-1000--subuser ID- shared
--region,--api-key,--save-api-key,--configure-api-key,--clear-api-key,--output, and--dry-run
Notes
- Never echo or store the API key in user-visible output.
- The script can save the API key locally at
~/.config/sendgrid-send-email/api_keywith file permission600; do not print the key value back to the user. - Use
--api-key <key> --save-api-keyor--configure-api-keywhen the user wants to update the saved key. Use--clear-api-keywhen the user wants to remove it. - If the user only has a Mail Send
x-message-id, the send result may be incomplete forGET /v3/logs/{sg_message_id}. Preferscripts/get_email_log.sh --to ... --sent-at ... --message-id ...so the script first resolves the full Email Logssg_message_idwithPOST /v3/logs, then fetches details. - If the user does not know any message ID, use
scripts/get_email_log.shwith multiple filters such as--to,--from,--start-time,--end-time,--subject, and--status; the script picks the first matching Email Logs message, so use narrow filters. - If
query_email_logs.shreturns no data or no fuzzysg_message_idmatch, direct the user to https://app.sendgrid.com/email_logs for manual review. - If
--api-key,SENDGRID_API_KEY, and the locally saved key are all missing, tell the user to read https://frevana.gitbook.io/frevana-docs/email-integrations/sendgrid-integration to get the required configuration. - If a user shares an API key in chat, advise them to rotate it.
Example Prompts
Chinese
- "Check whether this SendGrid email has been opened or clicked, the sg_message_id is ..."
- "Get the event timeline for this SendGrid message id"
- "Check whether this email was delivered / opened / clicked"
English
- "Check whether this SendGrid email was opened or clicked"
- "Retrieve SendGrid Email Logs activity for this sg_message_id"
- "Get the event timeline for this SendGrid message"