DEV Community

Cover image for Solved: Syncing Stripe Customers to Intercom for Better Support Context
Darian Vance
Darian Vance

Posted on • Originally published at wp.me

Solved: Syncing Stripe Customers to Intercom for Better Support Context

🚀 Executive Summary

TL;DR: This guide addresses the problem of fragmented customer data between Stripe and Intercom, which hinders efficient support. It provides a step-by-step Python-based solution to automatically sync Stripe customer and subscription details into Intercom’s custom attributes, enabling support agents with immediate, comprehensive context.

🎯 Key Takeaways

  • Securely obtain and manage Stripe Secret API Keys and Intercom Personal Access Tokens using environment variables and python-dotenv.
  • Utilize Python virtual environments (venv) and install stripe, intercom-python, and python-dotenv for dependency management.
  • Fetch all Stripe customers efficiently using stripe.Customer.list().auto\_paging\_iter() to handle pagination automatically.
  • Map Stripe customer IDs to Intercom’s external\_id for robust upsert operations (create or update) and link customer profiles across platforms.
  • Enrich Intercom user profiles with Stripe data (e.g., balance, currency, livemode, subscription\_status, plan\_name) by mapping them to custom attributes.
  • Implement comprehensive error handling for both Stripe and Intercom API calls to ensure script robustness and graceful failure.
  • Be aware of API rate limits for both Stripe and Intercom; for large datasets, consider batching or introducing delays to prevent HTTP 429 errors.
  • Enhance the solution with Stripe Webhooks for real-time updates, integrate more data sources, or deploy as a scheduled job (e.g., cron, AWS Lambda) for continuous synchronization.

Syncing Stripe Customers to Intercom for Better Support Context

As a DevOps Engineer, you know the value of connected systems. Fragmented data across different platforms is a common pain point, especially when it comes to customer support. Imagine a customer reaching out to your support team on Intercom, but your agents have no immediate access to their subscription status, payment history, or recent activity from Stripe. This lack of context leads to slower resolution times, frustrated customers, and inefficient support operations. Manually looking up customer details in separate dashboards is not only tedious but also prone to human error and simply doesn’t scale.

At TechResolve, we believe in automating away these inefficiencies. This tutorial will guide you through building a robust, automated solution to sync your Stripe customer data directly into Intercom. By integrating these two critical platforms, your support agents will gain immediate access to comprehensive customer profiles, enabling them to provide faster, more personalized, and effective support. No more tab-switching, no more guesswork – just streamlined support with all the context you need, right where you need it.

Prerequisites

Before we dive into the integration, ensure you have the following:

  • A Stripe Account with access to your secret API keys.
  • An Intercom Account with developer permissions to generate a Personal Access Token.
  • Python 3.7+ installed on your system.
  • pip (Python package installer), usually included with Python 3.
  • A basic understanding of Python programming and API concepts.
  • Familiarity with environment variables for securely storing API keys.

Step-by-Step Guide: Integrating Stripe and Intercom

We’ll break down the integration into four clear steps: obtaining credentials, setting up your environment, fetching data from Stripe, and finally, pushing that data to Intercom.

Step 1: Obtain API Credentials

Security is paramount. Your API keys grant programmatic access to sensitive data, so treat them like passwords and never expose them in your code or public repositories. We’ll use environment variables for this.

Stripe Secret Key

Log in to your Stripe Dashboard. Navigate to the “Developers” section (usually on the left sidebar), then click on “API Keys.” You’ll see a “Publishable key” and a “Secret key.” We need the Secret key. If it’s hidden, click “Reveal test key” or “Reveal live key” to copy it. For this tutorial, using a test key is recommended first.

Intercom Personal Access Token

Log in to your Intercom workspace. Go to “Settings” (bottom left gear icon) > “Developers” > “Developer Hub.” From there, click on “Your apps,” then select an existing app or “New app.” Under “Authentication,” you’ll find “Personal Access Tokens.” Generate a new token and ensure it has the necessary permissions (e.g., read_users, write_users) to manage users. Copy this token.

Create a file named .env in your project directory to store these keys:

STRIPE_SECRET_KEY="sk_test_YOUR_STRIPE_SECRET_KEY"
INTERCOM_ACCESS_TOKEN="dGhpcyBpcyBhIHNhbXBsZSB0b2tlbiBhbmQgbm90IGEgbGl2ZSBvbmU="
Enter fullscreen mode Exit fullscreen mode

Step 2: Set Up Your Python Environment

It’s always best practice to work within a virtual environment to manage project dependencies without conflicts.

  1. Create a virtual environment:
   python3 -m venv venv
Enter fullscreen mode Exit fullscreen mode
  1. Activate the virtual environment:

    • On macOS/Linux:
     source venv/bin/activate
    
  • On Windows:

     .\venv\Scripts\activate
    
  1. Install necessary libraries:

We’ll use stripe for Stripe API interaction, intercom-python for Intercom API interaction, and python-dotenv to load our environment variables.

   pip install stripe intercom-python python-dotenv
