Skip to content

Latest commit

 

History

History
214 lines (180 loc) · 5.87 KB

File metadata and controls

214 lines (180 loc) · 5.87 KB

Payhip API & Webhooks Reference

This document provides complete technical specifications for Payhip's Public REST API (v2) and Webhooks system.


1. Webhooks Architecture

Payhip sends HTTP POST requests with a JSON body to your configured webhook endpoints whenever monitored events occur.

Configuration

  1. Go to Settings > Developer.
  2. Enter your Webhook Endpoint URL. Multiple endpoints can be comma-separated:
    https://api.yourdomain.com/webhooks/payhip, https://backup.yourdomain.com/payhip
    
  3. Check the events you want to listen to: paid, refunded, subscription.created, subscription.deleted.

2. Webhook Signature Verification

Every webhook payload contains a "signature" property. To authenticate that the request is genuine:

$$\text{signature} = \text{SHA-256}(\text{YOUR_API_KEY})$$

Node.js / TypeScript Verification Example

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')
  );
}

Python Verification Example

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)

3. Webhook Event Payloads

Event: paid

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).


Event: refunded

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"
}

Event: subscription.created

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"
}

Event: subscription.deleted

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"
}

4. REST API: Software License Keys (v2)

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.

Endpoints Overview

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>

Verification Details

  • 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.