/stripe-guides

How to create a Stripe customer programmatically?

Learn how to create a Stripe customer programmatically with step-by-step guides, code examples in Node.js, Python, PHP, and Ruby, plus best practices for secure integration.

Matt Graham, CEO of Rapid Developers

Book a call with an Expert

Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.

Book a free consultation

How to create a Stripe customer programmatically?

How to Create a Stripe Customer Programmatically

 

In this comprehensive tutorial, I'll guide you through the process of creating a Stripe customer programmatically using various programming languages and approaches. Creating customers in Stripe allows you to store payment information securely and charge customers repeatedly without having to collect their payment details each time.

 

Step 1: Set Up Your Stripe Account

 

Before you can create customers programmatically, you need to have a Stripe account and obtain your API keys:

  • Sign up for a Stripe account at https://stripe.com if you don't have one
  • Go to the Stripe Dashboard
  • Navigate to Developers → API keys
  • Make note of your publishable key and secret key
  • For testing purposes, use the test mode keys (they start with "pk_test_" and "sk_test_")

 

Step 2: Install the Stripe Library

 

You'll need to install the Stripe library for your programming language. Here are instructions for common languages:

For Node.js:

npm install stripe

For Python:

pip install stripe

For PHP:

composer require stripe/stripe-php

For Ruby:

gem install stripe

 

Step 3: Initialize the Stripe Client

 

After installing the library, you need to initialize the Stripe client with your secret API key.

Node.js:

const stripe = require('stripe')('sk_test_your_secret_key');

// Using ES modules
// import Stripe from 'stripe';
// const stripe = new Stripe('sk_test_your_secret_key');

Python:

import stripe
stripe.api_key = "sk_test_your_secret\_key"

PHP:

Ruby:

require 'stripe'
Stripe.api_key = 'sk_test_your_secret\_key'

 

Step 4: Create a Basic Stripe Customer

 

Now let's create a basic Stripe customer with minimal information.

Node.js:

async function createCustomer() {
  try {
    const customer = await stripe.customers.create({
      email: '[email protected]',
      name: 'John Doe',
      description: 'Customer created programmatically',
    });
    console.log('Success! Customer created:', customer.id);
    return customer;
  } catch (error) {
    console.error('Error creating customer:', error);
    throw error;
  }
}

createCustomer();

Python:

def create\_customer():
    try:
        customer = stripe.Customer.create(
            email='[email protected]',
            name='John Doe',
            description='Customer created programmatically'
        )
        print(f'Success! Customer created: {customer.id}')
        return customer
    except Exception as e:
        print(f'Error creating customer: {e}')
        raise e

create\_customer()

PHP:

 '[email protected]',
            'name' => 'John Doe',
            'description' => 'Customer created programmatically'
        ]);
        echo 'Success! Customer created: ' . $customer->id;
        return $customer;
    } catch (\Exception $e) {
        echo 'Error creating customer: ' . $e->getMessage();
        throw $e;
    }
}

createCustomer();
?>

Ruby:

def create\_customer
  begin
    customer = Stripe::Customer.create({
      email: '[email protected]',
      name: 'John Doe',
      description: 'Customer created programmatically'
    })
    puts "Success! Customer created: #{customer.id}"
    return customer
  rescue Stripe::StripeError => e
    puts "Error creating customer: #{e.message}"
    raise e
  end
end

create\_customer

 

Step 5: Create a Customer with Additional Information

 

You can add more details to the customer object like phone number, address, and metadata.

Node.js:

async function createDetailedCustomer() {
  try {
    const customer = await stripe.customers.create({
      email: '[email protected]',
      name: 'John Doe',
      phone: '+14155552671',
      description: 'Customer with additional details',
      address: {
        line1: '123 Main St',
        city: 'San Francisco',
        state: 'CA',
        postal\_code: '94111',
        country: 'US',
      },
      metadata: {
        user\_id: '12345',
        signup\_date: new Date().toISOString(),
        referral\_source: 'website'
      }
    });
    console.log('Success! Detailed customer created:', customer.id);
    return customer;
  } catch (error) {
    console.error('Error creating detailed customer:', error);
    throw error;
  }
}

