Weelay

Webhooks

Public description of Weelay webhooks: invoice.paid event, headers, signature, verification, idempotent handling and endpoint security.

Documentation Published: 2026-06-21 ~5 min read

General provisions

Webhook allows Weelay to send a notification to the merchant backend after an important event.

The main scenario is notifying the merchant that an invoice received the paid status.

Webhook is needed so the merchant does not have to manually check invoice status through API all the time.

Webhook endpoint must be a merchant backend endpoint. Do not use a frontend URL or a page that cannot receive POST requests.

When webhook is sent

Weelay sends a webhook after an invoice payment event.

The current main event:

invoice.paid

This event means the invoice was marked as paid.

After receiving and verifying this webhook, the merchant may update the order as paid.

Webhook URL

Webhook URL is configured in project settings.

Webhook URL must use HTTPS.

Example:

https://example.com/weelay/webhook

The endpoint must accept POST requests with JSON body.

Headers

Webhook request from Weelay contains service headers.

Main headers:

  • User-Agent;
  • Content-Type;
  • X-Weelay-Event;
  • X-Weelay-Delivery;
  • X-Weelay-Timestamp;
  • X-Weelay-Signature.

Content-Type is application/json.

X-Weelay-Event contains event name, for example invoice.paid.

X-Weelay-Delivery contains webhook delivery identifier.

X-Weelay-Timestamp contains Unix timestamp.

X-Weelay-Signature contains webhook signature.

Webhook signature

Each webhook is signed.

Signature header has the format:

X-Weelay-Signature: t={timestamp},v1={signature}

timestamp is Unix timestamp.

signature is HMAC-SHA256 signature.

The signature is calculated from the string:

{timestamp}.{raw_body}

Where raw_body is the original request body without formatting changes.

How to verify signature

The merchant backend should:

  1. Get raw request body.
  2. Get X-Weelay-Timestamp.
  3. Get X-Weelay-Signature.
  4. Build the string {timestamp}.{raw_body}.
  5. Calculate HMAC-SHA256 with the project webhook secret.
  6. Compare the calculated signature with v1 from X-Weelay-Signature.
  7. Reject the webhook if signatures do not match.

Signature comparison should be safe, without ordinary string comparison, to avoid timing attack.

Timestamp check

It is recommended to check that X-Weelay-Timestamp is not too old.

For example, reject the webhook if timestamp is older than 5 minutes.

This reduces the risk of replaying an old webhook request.

Payload

Webhook body is sent as JSON.

Main payload fields:

  • id — event id;
  • event — event name;
  • created_at — event creation time;
  • data.project — project data;
  • data.invoice — invoice data;
  • data.payment — payment data.

Payload may contain additional fields.

For business logic, merchants should rely only on fields described in public documentation.

invoice.paid

Event invoice.paid means the invoice is paid.

When receiving invoice.paid, the merchant should:

  • verify webhook signature;
  • find the order by order_id or invoice id;
  • check whether the order was already processed;
  • mark the order as paid;
  • issue goods, services or access;
  • save tx_hash if needed for reconciliation;
  • return a successful HTTP response.

Idempotent handling

Webhook may be delivered more than once.

This is normal for webhook delivery.

The merchant backend must handle webhook idempotently.

If the order is already marked as paid, repeated webhook must not issue goods, services, access or create a second payment record again.

What to return

Webhook endpoint should quickly return a successful HTTP response after correct processing.

It is recommended to return status 200 or another successful 2xx.

If the endpoint returns an error, Weelay may treat the delivery as unsuccessful.

Do not run long operations directly inside webhook handler if they may take too much time.

Endpoint security

Webhook endpoint should:

  • accept only POST;
  • accept only JSON;
  • verify signature;
  • check timestamp;
  • not trust webhook without signature;
  • not fulfill the order before checking the event;
  • not log webhook secret;
  • not expose internal errors to the buyer.

Disputes

If the buyer says they paid but webhook was not processed, check:

  • invoice id;
  • order_id;
  • status;
  • paid_at;
  • tx_hash;
  • webhook delivery in dashboard;
  • logs of your webhook endpoint.

If manual review is needed, ask the buyer to provide tx_hash.

Test webhook

In the project dashboard, a test webhook may be available.

Test webhook is used to check endpoint availability, processing format and signature verification before real payments.

A test event must not issue goods or services to the buyer.

Production checklist

Before launch, check:

  • webhook URL uses HTTPS;
  • endpoint accepts POST;
  • endpoint reads raw body;
  • X-Weelay-Signature is verified;
  • timestamp is checked;
  • invoice.paid is handled idempotently;
  • order is fulfilled only once;
  • webhook secret does not appear in logs;
  • endpoint errors are logged by the merchant.

Summary

Webhook is used for automatic merchant notification about payment.

The main event is invoice.paid.

Main rules: verify signature, handle the event idempotently and fulfill the order only once.

Support

Need help?

Contact Weelay support if this page does not answer your question.