Messages (email log)

GET/api/v1/email-logs/messages
Requires anorganization API keywith the scopeevents:read

Request

GET/api/v1/email-logs/messages
curl -X GET 'https://app.mailyte.com/api/v1/email-logs/messages' \
  -H 'Authorization: Bearer mk_live_YOUR_API_KEY'
The key names its own organization, so no X-Organization-ID header is needed.

Response

Success.

  • dataobject
    • dataarray<object>
      • objectstringmessage
      • idstring

        The opaque handle, and the value `GET /email-logs/messages/{id}` takes. A bare local part or -- for a message that never carried a Message-ID -- a row id; either way it resolves. Not the Message-ID: see `message_id`.

      • message_idstring

        The RFC 5322 Message-ID, angle brackets included, for `GET /domains/{domain}/messages/{messageId}`. NULL MEANS THIS MESSAGE NEVER CARRIED THE HEADER -- it is not a missing lookup, and `id` above is deliberately not published here in its place.

      • subjectstring

        NULL MEANS NONE, and on this endpoint that is a strong statement rather than a list omission: the aggregate takes the subject from EVERY event in the group, not just one, so a null means no event we hold for this message carried a subject at all -- the message is known to us only from webhooks and we never saw its submission. Contrast `GET /email-logs`, where a null subject usually just means that ROW is not the submission; here there is no other row to go and look at.

      • fromobject
        • emailstring

          NULL MEANS NONE, on the same terms as `subject`: the aggregate reads `from` and then `sender` across every event in the group, so null means not one of them named a sender. It is not a relation we failed to join and not a value withheld from the list -- fetching the message will not fill it in.

        • namestring

          NULL MEANS NONE: the display name the message was sent with, read from the submission payload by the same aggregate that reads `subject` and `email`. Null means this sender has no name set, or the group holds no submission event to read one from -- not that the value was withheld. It used to be hardcoded null on every row, which claimed every message went out as a bare address.

      • recipientstring

        The one address this message was sent to -- a grouped row is one recipient's copy, so a batch appears as many rows. NULL MEANS UNKNOWN: the aggregate takes the recipient across every event in the group, so null means not one of them recorded an address. Every event we write fills it in, so this only happens on a message known to us purely from ingested webhooks whose payloads named the address under a key we do not read. Never read it as a message with no destination.

      • statusstringsubmitted | sent | delivered | deferred | bounced | rejected | dropped | opened | clicked | complained | unsubscribed | unknown

        The message's newest outcome, and a CLOSED set: a value this resource does not recognise is published as `unknown` rather than leaking a new one into the contract. Two of these cannot currently occur -- `sent` and `complained` are derived from `email.sent` and `email.complained`, which no producer emits (a complaint arrives as `delivery.complaint`). They stay in the set because the derivation still names them; treat them as reserved.

      • activityobject

        Counts over every event recorded for this message.

        • totalinteger

          All events, of any type.

        • opensinteger

          Every `tracking.open`, not unique openers -- one person reopening a message counts each time.

        • clicksinteger

          Every `tracking.click`, not unique links.

        • typesarray<string>

          The distinct `type` values seen for this message, from the same set as an event's `type`.

      • first_event_atstring

        ISO 8601 UTC. This came off a MySQL aggregate as `2026-09-17 20:10:54` -- no T, no offset -- which parses in most languages AS LOCAL TIME, silently. NULL WOULD MEAN UNKNOWN and is not a case to code for: it is `MIN(created_at)` over a group that exists only because events exist, and that column is NOT NULL. It can never mean "nothing has happened yet" -- such a message would not be a row.

      • last_event_atstring

        ISO 8601 UTC. The event `status` was derived from. NULL WOULD MEAN UNKNOWN, on the same terms as `first_event_at`, and is likewise unreachable: a group with no events is not published. A message with one event has this equal to `first_event_at`, which is not a bug.

    • pagination_metaany

Returned inside the standard envelope.

Errors

StatusWhen
401The API key is missing, unknown, revoked or expired. All four answer identically, on purpose: distinguishing them would confirm which keys exist.
403The key is valid but may not do this: it lacks the required scope, its IP allowlist does not include you, or this endpoint does not accept API keys.
404No such resource in this organization.
422The request was understood but the values were not acceptable.
429Too many requests, or the organization has spent its sending allowance. `Retry-After` says how long to wait.

Every status, with what causes it and what to do, is on the error reference.