createDetailedCustomer();

Python:

import datetime

def create_detailed_customer():
    try:
        customer = stripe.Customer.create(
            email='[email protected]',
            name='John Doe',
            phone='+14155552671',
            description='Customer with additional details',
            address={
                'line1': '123 Main St',
                'city': 'San Francisco',
                'state': 'CA',
                'postal\_code': '94111',
                'country': 'US',
            },
            metadata={
                'user\_id': '12345',
                'signup\_date': datetime.datetime.now().isoformat(),
                'referral\_source': 'website'
            }
        )
        print(f'Success! Detailed customer created: {customer.id}')
        return customer
    except Exception as e:
        print(f'Error creating detailed customer: {e}')
        raise e

create_detailed_customer()

 

Step 6: Create a Customer with a Payment Method

 

To charge customers in the future, you'll typically want to attach a payment method to them.

Node.js:

async function createCustomerWithPaymentMethod() {
  try {
    // First, create a Payment Method (this would usually come from your frontend)
    // Here we're using test card details for demonstration
    const paymentMethod = await stripe.paymentMethods.create({
      type: 'card',
      card: {
        number: '4242424242424242',
        exp\_month: 12,
        exp\_year: 2025,
        cvc: '123',
      },
    });

    // Next, create a Customer
    const customer = await stripe.customers.create({
      email: '[email protected]',
      name: 'John Doe',
      payment\_method: paymentMethod.id,
      invoice\_settings: {
        default_payment_method: paymentMethod.id,
      },
    });

    // Attach the Payment Method to the Customer
    await stripe.paymentMethods.attach(
      paymentMethod.id,
      {customer: customer.id}
    );

    console.log('Success! Customer created with payment method:', customer.id);
    return customer;
  } catch (error) {
    console.error('Error creating customer with payment method:', error);
    throw error;
  }
}

createCustomerWithPaymentMethod();

Python:

def create_customer_with_payment_method():
    try:
        # First, create a Payment Method (this would usually come from your frontend)
        # Here we're using test card details for demonstration
        payment\_method = stripe.PaymentMethod.create(
            type="card",
            card={
                "number": "4242424242424242",
                "exp\_month": 12,
                "exp\_year": 2025,
                "cvc": "123",
            },
        )

        # Next, create a Customer
        customer = stripe.Customer.create(
            email="[email protected]",
            name="John Doe",
            payment_method=payment_method.id,
            invoice\_settings={
                "default_payment_method": payment\_method.id,
            },
        )

        # Attach the Payment Method to the Customer
        stripe.PaymentMethod.attach(
            payment\_method.id,
            customer=customer.id,
        )

        print(f'Success! Customer created with payment method: {customer.id}')
        return customer
    except Exception as e:
        print(f'Error creating customer with payment method: {e}')
        raise e

create_customer_with_payment_method()

 

Step 7: Create a Customer from a Frontend Tokenized Card

 

In a real application, you typically collect payment information securely via Stripe Elements on the frontend, then pass a token or payment method ID to your backend.

Frontend (HTML/JavaScript):

<!DOCTYPE html>
<html>
<head>
  <title>Create Stripe Customer</title>
  <script src="https://js.stripe.com/v3/"></script>
  <style>
    .form-row {
      margin: 10px 0;
    }
    #card-element {
      border: 1px solid #ccc;
      padding: 10px;
      border-radius: 4px;
    }
    #card-errors {
      color: red;
      margin-top: 5px;
    }
    button {
      margin-top: 15px;
      padding: 8px 15px;
    }
  </style>
