# Best practices

> What a webhook endpoint needs to do: validate the signature, respond fast, be idempotent, use HTTPS and a public address.

Página: https://doc.rapidchargeback.com/en/canais/webhook/boas-praticas/

## Validate the signature first

Compute and check `X-Webhook-Signature` **before** parsing the JSON or touching the database. Any request with an invalid signature must be discarded. See [Authentication](https://doc.rapidchargeback.com/en/canais/webhook/autenticacao/).

## Respond fast

Return `200` or `204` as soon as possible, ideally in under 1 second. If you need to process the alert (e.g. update the database, call the gateway API), do it asynchronously after responding.

The timeout is 30 seconds per attempt. Any delay eats into that budget and can trigger an unnecessary retry.

## Idempotency

Rapid can send the same alert again:
- When the previous attempt failed (automatic retry)
- When someone on your team redelivers it from the dashboard
- In rare cases of network failure between your server's response and the confirmation on Rapid's side

Your processing must be **idempotent by `alert_id`**:

1. When you receive a webhook, check whether a record with that `alert_id` already exists in your system
2. If it does, return `200` immediately and do not process it again
3. If it does not, process and store it

## Ignore unknown fields

The payload can evolve with new fields. Your deserialization must **tolerate extra fields** instead of failing. Never remove or change fields while processing.

## Return 200 even on a validation error

If the payload arrives but you cannot process it (e.g. the merchant does not exist on your side), **still return 200**. Returning an error triggers a useless retry.

Record the failure on your side (log, internal alert, error queue) and handle it offline.

## Always use HTTPS

The webhook URL must be `https://`: the dashboard does not save an `http://` URL, and Rapid does not deliver over plain HTTP. The signature proves the request came from Rapid, but it does not encrypt the content, and the payload carries card data (BIN and last 4 digits) and purchase data.

## Use a public internet address

The URL must point to a server reachable from the internet. Rapid does not deliver to a local or private network address: `localhost`, `127.0.0.1`, `10.x`, `172.16.x` to `172.31.x`, `192.168.x` and their IPv6 equivalents. The dashboard already rejects these addresses at registration, and a domain name that resolves to one of them fails at delivery time.

To test the integration on your machine, expose the local server with an HTTPS tunnel (such as ngrok or Cloudflare Tunnel) and register the public address it generates.

## Protect the secret

The `secret` used to validate `X-Webhook-Signature` must be treated as a sensitive credential:
- Do not commit it to a repository
- Do not log it
- Store it in an environment variable or a secrets vault

## Monitoring

We recommend instrumenting:
- Rate of webhooks received (if it drops, something may be wrong at Rapid or on the network)
- Rate of invalid signatures (if it rises, it may mean a secret rotation that was not propagated or a forgery attempt)
- Processing latency (to make sure it stays below the 30s timeout)
- Rate of retries delivered (points to problems on your side)
