# Events

When a conversion ends, every webhook endpoint of its mode that wants the event receives it, signed.

| Type | When |
| --- | --- |
| `conversion.completed` | The result is ready: its figures and its files. |
| `conversion.failed` | It ended without a result. Any credit came back. |
| `conversion.expired` | It did not finish in time. Any credit came back. |

## The envelope

| Field | Type | What |
| --- | --- | --- |
| `object` | `event` |  |
| `id` | id | The same as the `webhook-id` header: dedupe on it, events may come more than once. |
| `type` | one of `conversion.completed`, `conversion.failed`, `conversion.expired` | `conversion.completed` (its result is ready), `conversion.failed` or `conversion.expired` (it ended without one). |
| `timestamp` | timestamp | When the conversion ended. |
| `livemode` | boolean |  |
| `data` | Conversion | A conversion: one image redrawn as SVG, and where it stands. |

```json
{
  "object": "event",
  "id": "6b1e4c9a-2f7d-4e3b-8a5c-1d0e9f8a7b6c",
  "type": "conversion.completed",
  "timestamp": "2026-10-24T12:00:00.000Z",
  "livemode": false,
  "data": {
    "object": "conversion",
    "id": "00000000-0000-4000-8000-000000000000",
    "livemode": false,
    "status": "completed",
    "phase": null,
    "preset": "default",
    "options": {},
    "imageId": "00000000-0000-4000-8000-000000000001",
    "filename": "logo",
    "inputFormat": null,
    "unlocked": true,
    "allowance": "credit",
    "engineVersion": "sample-27a924dbb20e",
    "result": {
      "anchorPoints": 29,
      "fileSize": 550,
      "formats": [
        {
          "background": "dropped",
          "bytes": 550,
          "currentColor": false,
          "default": true,
          "editableText": false,
          "id": "web",
          "profile": "web"
        },
        {
          "background": "kept",
          "bytes": 600,
          "currentColor": false,
          "default": false,
          "editableText": false,
          "id": "web-background",
          "profile": "web"
        },
        {
          "background": "dropped",
          "bytes": 759,
          "currentColor": false,
          "default": true,
          "editableText": false,
          "id": "design",
          "profile": "design"
        },
        {
          "background": "kept",
          "bytes": 823,
          "currentColor": false,
          "default": false,
          "editableText": false,
          "id": "design-background",
          "profile": "design"
        }
      ]
    },
    "failure": null,
    "inputDeletedAt": null,
    "createdAt": "2026-10-24T12:00:00.000Z",
    "updatedAt": "2026-10-24T12:00:00.000Z"
  }
}
```

## The headers

Sent to every endpoint of the conversion's mode that wants it, signed by the Standard Webhooks scheme with the endpoint's secret: verify `webhook-signature` over `${webhook-id}.${webhook-timestamp}.${raw body}` before trusting it. At least once: dedupe on `webhook-id`. Answer 2xx within 15 seconds; anything else is retried for about 24 hours.

| Header | What |
| --- | --- |
| `webhook-id` | The event's id, the same on every attempt: dedupe on it. |
| `webhook-timestamp` | When this attempt was signed, in Unix seconds: refuse one more than 5 minutes off. |
| `webhook-signature` | `v1,<base64 HMAC-SHA256>` of `id.timestamp.body` with the endpoint's secret; two, space-separated, while a rolled secret overlaps. |

Check them with our SDKs' `verifyWebhook`, or any Standard Webhooks library. [How webhooks work](https://vecsnap.com/docs/webhooks).

---
This page: https://vecsnap.com/docs/api/events
