Integrations
Integrations send your organization's customers to another tool, automatically. Every customer created, or whose email or name changes, is sent. Customers without an email are never sent.
Everything lives in Rules & settings in the sidebar, then the Integrations tab, visible to the owner and the admins of the organization. Integrations are included in the Pro plan: on another plan the screen shows Pro plan required and nothing is sent.
Consent belongs to the tool you send to. VillaSlot sends the contact; your email tool handles opt-in and unsubscribes.
AgentsMail
Adds each customer to an AgentsMail list.
- Connect → paste your AgentsMail API key → Check the key.
- Pick the target list.
- Save.
The key is verified with AgentsMail, then stored encrypted. It is never shown again; leave the field empty when editing to keep the saved key. A contact is created or updated with the email, the first name and the last name.
Deleting the integration stops the sending; contacts already in the list stay there.
Webhook
Sends each event as a JSON POST to a URL of yours.
- The URL must be
https://and publicly reachable — private networks andlocalhostare refused. Redirects are not followed. - Answer with any
2xxwithin 10 seconds. Anything else counts as a failure and the delivery is retried a few times. - The signing secret is shown once, when the webhook is created. Keep it.
Events
| Event | Sent when |
|---|---|
customer.created | a customer with an email is created |
customer.updated | a customer's email or name changes |
{
"event": "customer.created",
"id": "5d27589a-…",
"email": "elena@marchetti.studio",
"firstName": "Elena",
"lastName": "Marchetti",
"fullName": "Elena Marchetti",
"organizationId": "8b1f…",
"occurredAt": "2026-10-01T06:12:44.000Z"
}The first word of the name becomes firstName, the rest lastName. A bulk sync adds
"source": "bulk_sync".
Verify the signature
Two headers come with every call:
X-VillaSlot-Event— the event nameX-VillaSlot-Signature—t=<unix timestamp>,v1=<signature>
v1 is the hex HMAC-SHA256 of <t>.<raw body>, keyed with your signing secret. Compute it on the
raw body, before parsing the JSON, and reject old timestamps:
import {createHmac, timingSafeEqual} from 'node:crypto'
export const isValidVillaSlotSignature = (
rawBody: string,
header: string,
secret: string
) => {
const parts = Object.fromEntries(
header.split(',').map((part) => part.split('=') as [string, string])
)
const timestamp = Number(parts.t)
if (!timestamp || Math.abs(Date.now() / 1000 - timestamp) > 300) {
return false
}
const expected = createHmac('sha256', secret)
.update(`${parts.t}.${rawBody}`)
.digest('hex')
return (
expected.length === parts.v1?.length &&
timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1))
)
}Bulk sync
New and changed customers are sent continuously. To send the customers you already had, use Sync all customers on an integration. It runs in the background; the card shows how many were sent, skipped (no email) and failed.
Status
Each integration card shows whether it is active, disabled or failing, the last successful send and the last error. A disabled integration sends nothing until it is enabled again.