Enter fullscreen mode Exit fullscreen mode

Step 3: Fetch Customers from Stripe

Now, let’s write the Python code to fetch your customer data from Stripe. We’ll iterate through all customers to ensure we get a complete list.

Create a file named sync_stripe_intercom.py:

import os
import stripe
from dotenv import load_dotenv

# Load environment variables from .env file
load_dotenv()

# Initialize Stripe API key
stripe.api_key = os.environ.get("STRIPE_SECRET_KEY")

def get_stripe_customers():
    """
    Fetches all customers from Stripe using auto-pagination.
    Returns a list of Stripe Customer objects.
    """
    customers = []
    try:
        # Use auto_paging_iter to handle pagination automatically for large datasets
        for customer in stripe.Customer.list(limit=100).auto_paging_iter():
            customers.append(customer)
        print(f"Successfully fetched {len(customers)} customers from Stripe.")
    except stripe.error.StripeError as e:
        print(f"Error fetching Stripe customers: {e}")
        exit(1)
    return customers

if __name__ == "__main__":
    print("Starting Stripe customer fetch process...")
    stripe_customers = get_stripe_customers()
    if stripe_customers:
        print("First 5 Stripe customers (for preview):")
        for customer in stripe_customers[:5]:
            print(f"  ID: {customer.id}, Email: {customer.email}, Name: {customer.name}")
    else:
        print("No customers found in Stripe or an error occurred.")
Enter fullscreen mode Exit fullscreen mode

Logic Explanation:

  • We import os to interact with environment variables, stripe for the Stripe API, and load_dotenv to load our .env file.
  • stripe.api_key is set using the secret key from your environment.
  • The get_stripe_customers function uses stripe.Customer.list(). Crucially, .auto_paging_iter() ensures that if you have more than the default 100 customers, it automatically fetches all subsequent pages of results, saving you from manual pagination logic.
  • Error handling for Stripe API issues is included to make the script more robust.

Step 4: Sync Customers to Intercom

With our Stripe customer data in hand, the next step is to push it to Intercom. Intercom allows you to create or update users based on their email or a unique external_id. We’ll use the Stripe customer ID as the external_id in Intercom for robust linking and the customer’s email.

Extend your sync_stripe_intercom.py file with the Intercom integration logic:

import os
import stripe
import intercom
from dotenv import load_dotenv

# Load environment variables from .env file
load_dotenv()

# Initialize Stripe API key
stripe.api_key = os.environ.get("STRIPE_SECRET_KEY")

# Initialize Intercom Client
intercom_client = intercom.Client(personal_access_token=os.environ.get("INTERCOM_ACCESS_TOKEN"))

def get_stripe_customers():
    """
    Fetches all customers from Stripe using auto-pagination.
    Returns a list of Stripe Customer objects.
    """
    customers = []
    try:
        for customer in stripe.Customer.list(limit=100).auto_paging_iter():
            customers.append(customer)
        print(f"Successfully fetched {len(customers)} customers from Stripe.")
    except stripe.error.StripeError as e:
        print(f"Error fetching Stripe customers: {e}")
        # Depending on criticality, you might want to log and continue or exit
        exit(1)
    return customers

def sync_customer_to_intercom(stripe_customer):
    """
    Syncs a single Stripe customer to Intercom, creating or updating them.
    """
    if not stripe_customer.email:
        print(f"  Skipping Stripe customer {stripe_customer.id} as no email address was found.")
        return

    # Prepare data for Intercom.
    # Intercom's `save` method acts as an upsert based on email or external_id.
    intercom_data = {
        "email": stripe_customer.email,
        "name": stripe_customer.name or stripe_customer.email.split('@')[0], # Use email prefix if name is missing
        "external_id": stripe_customer.id, # Link Stripe Customer ID to Intercom
        "signed_up_at": stripe_customer.created, # Unix timestamp of creation
        "custom_attributes": {
            "stripe_customer_id": stripe_customer.id,
            "stripe_balance": stripe_customer.balance,
            "stripe_currency": stripe_customer.currency,
            "livemode": stripe_customer.livemode,
            "stripe_created": stripe_customer.created # Duplicate for clarity if desired
        }
    }

    # Fetch subscriptions to add more context
    try:
        subscriptions = stripe.Subscription.list(customer=stripe_customer.id, status='active').data
        if subscriptions:
            # Taking the first active subscription for summary attributes
            first_sub = subscriptions[0]
            intercom_data["custom_attributes"]["stripe_subscription_status"] = first_sub.status
            intercom_data["custom_attributes"]["stripe_subscription_id"] = first_sub.id
            intercom_data["custom_attributes"]["stripe_subscription_plan"] = first_sub.plan.name if first_sub.plan else "N/A"
            intercom_data["custom_attributes"]["stripe_current_period_end"] = first_sub.current_period_end
            intercom_data["custom_attributes"]["stripe_cancel_at_period_end"] = first_sub.cancel_at_period_end
        else:
            intercom_data["custom_attributes"]["stripe_subscription_status"] = "no_active_subscription"

    except stripe.error.StripeError as e:
        print(f"  Warning: Could not fetch subscriptions for {stripe_customer.id}: {e}")
        # Continue syncing the customer even if subscription fetch fails

    try:
        user = intercom_client.users.save(**intercom_data)
        print(f"  Successfully synced/updated Stripe customer {stripe_customer.id} as Intercom User ID: {user.id}")
    except intercom.errors.IntercomError as e:
        print(f"  Error syncing Stripe customer {stripe_customer.id} ({stripe_customer.email}): {e}")

