Skip to content

Webhooks

Webhooks notify your application when events occur in AgentMail.

Create a Webhook

suspend fun createWebhookExample() {
    val client = AgentMailClient()
    val webhook = client.createWebhook {
        url = "https://example.com/webhook"
        events(WebhookEvent.MESSAGE_RECEIVED, WebhookEvent.MESSAGE_SENT)
    }
    println("Webhook ID: ${webhook.webhookId}")
    client.close()
}

Available Events

Event Description
MESSAGE_RECEIVED A new message was received
MESSAGE_SENT A message was sent
MESSAGE_DELIVERED A message was delivered
MESSAGE_BOUNCED A message bounced
MESSAGE_COMPLAINED A spam complaint was received
MESSAGE_REJECTED A message was rejected
DOMAIN_VERIFIED A domain was verified

List Webhooks

suspend fun listWebhooksExample() {
    val client = AgentMailClient()
    val result = client.listWebhooks {
        limit = 10
    }
    for (webhook in result.webhooks) {
        println("${webhook.webhookId}: ${webhook.url}")
    }
    client.close()
}

Get a Webhook

suspend fun getWebhookExample() {
    val client = AgentMailClient()
    val webhook = client.getWebhook("webhook-id")
    println("URL: ${webhook.url}")
    println("Events: ${webhook.events}")
    client.close()
}

Update a Webhook

suspend fun updateWebhookExample() {
    val client = AgentMailClient()
    val updated = client.updateWebhook("webhook-id") {
        url = "https://example.com/new-webhook"
        events(WebhookEvent.MESSAGE_RECEIVED)
    }
    println("Updated URL: ${updated.url}")
    client.close()
}

Delete a Webhook

suspend fun deleteWebhookExample() {
    val client = AgentMailClient()
    client.deleteWebhook("webhook-id")
    println("Webhook deleted")
    client.close()
}

Webhook Handler

The SDK includes a webhook handler that verifies signatures and routes events to handlers.

Basic Handler

fun webhookHandlerExample() {
    val handler = webhookHandler {
        signingSecret = "whsec_your-signing-secret"

        onMessageReceived { payload ->
            println("Message received: $payload")
        }

        onMessageSent { payload ->
            println("Message sent: $payload")
        }

        onMessageBounced { payload ->
            println("Message bounced: $payload")
        }
    }

    // In your HTTP handler:
    // val headers = mapOf("svix-id" to ..., "svix-timestamp" to ..., "svix-signature" to ...)
    // val success = handler.handle(headers, requestBody)
}

Custom Event Handlers

Use the generic on() method for any event type:

fun webhookHandlerCustomExample() {
    val handler = webhookHandler {
        signingSecret = "whsec_your-signing-secret"

        // Use the generic on() for any event type
        on(WebhookEvent.DOMAIN_VERIFIED) { payload ->
            println("Domain verified: $payload")
        }

        on(WebhookEvent.MESSAGE_COMPLAINED) { payload ->
            println("Complaint received: $payload")
        }
    }

    // Use handler.handle(headers, body) to verify and dispatch
    // See the basic handler example above for the full pattern
}

Signature Verification

Webhooks are signed using HMAC-SHA256 (Svix format). The handler verifies signatures automatically when signingSecret is set.

You can also verify signatures without dispatching:

fun webhookVerifyExample() {
    val handler = webhookHandler {
        signingSecret = "whsec_your-signing-secret"
    }

    // Verify signature without dispatching to handlers
    val headers = mapOf(
        "svix-id" to "msg_abc123",
        "svix-timestamp" to "1234567890",
        "svix-signature" to "v1,signature-here"
    )
    val isValid = handler.verify(headers, """{"type":"message.received"}""")
    println("Valid: $isValid")
}

Next Steps

  • Pods — group inboxes into isolated pods
  • Domains — register and manage custom domains
  • Lists — manage mailing lists and subscribers