Skip to main content

Overview

Customer events are triggered when significant changes occur to customer profiles in the loyalty program. These webhooks enable real-time synchronization with CRM systems, marketing automation platforms, and customer service tools.
Outbound Webhooks: These are events that Zupy sends TO your configured webhook endpoints when customer actions occur. You don’t call these endpoints - you receive them.

Event Types

customer.registered

Triggered when a new customer joins the loyalty program through any channel (POS, mobile app, website, or API).

tier.upgraded

Triggered when a customer’s loyalty tier is upgraded based on their activity and point accumulation.

customer.registered

X-Zupy-Signature
string
required
HMAC-SHA256 signature for request verification
sha256=a3b2c1d4e5f6...
X-Zupy-Event
string
required
Event type identifier
customer.registered

Webhook Payload

event
string
Event type identifier
customer.registered
timestamp
string
Event occurrence timestamp (ISO 8601)
company_id
string
Company identifier where the customer registered
customer
object
Complete customer profile information
welcome_reward
object
Information about welcome rewards granted to new customer

Example Payload

{
  "event": "customer.registered",
  "timestamp": "2025-08-26T15:30:00Z",
  "company_id": "comp_bella_vista",
  "customer": {
    "member_id": "ZP-8B23CD41",
    "whatsapp": "+5511965958122",
    "email": "[email protected]",
    "name": "João Silva",
    "cpf": "12345678901",
    "tier": "bronze",
    "created_at": "2025-08-26T15:30:00Z"
  },
  "welcome_reward": {
    "enabled": true,
    "type": "points",
    "points_awarded": 100
  }
}

Integration Examples

const handleCustomerRegistered = async (webhook) => {
  const { customer, company_id, welcome_reward } = webhook;
  
  try {
    // Create contact in CRM
    const crmContact = await crmClient.createContact({
      email: customer.email,
      phone: customer.whatsapp,
      firstName: customer.name.split(' ')[0],
      lastName: customer.name.split(' ').slice(1).join(' '),
      customFields: {
        loyaltyId: customer.member_id,
        loyaltyTier: customer.tier,
        cpf: customer.cpf,
        companyId: company_id,
        registrationDate: customer.created_at
      },
      tags: ['loyalty-member', customer.tier, 'new-customer']
    });
    
    // Trigger welcome sequence
    if (welcome_reward.enabled) {
      await emailService.triggerSequence('loyalty-welcome', customer.email, {
        customerName: customer.name,
        rewardType: welcome_reward.type,
        pointsAwarded: welcome_reward.points_awarded,
        couponCode: welcome_reward.coupon_code
      });
    }
    
    // Add to marketing segments
    await marketingAutomation.addToSegment(customer.email, 'new-loyalty-members');
    
    console.log(`Customer ${customer.member_id} synced to CRM and automation`);
  } catch (error) {
    console.error('Failed to process customer registration:', error);
    // Consider adding to retry queue
  }
};

tier.upgraded

X-Zupy-Signature
string
required
HMAC-SHA256 signature for request verification
sha256=a3b2c1d4e5f6...
X-Zupy-Event
string
required
Event type identifier
tier.upgraded

Webhook Payload

event
string
Event type identifier
tier.upgraded
timestamp
string
Event occurrence timestamp (ISO 8601)
company_id
string
Company identifier where the tier upgrade occurred
customer
object
Customer information after tier upgrade
tier_change
object
Details about the tier upgrade

Example Payload

{
  "event": "tier.upgraded",
  "timestamp": "2025-08-26T15:30:00Z",
  "company_id": "comp_bella_vista",
  "customer": {
    "member_id": "ZP-4F95FB0A",
    "name": "João Silva",
    "whatsapp": "+5511965958122",
    "email": "[email protected]",
    "tier": "silver"
  },
  "tier_change": {
    "previous_tier": "bronze",
    "new_tier": "silver",
    "qualification_metric": "points_balance",
    "qualification_value": 2500,
    "next_tier_requirements": {
      "tier_name": "gold",
      "points_needed": 2500,
      "total_points_required": 5000
    }
  }
}