</head>
<body>
  <h1>Create a Stripe Customer</h1>
  
  <form id="payment-form">
    <div class="form-row">
      <label for="name">Name</label>
      <input id="name" name="name" type="text" placeholder="Jane Doe" required>
    </div>
    
    <div class="form-row">
      <label for="email">Email</label>
      <input id="email" name="email" type="email" placeholder="[email protected]" required>
    </div>
    
    <div class="form-row">
      <label for="card-element">Credit or debit card</label>
      <div id="card-element">
        <!-- Stripe.js will inject the Card Element here -->
      </div>
      <div id="card-errors" role="alert"></div>
    </div>
    
    <button type="submit">Create Customer</button>
  </form>

  <script>
    // Initialize Stripe.js
    const stripe = Stripe('pk_test_your_publishable_key');
    const elements = stripe.elements();
    
    // Create an instance of the card Element
    const cardElement = elements.create('card');
    
    // Add an instance of the card Element into the `card-element` div
    cardElement.mount('#card-element');
    
    // Handle form submission
    const form = document.getElementById('payment-form');
    form.addEventListener('submit', async (event) => {
      event.preventDefault();
      
      const name = document.getElementById('name').value;
      const email = document.getElementById('email').value;
      
      // Create a PaymentMethod
      const { paymentMethod, error } = await stripe.createPaymentMethod({
        type: 'card',
        card: cardElement,
        billing\_details: {
          name: name,
          email: email
        }
      });
      
      if (error) {
        // Show error to your customer
        const errorElement = document.getElementById('card-errors');
        errorElement.textContent = error.message;
      } else {
        // Send the payment method ID to your server
        const result = await fetch('/create-customer', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json'
          },
          body: JSON.stringify({
            name: name,
            email: email,
            paymentMethodId: paymentMethod.id
          })
        });
        
        const data = await result.json();
        
        if (data.error) {
          const errorElement = document.getElementById('card-errors');
          errorElement.textContent = data.error;
        } else {
          alert(`Customer created successfully! Customer ID: ${data.customerId}`);
          form.reset();
        }
      }
    });
  </script>
</body>
</html>

Backend (Node.js/Express):

const express = require('express');
const bodyParser = require('body-parser');
const stripe = require('stripe')('sk_test_your_secret_key');

const app = express();

// Middleware
app.use(express.static('public'));
app.use(bodyParser.json());

// Create customer endpoint
app.post('/create-customer', async (req, res) => {
  const { name, email, paymentMethodId } = req.body;
  
  try {
    // Create a customer
    const customer = await stripe.customers.create({
      name: name,
      email: email,
      payment\_method: paymentMethodId,
      invoice\_settings: {
        default_payment_method: paymentMethodId,
      }
    });
    
    // Attach the payment method to the customer
    await stripe.paymentMethods.attach(
      paymentMethodId,
      { customer: customer.id }
    );
    
    res.json({ 
      success: true, 
      customerId: customer.id 
    });
  } catch (error) {
    res.json({ 
      success: false, 
      error: error.message 
    });
  }
});

// Start server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

 

Step 8: Update an Existing Customer

 

After creating a customer, you might need to update their information.

Node.js:

async function updateCustomer(customerId) {
  try {
    const customer = await stripe.customers.update(
      customerId,
      {
        email: '[email protected]',
        name: 'Updated Name',
        phone: '+14155552672',
        metadata: {
          updated\_at: new Date().toISOString(),
          status: 'active'
        }
      }
    );
    console.log('Success! Customer updated:', customer.id);
    return customer;
  } catch (error) {
    console.error('Error updating customer:', error);
    throw error;
  }
}

// Usage:
// updateCustomer('cus\_1234567890');

Python:

import datetime

def update_customer(customer_id):
    try:
        customer = stripe.Customer.modify(
            customer\_id,
            email='[email protected]',
            name='Updated Name',
            phone='+14155552672',
            metadata={
                'updated\_at': datetime.datetime.now().isoformat(),
                'status': 'active'
            }
        )
        print(f'Success! Customer updated: {customer.id}')
        return customer
    except Exception as e:
        print(f'Error updating customer: {e}')
        raise e

