> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sendr.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Get Email Logs

> Retrieve email event logs for a domain associated with your tenant: receptions, deliveries, opens, clicks, temporary failures, bounces, and complaints. Results are returned newest-first and paginated via next_token.

<Note>
  Logs are served from a dedicated hostname: **`logs.sendrapp.org`**. Authenticate with your API key in the `Authorization` header.
</Note>

Retrieve per-message email event logs for one of your tenant's sender domains — receptions, deliveries, opens, clicks, temporary failures, bounces, and complaints. Results are returned **newest-first** and paginated with `next_token`.

### Query parameters

All parameters are optional. Filters are combined with AND.

| Parameter         | Type    | Description                                                                                           |
| ----------------- | ------- | ----------------------------------------------------------------------------------------------------- |
| `type`            | string  | Single event type, exact match (see table below). Cannot combine multiple types in one request.       |
| `message_id`      | string  | Return **all** events for one message (its `id`). When set, other filters and pagination are ignored. |
| `recipient`       | string  | Recipient address (substring match)                                                                   |
| `sender`          | string  | Envelope sender (substring match)                                                                     |
| `from`            | string  | Full `From` header (substring match)                                                                  |
| `subject`         | string  | Subject (substring match)                                                                             |
| `response_code`   | integer | Exact response code, e.g. `421`, `550`                                                                |
| `start_timestamp` | integer | Window start, **Unix seconds**. Defaults to 15 days ago.                                              |
| `end_timestamp`   | integer | Window end, **Unix seconds**. Defaults to now.                                                        |
| `limit`           | integer | Page size. Defaults to `50`.                                                                          |
| `next_token`      | string  | Cursor from a previous response, to fetch the next page.                                              |

<Note>
  Filtering by a sparse `type` (e.g. `Bounce`) over a wide window scans a lot of history and can be slow. Narrow the search with `start_timestamp` / `end_timestamp` whenever possible.
</Note>

### Event types

Filter with `?type=<value>`. One type per request.

| `type`             | Meaning                                           | Error?  |
| ------------------ | ------------------------------------------------- | ------- |
| `Reception`        | Message accepted by Sendr for sending             | no      |
| `Delivery`         | Accepted by the recipient's mail server           | no      |
| `Opened`           | Recipient opened the email                        | no      |
| `Click`            | Recipient clicked a link                          | no      |
| `TransientFailure` | Temporary failure — will be retried               | **yes** |
| `Delayed`          | Deferred and queued for a later retry             | **yes** |
| `Bounce`           | Permanent failure — not retried                   | **yes** |
| `OOBBounce`        | Out-of-band bounce reported later by the receiver | **yes** |
| `Feedback`         | Spam complaint (feedback loop)                    | **yes** |

### Response codes

`response_code` accompanies most events. **4xx are temporary (auto-retried), 5xx are permanent.**

| Code  | Class                | Meaning                                                                               |
| ----- | -------------------- | ------------------------------------------------------------------------------------- |
| `250` | success              | Accepted / delivered                                                                  |
| `400` | temporary (internal) | Sendr-internal send error (e.g. connection dropped); also carried by `Delayed` events |
| `421` | temporary            | Receiver is throttling / not accepting right now                                      |
| `450` | temporary            | Mailbox busy or "receiving mail too quickly"                                          |
| `451` | temporary            | Receiver processing error / greylisting                                               |
| `452` | temporary            | Receiver out of resources                                                             |
| `550` | permanent            | Mailbox doesn't exist **or** blocked as spam                                          |
| `551` | permanent            | User not local / relay denied                                                         |
| `552` | permanent            | Mailbox full or message too large                                                     |
| `553` | permanent            | Invalid recipient address                                                             |
| `554` | permanent            | Transaction failed / blocked                                                          |

### Pagination

When more results exist, the response includes a `next_token`. Pass it back as `?next_token=<token>` (keeping the same filters) to fetch the next page. When `next_token` is absent, you've reached the end.

### Example response

```json theme={null}
{
  "events": [
    {
      "id": "1NyCaoz9siVg2-A-1782502911",
      "timestamp": 1782502917,
      "type": "TransientFailure",
      "domain_name": "example.com",
      "recipient": "user@yahoo.com",
      "sender": "news@example.com",
      "from": "Example <news@example.com>",
      "subject": "Your weekly digest",
      "response_code": 450,
      "response_content": "User is receiving mail too quickly",
      "response_enhanced_code": "",
      "provider_name": "yahoo",
      "peer_name": "mta6.am0.yahoodns.net",
      "bounce_classification": "Uncategorized",
      "num_attempts": 0,
      "size": 165284,
      "sendr_message_id": "1NyCaoz9siVg2-A-1782502911",
      "direction": "outbound",
      "delivery_protocol": "ESMTP",
      "tls_protocol_version": "TLSv1_3"
    }
  ],
  "count": 1,
  "filters_applied": { "type": "TransientFailure" },
  "next_token": "eyJkb21haW5fbmFtZSI6..."
}
```

<Note>
  Field availability per event depends on the event type and how far the message progressed (e.g. `peer_name` and TLS fields only appear once a connection to the recipient server was made).
</Note>

### Errors

* `400 Bad Request`: Missing domain in the path
* `401 Unauthorized`: Missing `Authorization` header or invalid API key
* `500 Internal Server Error`: Unexpected server error


## OpenAPI

````yaml GET /webhooks/{domain}
openapi: 3.1.0
info:
  title: Email Service API
  description: API for sending and managing email communications
  license:
    name: MIT
  version: 1.0.0
servers:
  - url: https://sending.sendrapp.org
    description: Email Sending API
  - url: https://stats.sendrapp.org
    description: Statistics API
  - url: https://logs.sendrapp.org
    description: Logs API
  - url: http://localhost:3001
    description: Local Development
