This document provides complete technical specifications for Payhip's Public REST API (v2) and Webhooks system.
Payhip sends HTTP POST requests with a JSON body to your configured webhook endpoints whenever monitored events occur.
- Go to Settings > Developer.
- Enter your Webhook Endpoint URL. Multiple endpoints can be comma-separated:
https://api.yourdomain.com/webhooks/payhip, https://backup.yourdomain.com/payhip - Check the events you want to listen to:
paid,refunded,subscription.created,subscription.deleted.
Every webhook payload contains a "signature" property. To authenticate that the request is genuine:
const crypto = require('crypto');
function verifyPayhipWebhook(payloadSignature, apiKey) {
const expectedSignature = crypto
.createHash('sha256')
.update(apiKey)
.digest('hex');
// Use timingSafeEqual to prevent timing attacks
return crypto.timingSafeEqual(
Buffer.from(payloadSignature, 'utf8'),
Buffer.from(expectedSignature, 'utf8')
);
}import hashlib
import hmac
def verify_payhip_webhook(payload_signature: str, api_key: str) -> bool:
expected_signature = hashlib.sha256(api_key.encode('utf-8')).hexdigest()
return hmac.compare_digest(payload_signature, expected_signature)Occurs whenever a customer makes a successful payment.
{
"id": "ZGjVj5x4GN",
"email": "customer@example.com",
"currency": "USD",
"price": 2500,
"vat_applied": true,
"ip_address": "72.334.28.154",
"items": [
{
"product_id": "2804256",
"product_name": "Modern Full-Stack Masterclass",
"product_key": "BaFxk",
"product_permalink": "https://payhip.com/b/BaFxk",
"quantity": "1",
"on_sale": false,
"used_coupon": false,
"used_social_discount": false,
"used_cross_sell_discount": false,
"used_upgrade_discount": false,
"promoted_by_affiliate": false,
"has_variant": false
}
],
"payment_type": "card",
"stripe_fee": 103,
"payhip_fee": 125,
"unconsented_from_emails": false,
"is_gift": false,
"date": 1703693218,
"type": "paid",
"signature": "dbcdccb0dfc5a57rh704bc75d7bbb18hdd3ee85f4081d5c4adbff934622919d8"
}Note
All currency amounts (price, stripe_fee, payhip_fee) are delivered in integer cents/pennies ($25.00 = 2500).
Occurs whenever a transaction is fully or partially refunded.
{
"id": "ZGjVj5x4GN",
"email": "customer@example.com",
"currency": "USD",
"price": 2500,
"amount_refunded": 2500,
"vat_applied": true,
"ip_address": "72.334.28.154",
"items": [
{
"product_id": "2804256",
"product_name": "Modern Full-Stack Masterclass",
"product_key": "BaFxk",
"product_permalink": "https://payhip.com/b/BaFxk",
"quantity": "1"
}
],
"payment_type": "card",
"date_created": 1703693218,
"date_refunded": 1703693410,
"type": "refunded",
"signature": "dbcdccb0dfc5a57rh704bc75d7bbb18hdd3ee85f4081d5c4adbff934622919d8"
}Fires when a new recurring member signs up.
{
"subscription_id": "rdWQN75zjq",
"customer_id": "Q7zqVMy5Bg",
"status": "active",
"customer_email": "member@example.com",
"plan_name": "Pro Membership",
"product_name": "Creator Community",
"product_link": "nb7fD",
"gdpr_consent": "Yes",
"date_subscription_started": 1703694529,
"customer_first_name": "Jane",
"customer_last_name": "Doe",
"type": "subscription.created",
"signature": "dbcdccb0dfc5a57rh704bc75d7bbb18hdd3ee85f4081d5c4adbff934622919d8"
}Fires when a member cancels or defaults on a subscription.
{
"subscription_id": "rdWQN75zjq",
"customer_id": "Q7zqVMy5Bg",
"status": "canceled",
"customer_email": "member@example.com",
"plan_name": "Pro Membership",
"product_name": "Creator Community",
"product_link": "nb7fD",
"gdpr_consent": "Yes",
"date_subscription_started": 1703694529,
"date_subscription_deleted": 1703694700,
"customer_first_name": "Jane",
"customer_last_name": "Doe",
"type": "subscription.deleted",
"signature": "dbcdccb0dfc5a57rh704bc75d7bbb18hdd3ee85f4081d5c4adbff934622919d8"
}Unlike legacy APIs that required root API keys, the v2 License Key API uses a scoped product-secret-key header found in the product edit view under Advanced Options.
| Action | HTTP Method | URL | Headers |
|---|---|---|---|
| Verify Key | GET |
https://payhip.com/api/v2/license/verify?license_key=KEY |
product-secret-key: <KEY> |
| Activate (Increase Use) | PUT |
https://payhip.com/api/v2/license/usage |
product-secret-key: <KEY> |
| Deactivate (Decrease Use) | PUT |
https://payhip.com/api/v2/license/decrease |
product-secret-key: <KEY> |
| Disable / Revoke | PUT |
https://payhip.com/api/v2/license/disable |
product-secret-key: <KEY> |
| Re-enable | PUT |
https://payhip.com/api/v2/license/enable |
product-secret-key: <KEY> |
- Request:
GET /api/v2/license/verify?license_key=WTKP4-66NL5-HMKQW-GFSCZ HTTP/1.1 Host: payhip.com product-secret-key: psk_test_9831aef71cba
- Response:
{ "data": { "enabled": true, "product_link": "BaFxk", "license_key": "WTKP4-66NL5-HMKQW-GFSCZ", "buyer_email": "customer@example.com", "uses": 1, "date": "2026-01-15T09:20:00+00:00" } } - Failure: Returns an empty response (
{}) or HTTP 4xx if the key is invalid or not found.