# Usage:
# update_customer('cus_1234567890')

 

Step 9: Retrieve a Customer

 

You can fetch a customer's details using their ID.

Node.js:

async function retrieveCustomer(customerId) {
  try {
    const customer = await stripe.customers.retrieve(customerId);
    console.log('Customer retrieved:', customer);
    return customer;
  } catch (error) {
    console.error('Error retrieving customer:', error);
    throw error;
  }
}

// Usage:
// retrieveCustomer('cus\_1234567890');

Python:

def retrieve_customer(customer_id):
    try:
        customer = stripe.Customer.retrieve(customer\_id)
        print(f'Customer retrieved: {customer}')
        return customer
    except Exception as e:
        print(f'Error retrieving customer: {e}')
        raise e

# Usage:
# retrieve_customer('cus_1234567890')

 

Step 10: Delete a Customer

 

When you no longer need a customer, you can delete them.

Node.js:

async function deleteCustomer(customerId) {
  try {
    const deleted = await stripe.customers.del(customerId);
    console.log('Customer deleted:', deleted);
    return deleted;
  } catch (error) {
    console.error('Error deleting customer:', error);
    throw error;
  }
}

// Usage:
// deleteCustomer('cus\_1234567890');

Python:

def delete_customer(customer_id):
    try:
        deleted = stripe.Customer.delete(customer\_id)
        print(f'Customer deleted: {deleted}')
        return deleted
    except Exception as e:
        print(f'Error deleting customer: {e}')
        raise e

# Usage:
# delete_customer('cus_1234567890')

 

Step 11: List All Customers

 

You can retrieve a list of all customers with pagination.

Node.js:

async function listCustomers(limit = 10) {
  try {
    const customers = await stripe.customers.list({
      limit: limit,
    });
    console.log('Customers retrieved:', customers.data.length);
    return customers;
  } catch (error) {
    console.error('Error listing customers:', error);
    throw error;
  }
}

// Usage:
// listCustomers(20);

Python:

def list\_customers(limit=10):
    try:
        customers = stripe.Customer.list(limit=limit)
        print(f'Customers retrieved: {len(customers.data)}')
        return customers
    except Exception as e:
        print(f'Error listing customers: {e}')
        raise e

# Usage:
# list\_customers(20)

 

Step 12: Handle Errors Properly

 

Always implement proper error handling when interacting with the Stripe API.

Node.js:

async function createCustomerWithErrorHandling() {
  try {
    const customer = await stripe.customers.create({
      email: '[email protected]',
      name: 'John Doe',
    });
    return customer;
  } catch (error) {
    if (error.type === 'StripeCardError') {
      // Problem with the card (e.g., declined)
      console.error('Card error:', error.message);
    } else if (error.type === 'StripeInvalidRequestError') {
      // Invalid parameters were supplied to Stripe's API
      console.error('Invalid parameters:', error.message);
    } else if (error.type === 'StripeAPIError') {
      // An error occurred internally with Stripe's API
      console.error('API error:', error.message);
    } else if (error.type === 'StripeConnectionError') {
      // Some kind of error occurred during the HTTPS communication
      console.error('Connection error:', error.message);
    } else if (error.type === 'StripeAuthenticationError') {
      // You probably used an incorrect API key
      console.error('Authentication error:', error.message);
    } else if (error.type === 'StripeRateLimitError') {
      // Too many requests made to the API too quickly
      console.error('Rate limit error:', error.message);
    } else {
      // Unknown error
      console.error('Unknown error:', error.message);
    }
    throw error;
  }
}

Python:

