DeveloperWebhooks & Data

Webhook Events API

Real-time HTTP notifications for customer, subscription, and loyalty events. Includes authentication, payload examples, and code samples.

Subscribfy sends real-time HTTP POST notifications to your endpoints when events occur. Use webhooks to sync customer data, trigger automations, or integrate with third-party systems.

Authentication

Each webhook request is signed using HMAC SHA-256. Verify the signature to ensure requests originate from Subscribfy.

HeaderDescription
SignatureHMAC SHA-256 hash of the request body
TimestampUnix timestamp when event occurred
ShopYour Shopify store domain

Subscribfy Token

Your unique secret token is used to sign all webhook requests. Generate it in Settings > Webhooks

  • Token is shown only once at generation - store it securely
  • If lost, regenerate a new token (invalidates the old one)
  • Never expose your token in client-side code

Signature Verification

$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_SIGNATURE'] ?? '';
$expected = hash_hmac('sha256', $payload, $subscribfyToken);

if (!hash_equals($expected, $signature)) {
    http_response_code(401);
    exit('Invalid signature');
}

$event = json_decode($payload, true);
const crypto = require('crypto');

app.post('/webhook', (req, res) => {
    const signature = req.headers['signature'];
    const payload = JSON.stringify(req.body);
    const expected = crypto
        .createHmac('sha256', process.env.SUBSCRIBFY_TOKEN)
        .update(payload)
        .digest('hex');

    if (signature !== expected) {
        return res.status(401).send('Invalid signature');
    }

    // Process event
    const { topic, data } = req.body;
    console.log(`Received: ${topic}`);
    res.status(200).send('OK');
});
import hmac
import hashlib
from flask import Flask, request

@app.route('/webhook', methods=['POST'])
def webhook():
    signature = request.headers.get('Signature', '')
    payload = request.get_data()
    expected = hmac.new(
        SUBSCRIBFY_TOKEN.encode(),
        payload,
        hashlib.sha256
    ).hexdigest()

    if not hmac.compare_digest(signature, expected):
        return 'Invalid signature', 401

    event = request.get_json()
    return 'OK', 200

Configuration

  1. Go to Settings > Webhooks in the Subscribfy app
  2. Select the event category (Wallet Pass, Membership, etc.)
  3. Enter your endpoint URL(s) - separate multiple URLs with commas
  4. Click Test Call to verify your endpoint
  5. Click Save to activate

Event Reference

Wallet Pass Events

TopicTrigger
wallet_pass/createdNew wallet pass generated for customer
wallet_pass/updatedPass content updated (points, rewards, tier)
wallet_pass/installedPass installed on customer's device
wallet_pass/uninstalledPass removed/uninstalled from device

Membership Events

TopicTrigger
membership/createdNew membership contract created
membership/updatedContract modified (frequency, next date)
membership/pausedMembership paused by customer or admin
membership/resumedPaused/cancelled membership resumed
membership/cancelledMembership cancelled
membership/billing_successPayment processed successfully
membership/billing_failedPayment failed
store_credit/changedCustomer store credits modified

Product Subscription Events

TopicTrigger
product_subscription/createdNew product subscription started
product_subscription/updatedSubscription modified (products, shipping, frequency)
product_subscription/pausedSubscription paused
product_subscription/resumedSubscription resumed
product_subscription/cancelledSubscription cancelled
product_subscription/billing_successRenewal payment successful
product_subscription/billing_failedRenewal payment failed

Loyalty Events

TopicTrigger
loyalty/rule_createdNew loyalty rule created in admin
loyalty/rule_updatedLoyalty rule settings modified
loyalty/rule_completedCustomer completed a rule and earned reward
loyalty/tier_createdNew tier created
loyalty/tier_updatedTier settings modified
loyalty/tier_promotedCustomer promoted to new tier
loyalty/tier_demotedCustomer demoted from tier
loyalty/points_changedCustomer points earned, spent, or adjusted
loyalty/coupon_createdNew coupon created
loyalty/coupon_redeemedCustomer redeemed a loyalty coupon

Payload Structure

All webhooks follow this structure:

{
  "topic": "event/type",
  "data": {
    "customer": { ... }
  }
}

Customer Object

Included in all events:

{
  "customer": {
    "id": "gid://shopify/Customer/123456789",
    "email": "customer@example.com",
    "name": "John Doe",
    "loyalty_points": 1250.00,
    "store_credits": 25.50,
    "birth_date": "1990-05-15",
    "tier": {
      "id": 1,
      "name": "Gold"
    }
  }
}

Example: Wallet Pass Created

{
  "topic": "wallet_pass/created",
  "data": {
    "pass_instance": {
      "status": "Active",
      "serial_number": "955773794",
      "created_at": "2026-01-22T10:30:00.000000Z",
      "deleted_at": null
    },
    "customer": {
      "id": "gid://shopify/Customer/424525265",
      "email": "john@example.com",
      "name": "John Doe",
      "loyalty_points": 500.0,
      "store_credits": 10.0,
      "tier": {
        "id": 2,
        "name": "Silver"
      }
    }
  }
}

Example: Membership Billing Success

{
  "topic": "membership/billing_success",
  "data": {
    "contract": {
      "id": "gid://shopify/SubscriptionContract/123",
      "status": "active",
      "next_billing_date": "2026-02-22",
      "billing_policy": {
        "interval": "month",
        "interval_count": 1
      }
    },
    "order": {
      "id": "gid://shopify/Order/456789",
      "total_price": "29.99",
      "currency": "USD"
    },
    "customer": {
      "id": "gid://shopify/Customer/123456",
      "email": "member@example.com",
      "name": "Jane Smith"
    }
  }
}

Example: Loyalty Points Changed

{
  "topic": "loyalty/points_changed",
  "data": {
    "change": {
      "previous_balance": 500,
      "new_balance": 750,
      "difference": 250,
      "reason": "Order completed",
      "rule_name": "Points per dollar spent"
    },
    "customer": {
      "id": "gid://shopify/Customer/789",
      "email": "loyal@example.com",
      "name": "Mike Johnson",
      "loyalty_points": 750.0,
      "tier": {
        "id": 3,
        "name": "Platinum"
      }
    }
  }
}

Request Details

PropertyValue
MethodPOST
Content-Typeapplication/json
Timeout30 seconds
RetriesNone (ensure your endpoint is reliable)

Best Practices

  • Respond quickly - Return 2xx status within 5 seconds, process asynchronously
  • Verify signatures - Always validate the Signature header
  • Handle duplicates - Use idempotency keys or check for duplicate events
  • Log everything - Store raw payloads for debugging
  • Use HTTPS - All webhook URLs must use HTTPS
  • Monitor failures - Set up alerts for failed webhook deliveries

Troubleshooting

Not receiving webhooks? Verify your endpoint is publicly accessible and returns 2xx status. Check firewall rules.

Invalid signature errors? Ensure you're using the raw request body (not parsed JSON) for HMAC calculation.

Missing events? Check that the specific event type is enabled in Settings > Webhooks.

Test endpoint? Use webhook.site or ngrok for local development testing.

On this page