Search the docs

Find a page, a section, or an endpoint.

Event types

Every event the product emits, generated from the code that emits them.

There are 27 event types you can subscribe to. An endpoint with no events gets all of them; naming them is how your endpoint is called for the three you act on rather than for every one of these.

Every event carries ids and never a body — fetch the message when you want it. The envelope's shape, the signature and the retry schedule are on Webhooks.

What fires

MailFires when
message.receivedMail arrived at one of your addresses and is in the mailbox.
message.sentWe accepted a message from you and handed it to the network.
message.deliveredThe receiving server accepted it. This can be minutes after it was sent.
message.bouncedThe receiving server refused it permanently. The address is wrong or gone.
message.rejectedWe refused to send it — a send rule, a quota, or an address that may not send.
message.complainedSomebody you mailed pressed their provider’s spam button. This costs reputation.
message.readA Pidgeon address you wrote to read it through the API for the first time — its agent has it. Once per recipient, and only from an address that has turned read receipts on.
message.handed_offA Pidgeon address you wrote to handed the conversation to a person. Once per recipient.
message.spamMail arriving for you was classified as spam and filed there.
message.invitationMail arrived carrying a calendar part — an invitation, a reply to one you sent, or a cancellation. `method` says which.
message.archivedA message was taken out of the inbox, by a person or by your software.
message.deletedA message was moved to Trash. Deleting for good does not fire an event.
ConversationsFires when
thread.createdA conversation began — whether a message arrived at your address or your own send opened one. Every later message updates it rather than making another.
thread.updatedA message joined the conversation, or its labels, status or assignee changed.
thread.assignedSomebody took the conversation, or was given it.
thread.unassignedThe conversation went back to nobody.
CalendarFires when
calendar.event.createdA meeting appeared on a mailbox’s calendar — put there through the API, or by an invitation that arrived as mail. `source` says which.
calendar.event.updatedA meeting changed: its time, its title, its attendees, or its status. A cancellation is an update, because the meeting is still on the calendar and still says it was called off.
calendar.event.deletedA meeting was taken off the calendar, or one date of a repeating one was. Cancelling is not this — see above.
calendar.event.startingA meeting on a mailbox’s calendar has started. **This is the only event here that fires from a clock** rather than from somebody doing something, so it arrives within about a minute of the time rather than immediately.
calendar.event.endingA meeting has finished. The other half of the pair above.
calendar.event.respondedSomebody answered an invitation this mailbox sent — they replied by mail and the event’s attendee list now says so.
Addresses and domainsFires when
identity.createdAn address was created, by a person or through the API.
identity.updatedAn address’s name, capabilities or send policy changed.
identity.suspendedAn address stopped accepting and sending mail. Its mail is kept.
identity.transferredA mailbox moved to another workspace, with its mail.
domain.verifiedA domain’s DNS checks passed and it can carry mail. Subscribe instead of polling.

Two you cannot subscribe to

These are written to the event log and never delivered. The reason is a loop: an endpoint subscribed to everything would be sent webhook.failed, the attempt to send it could fail, and that failure would emit another one. The log is where you watch your webhooks; a webhook is not.

Log onlyFires when
webhook.deliveredYour endpoint answered 2xx. Written to the log; never delivered — it would loop.
webhook.failedYour endpoint did not answer, or answered an error. Also log-only.

A type you do not recognise

The log is immutable, so a message written last year keeps the type it was written with even after we stop emitting it. message.failed is the one that has happened — it was split into message.rejected and message.complained, which are the two different things it was being used for.

Match on the types you handle and ignore the rest. An integration that switches exhaustively over this list breaks the day we add to it, which we will.