def create_customer_with_error_handling():
    try:
        customer = stripe.Customer.create(
            email='[email protected]',
            name='John Doe',
        )
        return customer
    except stripe.error.CardError as e:
        # Problem with the card (e.g., declined)
        print(f"Card error: {e.error.message}")
    except stripe.error.InvalidRequestError as e:
        # Invalid parameters were supplied to Stripe's API
        print(f"Invalid parameters: {e.error.message}")
    except stripe.error.APIError as e:
        # An error occurred internally with Stripe's API
        print(f"API error: {e.error.message}")
    except stripe.error.APIConnectionError as e:
        # Network communication with Stripe failed
        print(f"Connection error: {e.error.message}")
    except stripe.error.AuthenticationError as e:
        # Authentication with Stripe's API failed
        print(f"Authentication error: {e.error.message}")
    except stripe.error.RateLimitError as e:
        # Too many requests made to the API too quickly
        print(f"Rate limit error: {e.error.message}")
    except Exception as e:
        # Something else happened
        print(f"Unknown error: {str(e)}")
        raise e

 

Step 13: Best Practices for Stripe Customer Creation

 

Here are some best practices to follow when creating Stripe customers:

  • Always use HTTPS for any communication with the Stripe API
  • Keep your API keys secure and never expose them in client-side code
  • Use webhooks to receive notifications about customer events
  • Implement idempotency keys for important operations to prevent duplicate actions
  • Store the Stripe customer ID in your database to reference it later
  • Use metadata to store additional custom information about customers
  • Implement proper error handling for all Stripe API calls
  • Follow PCI compliance guidelines when handling payment information
  • Consider implementing automated tests for your Stripe integration

 

Step 14: Using Idempotency Keys

 

Idempotency keys help prevent duplicate operations when network issues occur.

Node.js:

async function createCustomerWithIdempotencyKey() {
  const idempotencyKey = `customer_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`;
  
  try {
    const customer = await stripe.customers.create(
      {
        email: '[email protected]',
        name: 'John Doe',
      },
      {
        idempotencyKey: idempotencyKey,
      }
    );
    console.log('Success! Customer created with idempotency key:', customer.id);
    return customer;
  } catch (error) {
    console.error('Error creating customer:', error);
    throw error;
  }
}

createCustomerWithIdempotencyKey();

Python:

import time
import random
import string

def create_customer_with_idempotency_key():
    # Generate a unique idempotency key
    random_string = ''.join(random.choices(string.ascii_lowercase + string.digits, k=10))
    idempotency_key = f"customer_{int(time.time())}_{random_string}"
    
    try:
        customer = stripe.Customer.create(
            email='[email protected]',
            name='John Doe',
            idempotency_key=idempotency_key
        )
        print(f'Success! Customer created with idempotency key: {customer.id}')
        return customer
    except Exception as e:
        print(f'Error creating customer: {e}')
        raise e

create_customer_with_idempotency_key()

 

Step 15: Implementing Webhooks for Customer Events

 

Set up webhooks to receive notifications when customer events occur.

Node.js/Express:

const express = require('express');
const bodyParser = require('body-parser');
const stripe = require('stripe')('sk_test_your_secret_key');

const app = express();

// For webhook signatures, use raw body
app.use('/webhook', 
  express.raw({type: 'application/json'}),
  async (req, res) => {
    const sig = req.headers['stripe-signature'];
    const endpointSecret = 'whsec_your_signing\_secret';
    
    let event;
    
    try {
      event = stripe.webhooks.constructEvent(req.body, sig, endpointSecret);
    } catch (err) {
      console.error(`Webhook Error: ${err.message}`);
      return res.status(400).send(`Webhook Error: ${err.message}`);
    }
    
    // Handle the event
    switch (event.type) {
      case 'customer.created':
        const customerCreated = event.data.object;
        console.log('Customer created:', customerCreated.id);
        // Update your database, send a welcome email, etc.
        break;
        
      case 'customer.updated':
        const customerUpdated = event.data.object;
        console.log('Customer updated:', customerUpdated.id);
        // Update your database with new customer details
        break;
        
      case 'customer.deleted':
        const customerDeleted = event.data.object;
        console.log('Customer deleted:', customerDeleted.id);
        // Update your database to mark this customer as deleted
        break;
        
      case 'customer.subscription.created':
        const subscription = event.data.object;
        console.log('Subscription created for customer:', subscription.customer);
        // Update customer subscription status
        break;
        
      // Add more customer-related events as needed
        
      default:
        console.log(`Unhandled event type ${event.type}`);
    }
    
    // Return a 200 response to acknowledge receipt of the event
    res.send();
  }
);

