Skip to content
Pidgely Docs

API reference · Emails

List the events of an email

GEThttps://api.pidgely.com/emails/{id}/events
View as Markdown

The full timeline of an email, oldest first, with each recipient's delivery and its open and click counters (Pidgely extension). Bounces carry SES-style bounce.type and bounce.sub_type, complaints complaint.feedback_type, opens and clicks the machine / bot flags. See Open and click tracking.

Pidgely extension. The full timeline of an e-mail, oldest first: email.queued, email.delivered (with delivery.remote_mta, smtp_response, processing_time_ms), email.deferred (delay), email.bounced (bounce.type Permanent, Transient or Undetermined and bounce.sub_type, like Amazon SES), email.complained (complaint.feedback_type, provider), email.opened (open), email.clicked (click), email.suppressed, email.failed, email.unsubscribed and email.canceled, plus each recipient's delivery with its open and click counters. Opens and clicks carry machine / bot flags for privacy proxies and security scanners. Requires a full_access key.

Authorization: Bearer pdg_…. An API key with full_access. A sending_access key gets 401 restricted_api_key.

Path parameters

Name Type Required Description
id string Yes Email id UUID.

Request

This endpoint is not in the SDKs yet; call it over HTTP.

cURL
curl -X GET 'https://api.pidgely.com/emails/0199d8a2-6f3c-7c51-9e2a-3b1f0c6d4e21/events' \
  -H "Authorization: Bearer $PIDGELY_API_KEY"

Response

200 OK

JSON
{
  "object": "list",
  "has_more": false,
  "data": [
    {
      "id": "0199d8a2-6f40-7000-8000-000000000001",
      "type": "email.queued",
      "created_at": "2026-10-12 16:44:41.000000+00",
      "data": {
        "from": "Acme <news@acme.com>",
        "subject": "October update",
        "to": [
          "steve@example.com"
        ],
        "tags": {}
      }
    },
    {
      "id": "0199d8a2-7000-7000-8000-000000000002",
      "type": "email.delivered",
      "recipient": "steve@example.com",
      "created_at": "2026-10-12 16:44:41.000000+00",
      "data": {
        "recipient": "steve@example.com",
        "delivery": {
          "remote_mta": "gmail-smtp-in.l.google.com",
          "smtp_response": "250 2.0.0 OK 1760280251",
          "transport": "mta",
          "attempts": 1,
          "processing_time_ms": 812,
          "mailbox_provider": "gmail"
        }
      }
    },
    {
      "id": "0199d8b0-1000-7000-8000-000000000003",
      "type": "email.opened",
      "recipient": "steve@example.com",
      "created_at": "2026-10-12 16:44:41.000000+00",
      "data": {
        "recipient": "steve@example.com",
        "open": {
          "timestamp": "2026-10-12T17:02:10Z",
          "user_agent": "Mozilla/5.0 (via ggpht.com GoogleImageProxy)",
          "ip_address": "66.249.84.0",
          "ua_class": "gmail_image_proxy",
          "machine": false,
          "first": true,
          "count": 1
        }
      }
    },
    {
      "id": "0199d8b0-2000-7000-8000-000000000004",
      "type": "email.clicked",
      "recipient": "steve@example.com",
      "created_at": "2026-10-12 16:44:41.000000+00",
      "data": {
        "recipient": "steve@example.com",
        "click": {
          "link": "https://acme.com/changelog",
          "link_index": 0,
          "timestamp": "2026-10-12T17:02:31Z",
          "user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 18_0 like Mac OS X)",
          "ip_address": "203.0.113.0",
          "ua_class": "mobile",
          "bot": false,
          "first": true,
          "count": 1
        }
      }
    }
  ],
  "deliveries": [
    {
      "id": "0199d8a2-6f41-7000-8000-000000000010",
      "recipient": "steve@example.com",
      "kind": "to",
      "status": "delivered",
      "attempts": 1,
      "mailbox_provider": "gmail",
      "opens": 1,
      "human_opens": 1,
      "clicks": 1,
      "human_clicks": 1,
      "updated_at": "2026-10-12T17:02:31Z"
    }
  ]
}