if __name__ == "__main__":
    print("Starting Stripe customer to Intercom sync process...")
    all_stripe_customers = get_stripe_customers()

    if all_stripe_customers:
        print(f"Initiating sync for {len(all_stripe_customers)} Stripe customers to Intercom...")
        for customer in all_stripe_customers:
            sync_customer_to_intercom(customer)
        print("Sync process completed.")
    else:
        print("No customers to sync.")
Enter fullscreen mode Exit fullscreen mode

Logic Explanation:

  • We initialize the intercom_client using your Personal Access Token.
  • The sync_customer_to_intercom function takes a Stripe customer object.
  • It constructs a dictionary intercom_data.
    • email and name are standard Intercom fields. We provide a fallback for name if it’s not present in Stripe.
    • external_id is crucial. We map the Stripe customer ID here. This allows Intercom to uniquely identify the user across systems, even if their email changes, and enables the upsert functionality (create if not exists, update if exists).
    • signed_up_at is set from stripe_customer.created, which is a Unix timestamp.
    • custom_attributes is where the magic happens for support context. You can map any relevant Stripe customer properties (like balance, live mode, and importantly, subscription details) to Intercom custom attributes. These will appear on the user’s profile in Intercom.
  • We also fetch active subscriptions for each customer to enrich the Intercom profile with current subscription status and plan details.
  • intercom_client.users.save(**intercom_data) is the core Intercom API call. This method automatically handles creating a new user or updating an existing one based on the provided email and external_id.
  • Comprehensive error handling for both Stripe and Intercom API calls ensures that the script can gracefully handle issues without crashing.

To run your sync script:

python sync_stripe_intercom.py
Enter fullscreen mode Exit fullscreen mode

Watch the output as your customers are synced. Then, check your Intercom workspace; you should see new or updated users with rich Stripe data in their custom attributes!

Common Pitfalls

Even with careful planning, integrations can sometimes hit bumps. Here are a couple of common issues to be aware of:

  1. API Rate Limits: Both Stripe and Intercom have API rate limits to prevent abuse.
    • Stripe: Generally generous (e.g., 100 requests per second for most endpoints). Our script uses auto_paging_iter, which handles multiple requests internally, but if you’re making many other calls, you might hit limits.
    • Intercom: Can be stricter, especially for write operations (e.g., 5 requests per second burst, 2 sustained for some endpoints). For large customer bases, a batch update API or adding small delays (e.g., time.sleep(0.5) after each Intercom call) might be necessary to avoid hitting limits. The intercom-python library often has built-in retry mechanisms, but it’s good to be aware.

If you encounter rate limit errors (often HTTP 429), consider implementing exponential backoff and retries, or processing customers in smaller batches over time.

  1. Authentication Errors / Incorrect API Keys: A common oversight is using an incorrect API key (e.g., a publishable key instead of a secret key, or a test key for a live environment without realizing it). Ensure your environment variables are correctly loaded and contain the right credentials. Double-check permissions on your Intercom Personal Access Token.
  2. Data Mismatches and Missing Fields: Not all Stripe customers will have a name, or even an email in rare cases. Our script handles missing names by falling back to a part of the email address. However, if your Intercom workflow strictly requires certain fields, ensure your data mapping logic accounts for potential nulls or provides sensible defaults.

Conclusion

Congratulations! You’ve successfully built an automated system to sync Stripe customer data to Intercom. Your support team now has a richer, more comprehensive view of each customer, directly within their Intercom conversations. This translates to faster issue resolution, more personalized interactions, and a significantly improved customer experience. By eliminating manual data lookups, you free up valuable time for your support agents to focus on what they do best: helping your customers.

This solution is just the beginning. Consider enhancing it by:

  • Implementing Stripe Webhooks to trigger real-time updates to Intercom whenever a customer’s subscription changes or a new customer is created.
  • Adding more custom attributes from Stripe, such as recent invoice details or specific product purchases, to Intercom.
  • Integrating other data sources (e.g., your CRM, product usage data) into Intercom to build an even more holistic customer profile.
  • Deploying this script as a scheduled job using cron, a cloud function (like AWS Lambda or Azure Functions), or a containerized service to keep your data regularly updated.

At TechResolve, we empower you to build intelligent, connected systems. Keep automating, and keep resolving!


Darian Vance

👉 Read the original article on TechResolve.blog


Support my work

If this article helped you, you can buy me a coffee:

👉 https://buymeacoffee.com/darianvance

Top comments (0)