Webhook events
Each delivery is a POST with a JSON body, the envelope:
| Field | Type | Description |
|---|---|---|
id | string | The delivery's id. A retry has the same id: skip ones you have handled. |
type | string | The event, below. |
createdAt | string (date-time) | When it happened. |
projectId | string | Your project. |
data | object | The event's fields, below. |
Headers: Content-Type: application/json, User-Agent: Lettrove-Webhooks/1, and Lettrove-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of "t.body" with the webhook's secret>. Check it before trusting the body.
Verify it with verifyWebhook.
Answer with any 2xx status to say it arrived. Anything else, or no answer within 10 seconds, is retried with backoff, up to 8 attempts. Setting up an endpoint, retries and the delivery log: Webhooks.
The events are in the OpenAPI document too, under webhooks.
design.saved
A design was created or saved.
data | Type | Description |
|---|---|---|
designId | string | The id Lettrove gave the design: 26 letters and digits. |
userId | string | Your own id for the person: whatever you chose, up to 256 characters. Never a name or an email. |
revision | integer | Its saved revision; only ever goes up. Saves of one design still waiting to be delivered are merged: you get the newest. |
{
"id": "01J9ZV8R1K3M5P7T9W2Y4A6C8E",
"type": "design.saved",
"createdAt": "2026-10-07T16:03:10.000Z",
"projectId": "01J9X2B4D6F8H0K2M4P6R8T0V2",
"data": {
"designId": "01J9ZQ3W8D2K7M5T1V4XG6HB0R",
"userId": "u_123",
"revision": 12
}
}
design.deleted
A design was deleted.
data | Type | Description |
|---|---|---|
designId | string | The id Lettrove gave the design: 26 letters and digits. |
userId | string | Your own id for the person: whatever you chose, up to 256 characters. Never a name or an email. |
{
"id": "01J9ZV8R1K3M5P7T9W2Y4A6C8E",
"type": "design.deleted",
"createdAt": "2026-10-07T16:03:10.000Z",
"projectId": "01J9X2B4D6F8H0K2M4P6R8T0V2",
"data": {
"designId": "01J9ZQ3W8D2K7M5T1V4XG6HB0R",
"userId": "u_123"
}
}
export.created
A design was exported, from the page or your server.
data | Type | Description |
|---|---|---|
exportId | string | The export's record. |
designId | string | The id Lettrove gave the design: 26 letters and digits. |
userId | string | Your own id for the person: whatever you chose, up to 256 characters. Never a name or an email. |
revision | integer | The saved revision; only ever goes up. |
source | editor | server | editor (the page) or server (your secret key). |
format | html | text | zip | pdf | png | html, text (a plain-text export), pdf, png or zip. |
{
"id": "01J9ZV8R1K3M5P7T9W2Y4A6C8E",
"type": "export.created",
"createdAt": "2026-10-07T16:03:10.000Z",
"projectId": "01J9X2B4D6F8H0K2M4P6R8T0V2",
"data": {
"exportId": "01J9ZR4C2N8B6V0X3M7K5T9QWE",
"designId": "01J9ZQ3W8D2K7M5T1V4XG6HB0R",
"userId": "u_123",
"revision": 12,
"source": "editor",
"format": "html"
}
}
user.erased
A person's data has been erased, after your erase request.
data | Type | Description |
|---|---|---|
userId | string | Your own id for the person: whatever you chose, up to 256 characters. Never a name or an email. |
{
"id": "01J9ZV8R1K3M5P7T9W2Y4A6C8E",
"type": "user.erased",
"createdAt": "2026-10-07T16:03:10.000Z",
"projectId": "01J9X2B4D6F8H0K2M4P6R8T0V2",
"data": {
"userId": "u_123"
}
}
ping
Sent by Send a test in the dashboard, whatever events the webhook subscribes to.
data | Type | Description |
|---|---|---|
message | string | Always this text. |
{
"id": "01J9ZV8R1K3M5P7T9W2Y4A6C8E",
"type": "ping",
"createdAt": "2026-10-07T16:03:10.000Z",
"projectId": "01J9X2B4D6F8H0K2M4P6R8T0V2",
"data": {
"message": "A test event from Lettrove."
}
}