Loops · AsyncAPI Specification

Loops Webhooks

Version 1.21.6

Event catalog for the Loops webhook surface, derived operation-for-operation from the `webhooks` block of the Loops OpenAPI 3.1 document (info.version 1.21.6, published at https://app.loops.so/openapi.json). Loops does not publish an AsyncAPI document; it publishes these events inside its OpenAPI, and this file is a faithful projection of that block into AsyncAPI 3.0.0 so the event surface is readable by event tooling. Every channel, message name, summary and payload schema below comes verbatim from the provider. Delivery is a single HTTP POST to one subscriber-configured endpoint per Loops account, signed with HMAC-SHA256 over `{webhook-id}.{webhook-timestamp}.{raw-body}` and capped at 10 events per second.

View Spec View on GitHub EmailEmail APIMarketing AutomationTransactional EmailLifecycle EmailWebhookSoftware-as-a-ServiceCommunicationsDeveloper ToolsMCPAgentsCampaignsAsyncAPIWebhooksEvents

Channels

contactUnsubscribed
Delivered by HTTP POST to the account webhook endpoint.
contactCreated
Delivered by HTTP POST to the account webhook endpoint.
contactDeleted
Delivered by HTTP POST to the account webhook endpoint.
contactMailingListSubscribed
Delivered by HTTP POST to the account webhook endpoint.
contactMailingListUnsubscribed
Delivered by HTTP POST to the account webhook endpoint.
transactionalEmailSent
Delivered by HTTP POST to the account webhook endpoint.
campaignEmailSent
Delivered by HTTP POST to the account webhook endpoint.
loopEmailSent
Delivered by HTTP POST to the account webhook endpoint.
emailDelivered
Delivered by HTTP POST to the account webhook endpoint.
emailSoftBounced
Delivered by HTTP POST to the account webhook endpoint.
emailHardBounced
Delivered by HTTP POST to the account webhook endpoint.
emailClicked
Delivered by HTTP POST to the account webhook endpoint.
emailUnsubscribed
Delivered by HTTP POST to the account webhook endpoint.
emailResubscribed
Delivered by HTTP POST to the account webhook endpoint.
emailOpened
Delivered by HTTP POST to the account webhook endpoint.
emailSpamReported
Delivered by HTTP POST to the account webhook endpoint.
testingTestEvent
Delivered by HTTP POST to the account webhook endpoint.

Messages

contactUnsubscribed
Contact unsubscribed
Sent when a contact is unsubscribed from your audience, or when a contact is deleted from your audience (alongside `contact.deleted`). This is not the same as a contact unsubscribing from a mailing list (see `contact.mailingList.unsubscribed`). Contains a `contactIdentity` object.
contactCreated
Contact created
Sent when a new contact is created in your audience. Contains a `contactIdentity` object and a full `contact` object with all of the new contact's properties (including custom properties). When double opt-in is enabled, contact webhooks do not fire until the contact is confirmed; `contact.created` only fires for form-created contacts once they confirm their subscription. `optInStatus` will never be `"pending"` or `"rejected"` for this event.
contactDeleted
Contact deleted
Sent when a contact is deleted from your audience. Contains a `contactIdentity` object.
contactMailingListSubscribed
Contact subscribed to mailing list
Sent when a contact is subscribed to a mailing list. Contains `contactIdentity` and `mailingList` objects. When double opt-in is enabled, this event only fires after the contact confirms their subscription.
contactMailingListUnsubscribed
Contact unsubscribed from mailing list
Sent when a contact is unsubscribed from a mailing list. This is not the same as a contact unsubscribing from your audience (see `contact.unsubscribed`). Contains `contactIdentity` and `mailingList` objects.
transactionalEmailSent
Transactional email sent
Sent when a transactional email is sent to a contact. Contains a `transactionalId` value plus `contactIdentity` and `email` objects.
campaignEmailSent
Campaign email sent
Sent when a campaign email is sent to a contact. This event fires for every campaign send (for example, sending to 1,000 contacts produces 1,000 events). Contains `campaignId` and `campaignName` plus `contactIdentity` and `email` objects. If the campaign was sent to one or more mailing lists, a `mailingLists` array is also included.
loopEmailSent
Loop email sent
Sent when a workflow email is sent to a contact. This event keeps its `loop` naming for compatibility (Loops was renamed to Workflows on May 6, 2026). This event fires for every contact in a workflow (for example, 1,000 recipients produces 1,000 events). Contains `loopId` and `loopName` plus `contactIdentity` and `email` objects. If the workflow was sent to one or more mailing lists, a `mailingLists` array is also included.
emailDelivered
Email delivered
Sent when an email is delivered to its recipient. Contains `sourceType` (`campaign`, `loop`, or `transactional`) and the related `campaignId`, `loopId` (workflow ID), or `transactionalId`, plus `contactIdentity` and `email` objects.
emailSoftBounced
Email soft bounced
Sent when an email soft bounces. Soft bounces are temporary delivery failures (for example, a connection timing out). Soft bounces are retried multiple times and the email may still be delivered. Contains `sourceType` and the related `campaignId`, `loopId` (workflow ID), or `transactionalId`, plus `contactIdentity` and `email` objects.
emailHardBounced
Email hard bounced
Sent when an email hard bounces. Hard bounces are persistent delivery failures (for example, a mailbox that does not exist); the email will not be delivered. In Loops, a hard bounce also unsubscribes the contact from your audience, so a `contact.unsubscribed` event will also be sent. Contains `sourceType` and the related `campaignId`, `loopId` (workflow ID), or `transactionalId`, plus `contactIdentity` and `email` objects.
emailClicked
Email clicked
Sent when a link in a campaign or workflow email is clicked. Not available for transactional emails because link clicks are not tracked for transactional emails. Contains `sourceType` and the related `campaignId` or `loopId` (workflow ID), plus `contactIdentity` and `email` objects.
emailUnsubscribed
Email unsubscribed
Sent when a recipient unsubscribes from marketing email or a mailing list using an email's "Unsubscribe" link. A `contact.unsubscribed` or `contact.mailingList.unsubscribed` event will also be sent depending on whether the email was sent to a mailing list. Not available for transactional emails because unsubscribe links are not included for transactional emails. Contains `sourceType` and the related `campaignId` or `loopId` (workflow ID), plus `contactIdentity` and `email` objects.
emailResubscribed
Email resubscribed
Sent when a recipient resubscribes to marketing email from an email's preference center ("Unsubscribe" link). Not available for transactional emails because unsubscribe links are not included for transactional emails. Contains `sourceType` and the related `campaignId` or `loopId` (workflow ID), plus `contactIdentity` and `email` objects.
emailOpened
Email opened
Sent when a campaign or workflow email is opened. Not available for transactional emails because email opens are not tracked for transactional emails. Contains `sourceType` and the related `campaignId` or `loopId` (workflow ID), plus `contactIdentity` and `email` objects.
emailSpamReported
Email spam reported
Sent when a recipient reports your email as spam. Contains `sourceType` and the related `campaignId`, `loopId` (workflow ID), or `transactionalId`, plus `contactIdentity` and `email` objects.
testingTestEvent
Test event
Test event that can be triggered from the Webhooks settings page in Loops. Use this to verify that your endpoint is working and that your signature verification code is correct. The payload contains `eventName`, `eventTime`, `message` (always `"test"`), and `webhookSchemaVersion`.

Servers

https
subscriber
The single endpoint URL configured by the Loops account holder at https://app.loops.so/settings?page=webhooks. Loops permits one webhook endpoint per account.

AsyncAPI Specification

Raw ↑
# generated: '2026-08-13'
# method: derived
# source: openapi/_original/loops-openapi.yaml (webhooks block, info.version 1.21.6) + https://loops.so/docs/webhooks
asyncapi: 3.0.0
info:
  title: Loops Webhooks
  version: 1.21.6
  description: Event catalog for the Loops webhook surface, derived operation-for-operation from the `webhooks` block of the Loops OpenAPI 3.1 document (info.version 1.21.6, published at https://app.loops.so/openapi.json). Loops does not publish an AsyncAPI document; it publishes these events inside its OpenAPI, and this file is a faithful projection of that block into AsyncAPI 3.0.0 so the event surface is readable by event tooling. Every channel, message name, summary and payload schema below comes verbatim from the provider. Delivery is a single HTTP POST to one subscriber-configured endpoint per Loops account, signed with HMAC-SHA256 over `{webhook-id}.{webhook-timestamp}.{raw-body}` and capped at 10 events per second.
  externalDocs:
    description: Loops webhooks documentation
    url: https://loops.so/docs/webhooks
defaultContentType: application/json
servers:
  subscriber:
    host: '{subscriberEndpoint}'
    protocol: https
    description: The single endpoint URL configured by the Loops account holder at https://app.loops.so/settings?page=webhooks. Loops permits one webhook endpoint per account.
    variables:
      subscriberEndpoint:
        description: Your HTTPS endpoint that receives Loops events.
        default: example.com/webhooks/loops
channels:
  contactUnsubscribed:
    address: /
    title: Contact unsubscribed
    description: Delivered by HTTP POST to the account webhook endpoint.
    servers:
    - $ref: '#/servers/subscriber'
    messages:
      contactUnsubscribed:
        $ref: '#/components/messages/contactUnsubscribed'
  contactCreated:
    address: /
    title: Contact created
    description: Delivered by HTTP POST to the account webhook endpoint.
    servers:
    - $ref: '#/servers/subscriber'
    messages:
      contactCreated:
        $ref: '#/components/messages/contactCreated'
  contactDeleted:
    address: /
    title: Contact deleted
    description: Delivered by HTTP POST to the account webhook endpoint.
    servers:
    - $ref: '#/servers/subscriber'
    messages:
      contactDeleted:
        $ref: '#/components/messages/contactDeleted'
  contactMailingListSubscribed:
    address: /
    title: Contact subscribed to mailing list
    description: Delivered by HTTP POST to the account webhook endpoint.
    servers:
    - $ref: '#/servers/subscriber'
    messages:
      contactMailingListSubscribed:
        $ref: '#/components/messages/contactMailingListSubscribed'
  contactMailingListUnsubscribed:
    address: /
    title: Contact unsubscribed from mailing list
    description: Delivered by HTTP POST to the account webhook endpoint.
    servers:
    - $ref: '#/servers/subscriber'
    messages:
      contactMailingListUnsubscribed:
        $ref: '#/components/messages/contactMailingListUnsubscribed'
  transactionalEmailSent:
    address: /
    title: Transactional email sent
    description: Delivered by HTTP POST to the account webhook endpoint.
    servers:
    - $ref: '#/servers/subscriber'
    messages:
      transactionalEmailSent:
        $ref: '#/components/messages/transactionalEmailSent'
  campaignEmailSent:
    address: /
    title: Campaign email sent
    description: Delivered by HTTP POST to the account webhook endpoint.
    servers:
    - $ref: '#/servers/subscriber'
    messages:
      campaignEmailSent:
        $ref: '#/components/messages/campaignEmailSent'
  loopEmailSent:
    address: /
    title: Loop email sent
    description: Delivered by HTTP POST to the account webhook endpoint.
    servers:
    - $ref: '#/servers/subscriber'
    messages:
      loopEmailSent:
        $ref: '#/components/messages/loopEmailSent'
  emailDelivered:
    address: /
    title: Email delivered
    description: Delivered by HTTP POST to the account webhook endpoint.
    servers:
    - $ref: '#/servers/subscriber'
    messages:
      emailDelivered:
        $ref: '#/components/messages/emailDelivered'
  emailSoftBounced:
    address: /
    title: Email soft bounced
    description: Delivered by HTTP POST to the account webhook endpoint.
    servers:
    - $ref: '#/servers/subscriber'
    messages:
      emailSoftBounced:
        $ref: '#/components/messages/emailSoftBounced'
  emailHardBounced:
    address: /
    title: Email hard bounced
    description: Delivered by HTTP POST to the account webhook endpoint.
    servers:
    - $ref: '#/servers/subscriber'
    messages:
      emailHardBounced:
        $ref: '#/components/messages/emailHardBounced'
  emailClicked:
    address: /
    title: Email clicked
    description: Delivered by HTTP POST to the account webhook endpoint.
    servers:
    - $ref: '#/servers/subscriber'
    messages:
      emailClicked:
        $ref: '#/components/messages/emailClicked'
  emailUnsubscribed:
    address: /
    title: Email unsubscribed
    description: Delivered by HTTP POST to the account webhook endpoint.
    servers:
    - $ref: '#/servers/subscriber'
    messages:
      emailUnsubscribed:
        $ref: '#/components/messages/emailUnsubscribed'
  emailResubscribed:
    address: /
    title: Email resubscribed
    description: Delivered by HTTP POST to the account webhook endpoint.
    servers:
    - $ref: '#/servers/subscriber'
    messages:
      emailResubscribed:
        $ref: '#/components/messages/emailResubscribed'
  emailOpened:
    address: /
    title: Email opened
    description: Delivered by HTTP POST to the account webhook endpoint.
    servers:
    - $ref: '#/servers/subscriber'
    messages:
      emailOpened:
        $ref: '#/components/messages/emailOpened'
  emailSpamReported:
    address: /
    title: Email spam reported
    description: Delivered by HTTP POST to the account webhook endpoint.
    servers:
    - $ref: '#/servers/subscriber'
    messages:
      emailSpamReported:
        $ref: '#/components/messages/emailSpamReported'
  testingTestEvent:
    address: /
    title: Test event
    description: Delivered by HTTP POST to the account webhook endpoint.
    servers:
    - $ref: '#/servers/subscriber'
    messages:
      testingTestEvent:
        $ref: '#/components/messages/testingTestEvent'
operations:
  receive_contactUnsubscribed:
    action: receive
    channel:
      $ref: '#/channels/contactUnsubscribed'
    summary: Contact unsubscribed
    messages:
    - $ref: '#/channels/contactUnsubscribed/messages/contactUnsubscribed'
  receive_contactCreated:
    action: receive
    channel:
      $ref: '#/channels/contactCreated'
    summary: Contact created
    messages:
    - $ref: '#/channels/contactCreated/messages/contactCreated'
  receive_contactDeleted:
    action: receive
    channel:
      $ref: '#/channels/contactDeleted'
    summary: Contact deleted
    messages:
    - $ref: '#/channels/contactDeleted/messages/contactDeleted'
  receive_contactMailingListSubscribed:
    action: receive
    channel:
      $ref: '#/channels/contactMailingListSubscribed'
    summary: Contact subscribed to mailing list
    messages:
    - $ref: '#/channels/contactMailingListSubscribed/messages/contactMailingListSubscribed'
  receive_contactMailingListUnsubscribed:
    action: receive
    channel:
      $ref: '#/channels/contactMailingListUnsubscribed'
    summary: Contact unsubscribed from mailing list
    messages:
    - $ref: '#/channels/contactMailingListUnsubscribed/messages/contactMailingListUnsubscribed'
  receive_transactionalEmailSent:
    action: receive
    channel:
      $ref: '#/channels/transactionalEmailSent'
    summary: Transactional email sent
    messages:
    - $ref: '#/channels/transactionalEmailSent/messages/transactionalEmailSent'
  receive_campaignEmailSent:
    action: receive
    channel:
      $ref: '#/channels/campaignEmailSent'
    summary: Campaign email sent
    messages:
    - $ref: '#/channels/campaignEmailSent/messages/campaignEmailSent'
  receive_loopEmailSent:
    action: receive
    channel:
      $ref: '#/channels/loopEmailSent'
    summary: Loop email sent
    messages:
    - $ref: '#/channels/loopEmailSent/messages/loopEmailSent'
  receive_emailDelivered:
    action: receive
    channel:
      $ref: '#/channels/emailDelivered'
    summary: Email delivered
    messages:
    - $ref: '#/channels/emailDelivered/messages/emailDelivered'
  receive_emailSoftBounced:
    action: receive
    channel:
      $ref: '#/channels/emailSoftBounced'
    summary: Email soft bounced
    messages:
    - $ref: '#/channels/emailSoftBounced/messages/emailSoftBounced'
  receive_emailHardBounced:
    action: receive
    channel:
      $ref: '#/channels/emailHardBounced'
    summary: Email hard bounced
    messages:
    - $ref: '#/channels/emailHardBounced/messages/emailHardBounced'
  receive_emailClicked:
    action: receive
    channel:
      $ref: '#/channels/emailClicked'
    summary: Email clicked
    messages:
    - $ref: '#/channels/emailClicked/messages/emailClicked'
  receive_emailUnsubscribed:
    action: receive
    channel:
      $ref: '#/channels/emailUnsubscribed'
    summary: Email unsubscribed
    messages:
    - $ref: '#/channels/emailUnsubscribed/messages/emailUnsubscribed'
  receive_emailResubscribed:
    action: receive
    channel:
      $ref: '#/channels/emailResubscribed'
    summary: Email resubscribed
    messages:
    - $ref: '#/channels/emailResubscribed/messages/emailResubscribed'
  receive_emailOpened:
    action: receive
    channel:
      $ref: '#/channels/emailOpened'
    summary: Email opened
    messages:
    - $ref: '#/channels/emailOpened/messages/emailOpened'
  receive_emailSpamReported:
    action: receive
    channel:
      $ref: '#/channels/emailSpamReported'
    summary: Email spam reported
    messages:
    - $ref: '#/channels/emailSpamReported/messages/emailSpamReported'
  receive_testingTestEvent:
    action: receive
    channel:
      $ref: '#/channels/testingTestEvent'
    summary: Test event
    messages:
    - $ref: '#/channels/testingTestEvent/messages/testingTestEvent'
components:
  messages:
    contactUnsubscribed:
      name: contactUnsubscribed
      title: Contact unsubscribed
      summary: Sent when a contact is unsubscribed from your audience, or when a contact is deleted from your audience (alongside `contact.deleted`). This is not the same as a contact unsubscribing from a mailing list (see `contact.mailingList.unsubscribed`). Contains a `contactIdentity` object.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/WebhookContactUnsubscribedPayload'
      headers:
        $ref: '#/components/schemas/LoopsWebhookHeaders'
    contactCreated:
      name: contactCreated
      title: Contact created
      summary: Sent when a new contact is created in your audience. Contains a `contactIdentity` object and a full `contact` object with all of the new contact's properties (including custom properties). When double opt-in is enabled, contact webhooks do not fire until the contact is confirmed; `contact.created` only fires for form-created contacts once they confirm their subscription. `optInStatus` will never be `"pending"` or `"rejected"` for this event.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/WebhookContactCreatedPayload'
      headers:
        $ref: '#/components/schemas/LoopsWebhookHeaders'
    contactDeleted:
      name: contactDeleted
      title: Contact deleted
      summary: Sent when a contact is deleted from your audience. Contains a `contactIdentity` object.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/WebhookContactDeletedPayload'
      headers:
        $ref: '#/components/schemas/LoopsWebhookHeaders'
    contactMailingListSubscribed:
      name: contactMailingListSubscribed
      title: Contact subscribed to mailing list
      summary: Sent when a contact is subscribed to a mailing list. Contains `contactIdentity` and `mailingList` objects. When double opt-in is enabled, this event only fires after the contact confirms their subscription.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/WebhookContactMailingListSubscribedPayload'
      headers:
        $ref: '#/components/schemas/LoopsWebhookHeaders'
    contactMailingListUnsubscribed:
      name: contactMailingListUnsubscribed
      title: Contact unsubscribed from mailing list
      summary: Sent when a contact is unsubscribed from a mailing list. This is not the same as a contact unsubscribing from your audience (see `contact.unsubscribed`). Contains `contactIdentity` and `mailingList` objects.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/WebhookContactMailingListUnsubscribedPayload'
      headers:
        $ref: '#/components/schemas/LoopsWebhookHeaders'
    transactionalEmailSent:
      name: transactionalEmailSent
      title: Transactional email sent
      summary: Sent when a transactional email is sent to a contact. Contains a `transactionalId` value plus `contactIdentity` and `email` objects.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/WebhookTransactionalEmailSentPayload'
      headers:
        $ref: '#/components/schemas/LoopsWebhookHeaders'
    campaignEmailSent:
      name: campaignEmailSent
      title: Campaign email sent
      summary: Sent when a campaign email is sent to a contact. This event fires for every campaign send (for example, sending to 1,000 contacts produces 1,000 events). Contains `campaignId` and `campaignName` plus `contactIdentity` and `email` objects. If the campaign was sent to one or more mailing lists, a `mailingLists` array is also included.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/WebhookCampaignEmailSentPayload'
      headers:
        $ref: '#/components/schemas/LoopsWebhookHeaders'
    loopEmailSent:
      name: loopEmailSent
      title: Loop email sent
      summary: Sent when a workflow email is sent to a contact. This event keeps its `loop` naming for compatibility (Loops was renamed to Workflows on May 6, 2026). This event fires for every contact in a workflow (for example, 1,000 recipients produces 1,000 events). Contains `loopId` and `loopName` plus `contactIdentity` and `email` objects. If the workflow was sent to one or more mailing lists, a `mailingLists` array is also included.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/WebhookLoopEmailSentPayload'
      headers:
        $ref: '#/components/schemas/LoopsWebhookHeaders'
    emailDelivered:
      name: emailDelivered
      title: Email delivered
      summary: Sent when an email is delivered to its recipient. Contains `sourceType` (`campaign`, `loop`, or `transactional`) and the related `campaignId`, `loopId` (workflow ID), or `transactionalId`, plus `contactIdentity` and `email` objects.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/WebhookEmailDeliveredPayload'
      headers:
        $ref: '#/components/schemas/LoopsWebhookHeaders'
    emailSoftBounced:
      name: emailSoftBounced
      title: Email soft bounced
      summary: Sent when an email soft bounces. Soft bounces are temporary delivery failures (for example, a connection timing out). Soft bounces are retried multiple times and the email may still be delivered. Contains `sourceType` and the related `campaignId`, `loopId` (workflow ID), or `transactionalId`, plus `contactIdentity` and `email` objects.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/WebhookEmailSoftBouncedPayload'
      headers:
        $ref: '#/components/schemas/LoopsWebhookHeaders'
    emailHardBounced:
      name: emailHardBounced
      title: Email hard bounced
      summary: Sent when an email hard bounces. Hard bounces are persistent delivery failures (for example, a mailbox that does not exist); the email will not be delivered. In Loops, a hard bounce also unsubscribes the contact from your audience, so a `contact.unsubscribed` event will also be sent. Contains `sourceType` and the related `campaignId`, `loopId` (workflow ID), or `transactionalId`, plus `contactIdentity` and `email` objects.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/WebhookEmailHardBouncedPayload'
      headers:
        $ref: '#/components/schemas/LoopsWebhookHeaders'
    emailClicked:
      name: emailClicked
      title: Email clicked
      summary: Sent when a link in a campaign or workflow email is clicked. Not available for transactional emails because link clicks are not tracked for transactional emails. Contains `sourceType` and the related `campaignId` or `loopId` (workflow ID), plus `contactIdentity` and `email` objects.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/WebhookEmailClickedPayload'
      headers:
        $ref: '#/components/schemas/LoopsWebhookHeaders'
    emailUnsubscribed:
      name: emailUnsubscribed
      title: Email unsubscribed
      summary: Sent when a recipient unsubscribes from marketing email or a mailing list using an email's "Unsubscribe" link. A `contact.unsubscribed` or `contact.mailingList.unsubscribed` event will also be sent depending on whether the email was sent to a mailing list. Not available for transactional emails because unsubscribe links are not included for transactional emails. Contains `sourceType` and the related `campaignId` or `loopId` (workflow ID), plus `contactIdentity` and `email` objects.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/WebhookEmailUnsubscribedPayload'
      headers:
        $ref: '#/components/schemas/LoopsWebhookHeaders'
    emailResubscribed:
      name: emailResubscribed
      title: Email resubscribed
      summary: Sent when a recipient resubscribes to marketing email from an email's preference center ("Unsubscribe" link). Not available for transactional emails because unsubscribe links are not included for transactional emails. Contains `sourceType` and the related `campaignId` or `loopId` (workflow ID), plus `contactIdentity` and `email` objects.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/WebhookEmailResubscribedPayload'
      headers:
        $ref: '#/components/schemas/LoopsWebhookHeaders'
    emailOpened:
      name: emailOpened
      title: Email opened
      summary: Sent when a campaign or workflow email is opened. Not available for transactional emails because email opens are not tracked for transactional emails. Contains `sourceType` and the related `campaignId` or `loopId` (workflow ID), plus `contactIdentity` and `email` objects.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/WebhookEmailOpenedPayload'
      headers:
        $ref: '#/components/schemas/LoopsWebhookHeaders'
    emailSpamReported:
      name: emailSpamReported
      title: Email spam reported
      summary: Sent when a recipient reports your email as spam. Contains `sourceType` and the related `campaignId`, `loopId` (workflow ID), or `transactionalId`, plus `contactIdentity` and `email` objects.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/WebhookEmailSpamReportedPayload'
      headers:
        $ref: '#/components/schemas/LoopsWebhookHeaders'
    testingTestEvent:
      name: testingTestEvent
      title: Test event
      summary: Test event that can be triggered from the Webhooks settings page in Loops. Use this to verify that your endpoint is working and that your signature verification code is correct. The payload contains `eventName`, `eventTime`, `message` (always `"test"`), and `webhookSchemaVersion`.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/WebhookTestingTestEventPayload'
      headers:
        $ref: '#/components/schemas/LoopsWebhookHeaders'
  schemas:
    WebhookBasePayload:
      type: object
      required:
      - eventName
      - eventTime
      - webhookSchemaVersion
      - contactIdentity
      properties:
        eventName:
          type: string
        eventTime:
          type: integer
          description: Unix timestamp in seconds.
        webhookSchemaVersion:
          type: string
          const: 1.0.0
        contactIdentity:
          $ref: '#/components/schemas/WebhookContactIdentity'
    WebhookCampaignEmailSentPayload:
      allOf:
      - $ref: '#/components/schemas/WebhookBasePayload'
      - type: object
        required:
        - eventName
        - campaignId
        - email
        - mailingLists
        - campaignName
        properties:
          eventName:
            type: string
            const: campaign.email.sent
          campaignId:
            type: string
          campaignName:
            type: string
          email:
            $ref: '#/components/schemas/WebhookEmail'
          mailingLists:
            type: array
            description: The mailing list(s) the email was sent to, or an empty array.
            items:
              $ref: '#/components/schemas/WebhookMailingList'
    WebhookContact:
      type: object
      required:
      - id
      - email
      - firstName
      - lastName
      - source
      - subscribed
      - userGroup
      - userId
      - mailingLists
      - optInStatus
      properties:
        id:
          type: string
        email:
          type: string
        firstName:
          type:
          - string
          - 'null'
        lastName:
          type:
          - string
          - 'null'
        source:
          type: string
        subscribed:
          type: boolean
        userGroup:
          type: string
        userId:
          type:
          - string
          - 'null'
        notes:
          type:
          - string
          - 'null'
        mailingLists:
          type: object
          description: An object of mailing list IDs and boolean subscription statuses.
          additionalProperties:
            type: boolean
        optInStatus:
          type:
          - string
          - 'null'
          description: Double opt-in status.
          enum:
          - accepted
          - pending
          - rejected
          - null
      additionalProperties: true
      description: Full contact object, including custom properties.
    WebhookContactCreatedPayload:
      allOf:
      - $ref: '#/components/schemas/WebhookBasePayload'
      - type: object
        required:
        - eventName
        - contact
        properties:
          eventName:
            type: string
            const: contact.created
          contact:
            $ref: '#/components/schemas/WebhookContact'
    WebhookContactDeletedPayload:
      allOf:
      - $ref: '#/components/schemas/WebhookBasePayload'
      - type: object
        required:
        - eventName
        properties:
          eventName:
            type: string
            const: contact.deleted
    WebhookContactIdentity:
      type: object
      required:
      - id
      - email
      - userId
      properties:
        id:
          type: string
        email:
          type: string
        userId:
          type:
          - string
          - 'null'
    WebhookContactMailingListSubscribedPayload:
      allOf:
      - $ref: '#/components/schemas/WebhookBasePayload'
      - type: object
        required:
        - eventName
        - mailingList
        properties:
          eventName:
            type: string
            const: contact.mailingList.subscribed
          mailingList:
            $ref: '#/components/schemas/WebhookMailingList'
    WebhookContactMailingListUnsubscribedPayload:
      allOf:
      - $ref: '#/components/schemas/WebhookBasePayload'
      - type: object
        required:
        - eventName
        - mailingList
        properties:
          eventName:
            type: string
            const: contact.mailingList.unsubscribed
          mailingList:
            $ref: '#/components/schemas/WebhookMailingList'
    WebhookContactUnsubscribedPayload:
      allOf:
      - $ref: '#/components/schemas/WebhookBasePayload'
      - type: object
        required:
        - eventName
        properties:
          eventName:
            type: string
            const: contact.unsubscribed
    WebhookEmail:
      type: object
      required:
      - id
      - emailMessageId
      - subject
      properties:
        id:
          type: string
          description: The ID of the email.
        emailMessageId:
          type: string
          description: The ID of the sent version of the campaign, workflow or transactional email.
        subject:
          type: string
          description: The subject of the email.
    WebhookEmailClickedPayload:
      allOf:
      - $ref: '#/components/schemas/WebhookMarketingEmailMetricPayload'
      - type: object
        required:
        - eventName
        properties:
          eventName:
            type: string
            const: email.clicked
    WebhookEmailDeliveredPayload:
      allOf:
      - $ref: '#/components/schemas/WebhookEmailMetricPayload'
      - type: object
        required:
        - eventName
        properties:
          eventName:
            type: string
            const: email.delivered
    WebhookEmailHardBouncedPayload:
      allOf:
      - $ref: '#/components/schemas/WebhookEmailMetricPayload'
      - type: object
        required:
        - eventName
        properties:
          eventName:
            type: string
            const: email.hardBounced
    WebhookEmailMetricPayload:
      allOf:
      - $ref: '#/components/schemas/WebhookBasePayload'
      - type: object
        required:
        - email
        - sourceType
        properties:
          email:
            $ref: '#/components/schemas/WebhookEmail'
          sourceType:
            type: string
            enum:
            - loop
            - campaign
            - transactional
            description: The type of email this event relates to. Workflow emails use `loop`.
          campaignId:
            type: string
            description: The ID of the campaign if `sourceType` is `campaign`.
          loopId:
            type: string
            description: The ID of the workflow if `sourceType` is `loop`.
          transactionalId:
            type: string
            description: The ID of the transactional email if `sourceType` is `transactional`.
    WebhookEmailOpenedPayload:
      allOf:
      - $ref: '#/components/schemas/WebhookMarketingEmailMetricPayload'
      - type: object
        required:
        - eventName
        properties:
          eventName:
            type: string
            const: email.opened
    WebhookEmailResubscribedPayload:
      allOf:
      - $ref: '#/components/schemas/WebhookMarketingEmailMetricPayload'
      - type: object
        required:
        - eventName
        properties:
          eventName:
            type: string
            const: email.resubscribed
    WebhookEmailSoftBouncedPayload:
      allOf:
      - $ref: '#/components/schemas/WebhookEmailMetricPayload'
      - type: object
        required:
        - eventName
        properties:
          eventName:
            type: string
            const: email.softBounced
    WebhookEmailSpamReportedPayload:
      allOf:
      - $ref: '#/components/schemas/WebhookEmailMetricPayload'
      - type: object
        required:
        - eventName
        properties:
          eventName:
            type: string
            const: email.spamReported
    WebhookEmailUnsubscribedPayload:
      allOf:
      - $ref: '#/components/schemas/WebhookMarketingEmailMetricPayload'
      - type: object
        required:
        - eventName
        properties:
          eventName:
            type: string
            const: email.unsubscribed
    WebhookLoopEmailSentPayload:
      allOf:
      - $ref: '#/components/schemas/WebhookBasePayload'
      - type: object
        required:
        - eventName
        - loopId
        - email
        - mailingLists
        - loopName
        properties:
          eventName:
            type: string
            const: loop.email.sent
          loopId:
            type: string
            description: The ID of the workflow.
          loopName:
            type: string
            description: The name of the workflow.
          email:
            $ref: '#/components/schemas/WebhookEmail'
          mailingLists:
            type: array
            description: The mailing list(s) the email was sent to, or an empty array.
            items:
              $ref: '#/components/schemas/WebhookMailingList'
    WebhookMailingList:
      type: object
      description: Details of the mailing list.
      required:
      - id
      - name
      - description
      - isPublic
      properties:
        id:
          type: string
        name:
          type: string
        description:
          type:
          - string
          - 'null'
        isPublic:
          type: boolean
    WebhookMarketingEmailMetricPayload:
      allOf:
      - $ref: '#/components/schemas/WebhookBasePayload'
      - type: object
        required:
        - email
        - sourceType
        properties:
          email:
            $ref: '#/components/schemas/WebhookEmail'
          sourceType:
            type: string
            enum:
            - loop
            - campaign
            description: The type of email this event relates to. Workflow emails use `loop`. Not available for transactional emails.
          campaignId:
            type: string
            description: The ID of the campaign if `sourceType` is `campaign`.
          loopId:
            type: string
            description: The ID of the workflow if `sourceType` is `loop`.
    WebhookTestingTestEventPayload:
      type: object
      required:
      - eventName
      - eventTime
      - message
      - webhookSchemaVersion
      properties:
        eventName:
          type: string
          const: testing.testEvent
        eventTime:
          type: integer
          description: Unix timestamp in seconds.
        message:
          type: string
          const: test
        webhookSchemaVersion:
          type: string
          const: 1.0.0
    WebhookTransactionalEmailSentPayload:
      allOf:
      - $ref: '#/components/schemas/WebhookBasePayload'
      - type: object
        required:
        - eventName
        - transactionalId
        - email
        - transactionalName
        properties:
          eventName:
            type: string
            const: transactional.email.sent
          transactionalId:
            type: string
          transactionalName:
            type: string
          email:
            $ref: '#/components/schemas/WebhookEmail'
    LoopsWebhookHeaders:
      type: object
      description: Signature headers Loops sends with every webhook request. Verify by HMAC-SHA256 over `{webhook-id}.{webhook-timestamp}.{raw-body}` using the base64-decoded portion of the signing secret after the underscore.
      properties:
        webhook-id:
          type: string
          description: Unique event id.
        webhook-timestamp:
          type: string
          description: Unix timestamp of the send.
        webhook-signature:
          type: string
          description: Space-separated list of versioned base64 signatures.
      required:
      - webhook-id
      - webhook-timestamp
      - webhook-signature