// Other routes
app.use(bodyParser.json());
// ... your other endpoints

// Start server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

Python (Flask):

from flask import Flask, request, jsonify
import stripe

app = Flask(**name**)
stripe.api_key = "sk_test_your_secret\_key"
endpoint_secret = "whsec_your_signing_secret"

@app.route('/webhook', methods=['POST'])
def webhook():
    payload = request.get_data(as_text=True)
    sig\_header = request.headers.get('Stripe-Signature')

    try:
        event = stripe.Webhook.construct\_event(
            payload, sig_header, endpoint_secret
        )
    except ValueError as e:
        # Invalid payload
        return jsonify(success=False), 400
    except stripe.error.SignatureVerificationError as e:
        # Invalid signature
        return jsonify(success=False), 400

    # Handle the event
    if event['type'] == 'customer.created':
        customer = event\['data']\['object']
        print(f"Customer created: {customer['id']}")
        # Update your database, send welcome email, etc.
        
    elif event['type'] == 'customer.updated':
        customer = event\['data']\['object']
        print(f"Customer updated: {customer['id']}")
        # Update your database with new customer details
        
    elif event['type'] == 'customer.deleted':
        customer = event\['data']\['object']
        print(f"Customer deleted: {customer['id']}")
        # Update your database to mark this customer as deleted
        
    elif event['type'] == 'customer.subscription.created':
        subscription = event\['data']\['object']
        print(f"Subscription created for customer: {subscription['customer']}")
        # Update customer subscription status
        
    else:
        print(f"Unhandled event type {event['type']}")

    return jsonify(success=True)

if **name** == '**main**':
    app.run(port=3000)

 

This comprehensive guide covers the essential aspects of creating Stripe customers programmatically. By following these steps, you should be able to implement a robust Stripe customer management system in your application. Remember to follow best practices for security and error handling, and to thoroughly test your integration before deploying to production.

Want to explore opportunities to work with us?

Connect with our team to unlock the full potential of no-code solutions with a no-commitment consultation!

Book a Free Consultation

Client trust and success are our top priorities

When it comes to serving you, we sweat the little things. That’s why our work makes a big impact.

Rapid Dev was an exceptional project management organization and the best development collaborators I've had the pleasure of working with. They do complex work on extremely fast timelines and effectively manage the testing and pre-launch process to deliver the best possible product. I'm extremely impressed with their execution ability.

CPO, Praction - Arkady Sokolov

May 2, 2023

Working with Matt was comparable to having another co-founder on the team, but without the commitment or cost. He has a strategic mindset and willing to change the scope of the project in real time based on the needs of the client. A true strategic thought partner!

Co-Founder, Arc - Donald Muir

Dec 27, 2022

Rapid Dev are 10/10, excellent communicators - the best I've ever encountered in the tech dev space. They always go the extra mile, they genuinely care, they respond quickly, they're flexible, adaptable and their enthusiasm is amazing.

Co-CEO, Grantify - Mat Westergreen-Thorne

Oct 15, 2022

Rapid Dev is an excellent developer for no-code and low-code solutions.
We’ve had great success since launching the platform in November 2023. In a few months, we’ve gained over 1,000 new active users. We’ve also secured several dozen bookings on the platform and seen about 70% new user month-over-month growth since the launch.

Co-Founder, Church Real Estate Marketplace - Emmanuel Brown

May 1, 2024 

Matt’s dedication to executing our vision and his commitment to the project deadline were impressive. 
This was such a specific project, and Matt really delivered. We worked with a really fast turnaround, and he always delivered. The site was a perfect prop for us!

Production Manager, Media Production Company - Samantha Fekete

Sep 23, 2022