> ## Documentation Index
> Fetch the complete documentation index at: https://ownpay.org/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> OwnPay is licensed under AGPL-3.0 and is completely free - no licensing fees.
> Production docs URL: https://ownpay.org/docs - append .md to any page URL for clean markdown.
> OwnPay requires PHP 8.3+, MySQL/MariaDB, and Redis.
> MCP server available at https://ownpay.org/docs/mcp for programmatic documentation queries.
> Use root-relative links (e.g. /quickstart) for internal navigation - do NOT include /docs prefix.
> Plugin development: consult /developer/plugins/ pages for correct interfaces and manifests.
> Canonical locations: API auth = /api/authentication, webhook verification = /api/webhooks, rate limits = /resources/rate-limiting, transaction statuses = /fundamentals/payment-flow.
> The documentation uses the Diataxis framework: Tutorials (learning), How-to (tasks), Reference (lookup), Explanation (understanding).

# Webhook Integration Tutorial

> End-to-end tutorial for building a webhook receiver that listens for payment.completed events with complete PHP and Node.js code examples.

In this tutorial you will build a webhook receiver that listens for `payment.completed` events from OwnPay and updates your order database. By the end you will have a production-ready endpoint in PHP or Node.js.

## What you will build

A single endpoint (`/webhooks/ownpay`) that:

1. Verifies the HMAC-SHA256 signature
2. Parses the event payload
3. Updates the order status in your database
4. Returns the correct HTTP response codes

## Prerequisites

* An OwnPay instance with a webhook endpoint configured in **Developers → Webhooks**
* A webhook signing secret (shown when you create the endpoint)
* PHP 8.1+ or Node.js 18+ with Express

### Security best practices

* Verify the signature on **every** request - never skip it
* Reject events with timestamps older than 5 minutes to prevent replay attacks
* Only process events you have registered for - ignore unknown event types
* Use HTTPS exclusively - OwnPay never sends webhooks to HTTP endpoints
* Keep your webhook secret in environment variables, never in code

## Related pages

* [Webhooks](/docs/api/webhooks)
* [API overview](/docs/api/overview)
* [Error codes](/docs/api/errors)
* [Testing payments](/docs/developer/testing)


## Related topics

- [Webhooks](/docs/api/webhooks.md)
- [Testing Payments](/docs/developer/testing.md)
- [Gateways - Payment Provider Integrations](/docs/fundamentals/gateways.md)
- [Payment Flow - Transaction Statuses and Lifecycle](/docs/fundamentals/payment-flow.md)
- [Plugin System - Extensible Architecture](/docs/fundamentals/plugins.md)
