Skip to main content
RapidDev - Software Development Agency
stripe-guide

How to create a Stripe customer programmatically

Create Stripe customers programmatically using stripe.customers.create() in Node.js. Pass email, name, metadata, and optionally attach a payment method in the same call. This is essential for automating signups, linking users to your database, and enabling recurring billing without manual Dashboard work.

What you'll learn

  • How to create customers via the Stripe Node.js API with full parameters
  • How to attach a payment method during customer creation
  • How to use metadata to link Stripe customers to your database
  • How to handle duplicate customer prevention
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner5 min read15 minutesStripe API v2024-12+, Node.js 18+, any backend frameworkMarch 2026RapidDev Engineering Team
TL;DR

Create Stripe customers programmatically using stripe.customers.create() in Node.js. Pass email, name, metadata, and optionally attach a payment method in the same call. This is essential for automating signups, linking users to your database, and enabling recurring billing without manual Dashboard work.

Programmatic Customer Creation in Stripe

When users sign up for your app, you need to create a matching Stripe customer record automatically. The stripe.customers.create() method accepts email, name, phone, address, metadata, and even a default payment method. By creating customers in code rather than the Dashboard, you can link each Stripe customer to your internal user ID, attach payment methods at signup, and set up subscriptions immediately — all in a single API flow.

Prerequisites

  • A Stripe account with API keys from Dashboard → Developers → API keys
  • Node.js 18 or newer installed
  • The stripe npm package installed (npm install stripe)
  • A basic understanding of async/await in JavaScript

Step-by-step guide

1

Initialize Stripe on your server

Import the Stripe library and initialize it with your secret key from environment variables.

typescript
1const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);

Expected result: The stripe object is ready for API calls.

2

Create a basic customer

Call stripe.customers.create() with the customer's email and name. The API returns the full customer object including the unique cus_ ID.

typescript
1const customer = await stripe.customers.create({
2 email: 'alice@example.com',
3 name: 'Alice Smith',
4 phone: '+15551234567',
5 metadata: {
6 app_user_id: 'usr_98765',
7 signup_source: 'web',
8 },
9});
10
11console.log(customer.id); // cus_...

Expected result: A new customer is created and the cus_ ID is logged.

3

Create a customer with a payment method

If you collected a payment method via Stripe Elements on the frontend (which gives you a pm_ token), attach it during customer creation by setting payment_method and invoice_settings.default_payment_method.

typescript
1const customer = await stripe.customers.create({
2 email: 'bob@example.com',
3 name: 'Bob Jones',
4 payment_method: 'pm_card_visa', // from frontend
5 invoice_settings: {
6 default_payment_method: 'pm_card_visa',
7 },
8});

Expected result: The customer is created with the payment method attached and set as default.

4

Prevent duplicate customers

Before creating a new customer, search by email to see if one already exists. Stripe does not enforce unique emails, so this check is your responsibility.

typescript
1async function findOrCreateCustomer(email, name) {
2 const existing = await stripe.customers.list({ email, limit: 1 });
3 if (existing.data.length > 0) {
4 return existing.data[0];
5 }
6 return stripe.customers.create({ email, name });
7}

Expected result: Returns the existing customer if found, or creates and returns a new one.

5

Test with the Stripe test card

In test mode, use pm_card_visa as a test payment method token, or create a PaymentMethod with card number 4242424242424242 to verify the full flow.

typescript
1// Use the built-in test payment method
2const customer = await stripe.customers.create({
3 email: 'test@example.com',
4 name: 'Test User',
5 payment_method: 'pm_card_visa',
6 invoice_settings: { default_payment_method: 'pm_card_visa' },
7});

Expected result: A test customer is created with a Visa test card attached.

Complete working example

