# Webhooks

How webhook delivery works: event types, payload format, signature verification, and retries. Movemint sends HTTP POST requests to your registered URL when events occur.

#### Supported Events

| Event Type                  | Trigger                                                 |
| --------------------------- | ------------------------------------------------------- |
| `event.participant.created` | A new participant registers for an event you administer |

#### Webhook Delivery

When a webhook event fires, Movemint sends an HTTP `POST` request to your registered URL with a JSON payload:

```json
{
  "type": "event.participant.created",
  "data": {
    "object": { ... }
  }
}
```

The `data.object` field contains the full participant object (see the EventParticipant schema).

#### Signature Verification

Every webhook request includes an `X-Signature` header containing an HMAC-SHA256 hex digest of the request body, signed with your webhook subscription's `secret`. **Always verify the signature** before processing the payload.

```python
import hmac
import hashlib

def verify_signature(payload_body, secret, signature_header):
    expected = hmac.new(
        secret.encode('utf-8'),
        payload_body.encode('utf-8'),
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature_header)
```

```ruby
def verify_signature(payload_body, secret, signature_header)
  expected = OpenSSL::HMAC.hexdigest(
    OpenSSL::Digest.new('sha256'),
    secret,
    payload_body
  )
  ActiveSupport::SecurityUtils.secure_compare(expected, signature_header)
end
```

#### Webhook Retries

If your endpoint does not return a 2xx status code, the delivery is considered failed. Failed deliveries are retried automatically by the background job system.

{% openapi-webhook spec="movemint-api" name="newParticipant" method="post" %}
[Broken link](https://movemint.gitbook.io/movemint-developer-docs/open-api-specification/webhooks-and-notifications/broken-reference)
{% endopenapi-webhook %}