Integration Examples

const handleTierUpgraded = async (webhook) => {
  const { customer, tier_change, company_id } = webhook;
  
  try {
    // Update customer record
    await database.updateCustomer(customer.member_id, {
      tier: customer.tier,
      previous_tier: tier_change.previous_tier,
      tier_upgraded_at: webhook.timestamp
    });
    
    // Send congratulatory notification
    const tierBenefits = await getTierBenefits(customer.tier);
    
    await pushNotification.send(customer.member_id, {
      title: `Parabéns! Você subiu para ${customer.tier.toUpperCase()}! 🎉`,
      body: `Aproveite seus novos benefícios: ${tierBenefits.summary}`,
      action: 'view_benefits',
      imageUrl: `https://cdn.zupy.com/tiers/${customer.tier}.jpg`
    });
    
    // Send personalized email
    await emailService.sendTemplate('tier-upgrade-congratulations', customer.email, {
      customerName: customer.name,
      previousTier: tier_change.previous_tier,
      newTier: customer.tier,
      benefits: tierBenefits,
      nextTier: tier_change.next_tier_requirements
    });
    
    // Special handling for VIP customers
    if (customer.tier === 'vip') {
      await handleVipUpgrade(customer, company_id);
    }
    
    // Update marketing segments
    await marketingAutomation.moveSegment(
      customer.email, 
      `tier-${tier_change.previous_tier}`, 
      `tier-${customer.tier}`
    );
    
  } catch (error) {
    console.error('Failed to process tier upgrade:', error);
  }
};

const handleVipUpgrade = async (customer, companyId) => {
  // Notify customer success team
  await slack.sendMessage('#customer-success', {
    text: `🌟 New VIP Customer!`,
    attachments: [{
      color: '#FFD700',
      fields: [
        { title: 'Customer', value: customer.name, short: true },
        { title: 'Member ID', value: customer.member_id, short: true },
        { title: 'Email', value: customer.email, short: true },
        { title: 'WhatsApp', value: customer.whatsapp, short: true }
      ],
      actions: [{
        type: 'button',
        text: 'View Profile',
        url: `https://admin.zupy.com/customers/${customer.member_id}`
      }]
    }]
  });
  
  // Schedule personal outreach
  await crm.createTask({
    title: `VIP Welcome Call - ${customer.name}`,
    description: `New VIP customer needs welcome call and benefits explanation`,
    assignee: 'vip-manager',
    dueDate: new Date(Date.now() + 24 * 60 * 60 * 1000), // Tomorrow
    customerId: customer.member_id
  });
};

Common Use Cases

Customer Onboarding

  • CRM Sync: Create contacts with loyalty data
  • Welcome Sequences: Trigger email/SMS campaigns
  • Marketing Segments: Add to appropriate customer lists
  • Support Integration: Create customer service profiles

VIP Customer Management

  • Account Assignment: Assign dedicated account managers
  • Personal Outreach: Schedule welcome calls and check-ins
  • Exclusive Access: Grant early access to products/events
  • Special Recognition: Send personalized congratulations

Marketing Automation

  • Segmentation: Move customers between tier-based segments
  • Personalization: Customize content based on tier status
  • Retention: Trigger tier-appropriate retention campaigns
  • Upselling: Promote next tier benefits and requirements

Response Requirements

Your webhook endpoint must return a 200 status code to acknowledge successful processing. Any other status code will trigger Zupy’s retry mechanism.
app.post('/webhooks/customer', (req, res) => {
  // Process the webhook
  processCustomerWebhook(req.body);
  
  // Return success response
  res.status(200).json({ 
    received: true,
    processed_at: new Date().toISOString()
  });
});

Testing Customer Webhooks

Use these test scenarios to verify your webhook integration:
Trigger: Create a new customer via API or admin panelExpected Webhook: customer.registeredTest Points:
  • Verify all customer fields are populated
  • Check welcome reward information
  • Confirm CRM/marketing system sync
Development Tip: Use the webhook test feature in the Zupy admin panel to send sample payloads to your development endpoint without triggering actual customer events.