customer-service.js
1const express = require('express');
2const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
3
4const app = express();
5app.use(express.json());
6
7// Find or create a customer
8async function findOrCreateCustomer(email, name, metadata) {
9 const existing = await stripe.customers.list({ email, limit: 1 });
10 if (existing.data.length > 0) {
11 return { customer: existing.data[0], isNew: false };
12 }
13 const customer = await stripe.customers.create({
14 email,
15 name,
16 metadata: metadata || {},
17 });
18 return { customer, isNew: true };
19}
20
21// Create customer endpoint
22app.post('/api/customers', async (req, res) => {
23 try {
24 const { email, name, paymentMethodId, metadata } = req.body;
25
26 if (!email) {
27 return res.status(400).json({ error: 'Email is required' });
28 }
29
30 const { customer, isNew } = await findOrCreateCustomer(email, name, metadata);
31
32 // Attach payment method if provided
33 if (paymentMethodId && isNew) {
34 await stripe.paymentMethods.attach(paymentMethodId, {
35 customer: customer.id,
36 });
37 await stripe.customers.update(customer.id, {
38 invoice_settings: { default_payment_method: paymentMethodId },
39 });
40 }
41
42 res.json({
43 id: customer.id,
44 email: customer.email,
45 name: customer.name,
46 isNew,
47 });
48 } catch (err) {
49 console.error('Customer creation error:', err.message);
50 res.status(500).json({ error: err.message });
51 }
52});
53
54const PORT = process.env.PORT || 3000;
55app.listen(PORT, () => console.log(`Server on port ${PORT}`));

Common mistakes when creating a Stripe customer programmatically

Why it's a problem: Not checking for existing customers before creating

How to avoid: Always search by email with stripe.customers.list({ email }) first. Stripe allows duplicates, which causes billing confusion.

Why it's a problem: Forgetting to store the Stripe customer ID in your database

How to avoid: Save customer.id alongside your user record immediately after creation. Without it, you cannot link future charges or subscriptions.

Why it's a problem: Attaching a payment method without setting it as default

How to avoid: After attaching a payment method, update the customer's invoice_settings.default_payment_method so it is used automatically for invoices and subscriptions.

Why it's a problem: Creating customers from the frontend

How to avoid: Customer creation requires your secret key (sk_). Always create customers from your server, never from client-side code.

Best practices

  • Always deduplicate customers by email before calling stripe.customers.create()
  • Store customer.id in your database immediately after creation for future reference
  • Use metadata to store your internal user ID, plan type, or signup source
  • Attach a payment method during creation for a smoother checkout experience later
  • Set invoice_settings.default_payment_method when attaching a card
  • Use environment variables for your secret key — never hardcode sk_ values
  • Log customer creation events for debugging and audit trails
  • Handle API errors gracefully with try/catch and meaningful error responses

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

Write a Node.js function that creates a Stripe customer with email, name, phone, and metadata. It should first check if a customer with that email already exists and return the existing customer if so. Use the stripe npm package.

Stripe Prompt

Add a customer registration flow to my app. When a user signs up, create a Stripe customer with their email and name, store the customer ID in metadata, and optionally attach a payment method. Prevent duplicate customers by checking email first.

Frequently asked questions

What fields are required to create a Stripe customer?

No fields are technically required — you can call stripe.customers.create({}) with an empty object. However, you should always include at least an email for identification and reconciliation purposes.

Can I create a customer and charge them in the same API call?

Not in a single call, but you can create a customer, then immediately create a PaymentIntent or Checkout Session with that customer ID. The two calls can happen in sequence within the same request handler.

How many metadata fields can I add to a customer?

Up to 50 key-value pairs. Keys can be up to 40 characters and values up to 500 characters. This is enough for most use cases like storing user IDs, plan names, and internal references.

What happens if I create a customer with the same email twice?

Stripe creates two separate customer records with different cus_ IDs. This can cause billing confusion, so always search for existing customers by email before creating new ones.

Can I bulk-create customers via the API?

There is no bulk-create endpoint. You need to call stripe.customers.create() for each customer individually. Use Promise.all() with batches of 10-20 to stay within rate limits (100 requests/second).

What if I need help automating customer creation for a complex signup flow?

For multi-step signup flows with payment method collection, trial periods, and subscription creation, the RapidDev team can help build a production-ready onboarding pipeline integrated with Stripe.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.