Response fields

Name Type Required Description
object string Yes Object type.
has_more boolean No Whether another page exists.
data object[] Yes Items of this page.
data[].id string Yes Unique id (UUID). UUID.
data[].type string Yes email.queued, email.delivered, email.deferred, email.bounced, email.failed, email.complained, email.suppressed, email.unsubscribed, email.opened, email.clicked, email.canceled
data[].recipient string No —
data[].data object (map of any) Yes Event payload. delivered: delivery {remote_mta, smtp_response, transport, attempts, processing_time_ms, mailbox_provider} (plus the older remote_host, response). deferred: delay {attempt, next_attempt_at, smtp_response, enhanced_code, remote_mta}. bounced: bounce {type: Permanent | Transient | Undetermined, sub_type: General | NoEmail | Suppressed | OnAccountSuppressionList | MailboxFull | MessageTooLarge | ContentRejected | AttachmentRejected | Undetermined, message, diagnostic_code, enhanced_code, smtp_code, remote_mta, reporting_mta, source, suppressed}. complained: complaint {feedback_type: abuse | fraud | virus | not-spam | auth-failure | other | null, provider, user_agent, arrival_date, suppressed}. opened: open {timestamp, user_agent, ip_address (anonymised: /24 or /48), ua_class, machine, machine_reason, first, count}. clicked: click {link, link_index, timestamp, user_agent, ip_address, ua_class, bot, bot_reason, first, count}. suppressed / failed: reason (and bounce for suppression and exhausted retries). queued: from, subject, to, tags, scheduled_at.
data[].created_at string Yes Timestamp in UTC (2026-10-12 16:44:41.000000+00).
deliveries object[] Yes —
deliveries[].id string Yes Unique id (UUID). UUID.
deliveries[].recipient string Yes —
deliveries[].kind string Yes One of to, cc, bcc.
deliveries[].status string Yes Current status. One of queued, deferred, delivered, bounced, complained, suppressed, failed, canceled, discarded.
deliveries[].attempts integer Yes —
deliveries[].last_response string No —
deliveries[].transport string No —
deliveries[].first_attempt_at string No Format: date-time.
deliveries[].finished_at string No Format: date-time.
deliveries[].updated_at string Yes Format: date-time.
deliveries[].mailbox_provider string Yes Recipient's mailbox provider (from the address domain, or the MX host of a custom domain). One of gmail, outlook, yahoo, icloud, other.
deliveries[].opens integer Yes Recorded opens, machine opens included.
deliveries[].human_opens integer Yes Opens not flagged as machine opens.
deliveries[].first_opened_at string No Format: date-time.
deliveries[].last_opened_at string No Format: date-time.
deliveries[].first_human_opened_at string No Format: date-time.
deliveries[].clicks integer Yes Recorded clicks, bot clicks included.
deliveries[].human_clicks integer Yes Clicks not flagged as bot clicks.
deliveries[].first_clicked_at string No Format: date-time.
deliveries[].last_clicked_at string No Format: date-time.
deliveries[].first_human_clicked_at string No Format: date-time.

Errors

Errors have the shape {"statusCode", "name", "message"}. See Errors for the full list.

Status Name When
401 missing_api_key, restricted_api_key No Authorization: Bearer header, or a sending_access key called an endpoint that needs full_access.
403 invalid_api_key, validation_error The API key is invalid or revoked, or the request is not allowed for this account (unverified domain, plan limit, paused account).
404 not_found The resource does not exist in this account (or the id is not a valid UUID).
422 validation_error A field is missing or invalid; message names it.
429 rate_limit_exceeded Too many requests per second. Wait for Retry-After seconds.