Configure Webhooks
Get real-time HTTP callbacks when messages are sent, received, or fail.
Webhooks let your server know when something happens in Coop — a message is delivered, a new message comes in, or a Mac goes offline.
Register a webhook
- Go to Settings > Webhooks
- Click Add Webhook
- Enter your HTTPS endpoint URL
- Select the events you want to subscribe to
- Optionally set a signing secret for payload validation
- Click Save
Choose events
| Event | When it fires |
|---|---|
message.queued | A message is added to the send queue |
message.sent | A message is sent via iMessage |
message.failed | A message fails after all retries |
message.received | An incoming iMessage arrives |
relay.online | Coop Desktop connects |
relay.offline | Coop Desktop disconnects |
Subscribe only to the events you need. You can update the subscription later.
Handle the payload
Every webhook delivers a JSON POST with this structure:
{
"event": "message.received",
"timestamp": "2025-01-15T10:30:00Z",
"data": {
"id": "rmsg_xyz789",
"from": "+15551234567",
"body": "Hey, are we still on for tomorrow?",
"receivedAt": "2025-01-15T10:30:00Z",
"conversationId": "conv_123"
}
}Your endpoint should return a 2xx status. Non-2xx responses trigger retries with exponential backoff.
Validate signatures
If you set a signing secret, every delivery includes an X-Webhook-Signature header — an HMAC-SHA256 hash of the raw request body.
Validate it server-side to confirm the request came from Coop:
const crypto = require('crypto');
function verifyWebhook(rawBody, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}Always validate in production. Without it, anyone who knows your endpoint URL could send fake events.
Disable or delete
Toggle a webhook off from Settings > Webhooks to pause deliveries. Delete it to remove it entirely.