security:
  - apiKeyAuth: []
paths:
  /webhooks/{domain}:
    get:
      summary: Get Email Logs
      description: >-
        Retrieve email event logs for a domain associated with your tenant:
        receptions, deliveries, opens, clicks, temporary failures, bounces, and
        complaints. Results are returned newest-first and paginated via
        next_token.
      parameters:
        - name: domain
          in: path
          required: true
          schema:
            type: string
          description: Sender domain to retrieve logs for (must belong to your tenant)
        - name: type
          in: query
          required: false
          schema:
            type: string
            enum:
              - Reception
              - Delivery
              - TransientFailure
              - Delayed
              - Bounce
              - OOBBounce
              - Opened
              - Click
              - Feedback
          description: >-
            Filter by a single event type (exact match). Cannot combine multiple
            types in one request.
        - name: message_id
          in: query
          required: false
          schema:
            type: string
          description: >-
            Return all events for a single message (its uuid / the id field).
            When set, other filters and pagination are ignored.
        - name: recipient
          in: query
          required: false
          schema:
            type: string
          description: Filter by recipient address (substring match)
        - name: sender
          in: query
          required: false
          schema:
            type: string
          description: Filter by sender address (substring match)
        - name: from
          in: query
          required: false
          schema:
            type: string
          description: Filter by the full From header (substring match)
        - name: subject
          in: query
          required: false
          schema:
            type: string
          description: Filter by subject (substring match)
        - name: response_code
          in: query
          required: false
          schema:
            type: integer
          description: >-
            Filter by exact SMTP/internal response code (e.g. 421, 550). Note:
            code 400 is an internal Sendr code, not a real SMTP reply.
        - name: start_timestamp
          in: query
          required: false
          schema:
            type: integer
          description: >-
            Start of the time window, Unix seconds. Defaults to 15 days ago when
            omitted.
        - name: end_timestamp
          in: query
          required: false
          schema:
            type: integer
          description: End of the time window, Unix seconds. Defaults to now when omitted.
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            default: 50
          description: Page size. Defaults to 50.
        - name: next_token
          in: query
          required: false
          schema:
            type: string
          description: >-
            Opaque cursor from a previous response's next_token, used to fetch
            the next page.
      responses:
        '200':
          description: Logs retrieved successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  events:
                    type: array
                    items:
                      $ref: '#/components/schemas/EmailLogEvent'
                  count:
                    type: integer
                    description: Number of events in this page
                  filters_applied:
                    type: object
                    description: The non-null filters that were applied to this query
                    additionalProperties:
                      type: string
                  next_token:
                    type: string
                    description: >-
                      Cursor for the next page. Absent when there are no more
                      results.
                required:
                  - events
                  - count
        '400':
          description: Missing domain in path
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Missing Authorization header or invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      servers:
        - url: https://logs.sendrapp.org
          description: Logs API
components:
  schemas:
    EmailLogEvent:
      type: object
      description: >-
        A single email event. Field availability depends on the event type and
        how far the message progressed.
      properties:
        id:
          type: string
          description: >-
            Message id (uuid). All events for one message share this id; pass it
            as message_id to fetch the full timeline.
        timestamp:
          type: integer
          description: Unix timestamp (seconds) of the event
        type:
          type: string
          enum:
            - Reception
            - Delivery
            - TransientFailure
            - Delayed
            - Bounce
            - OOBBounce
            - Opened
            - Click
            - Feedback
          description: Event type
        domain_name:
          type: string
          description: Sender domain
        recipient:
          type: string
          format: email
          description: Recipient address
        sender:
          type: string
          format: email
          description: Envelope sender address
        from:
          type: string
          description: Full From header including display name
        subject:
          type: string
          description: Email subject
        response_code:
          type: integer
          description: >-
            SMTP/internal response code. 250 = success; 4xx = temporary; 5xx =
            permanent; 400 = internal Sendr code (e.g. connection dropped, or a
            Delayed retry).
        response_content:
          type: string
          description: >-
            Human-readable response text from the receiving server (or internal
            error)
        response_enhanced_code:
          type: string
          description: Enhanced status code in dotted form, e.g. "5.5.4". May be empty.
        provider_name:
          type: string
          description: Normalized receiving provider, e.g. "yahoo"
        peer_name:
          type: string
          description: Hostname of the receiving mail server, e.g. "mta6.am0.yahoodns.net"
        bounce_classification:
          type: string
          description: Failure category assigned by the MTA
        num_attempts:
          type: integer
          description: Delivery attempts made at the time of this event
        size:
          type: integer
          description: Message size in bytes
        sendr_message_id:
          type: string
          description: Your X-Sendr-Message-Id for this message (support correlation)
        direction:
          type: string
          description: Message direction, e.g. "outbound"
        campaign:
          type:
            - string
            - 'null'
          description: Campaign identifier, when applicable
        reception_protocol:
          type: string
          description: Protocol the message was received over (e.g. HTTP)
        delivery_protocol:
          type: string
          description: Protocol used to deliver to the recipient server (e.g. ESMTP)
        tls_protocol_version:
          type: string
          description: TLS version used for delivery, e.g. "TLSv1_3"
        tls_cipher:
          type: string
          description: TLS cipher used for delivery
      required:
        - id
        - timestamp
        - type
        - domain_name
        - recipient
    Error:
      type: object
      required:
        - error
        - message
      properties:
        error:
          type: integer
          format: int32
          description: Error code
        message:
          type: string
          description: Error message
  securitySchemes:
    apiKeyAuth:
      type: apiKey
      in: header
      name: Authorization

````