70

Update: Since around January 2018, it is now possible to search using the email parameter on Stripe. See the accepted answer.


I was wondering if it was possible to search a customer only by their email address when using the Stripe API.

The documentation only indicates searching by:

created,
ending_before,
limit,
starting_after 

But not email.

I'd like to avoid having to list over all my customers to find which ones have the same email addresses.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Cyril N.
  • 38,875
  • 36
  • 142
  • 243
  • Also, the limit max is 100, therefore, if you have more than 100 customers, then search by email is not guaranteed to result in finding a customer by email. – Greeso Apr 11 '17 at 15:30
  • 1
    Supposedly you can search by email now, but Stripe still stupidly allows multiple customers with the same email, so we'll need to handle duplicates in the results: https://stackoverflow.com/a/40482496/470749 – Ryan May 25 '17 at 20:14
  • 2
    UPDATE: Stripe now allows searching the email address: https://stackoverflow.com/a/38492724/470749 – Ryan May 10 '18 at 20:12
  • 1
    Note that searches are not limited to 100 records. There's up to 100 records per page. You can retrieve more with starting_after parameter – Danial Dec 23 '18 at 22:06

16 Answers16

53

Stripe now allows you to filter customers by email.

https://stripe.com/docs/api#list_customers

Map<String, Object> options = new HashMap<>();
options.put("email", email);
List<Customer> customers = Customer.list(options).getData();

if (customers.size() > 0) {
    Customer customer = customers.get(0);
    ...

This is important to help ensure you don't create duplicate customers. Because you can't put creating a customer in Stripe and the storage of the Stripe customer ID in your system inside a single transaction you need to build in some fail safes that check to see if a particular customer exists before you create a new one. Searching customers by email is important in that regard.

Russ Jackson
  • 1,993
  • 1
  • 18
  • 14
  • 3
    If you don't like generic maps, with the current Java API you can use: List customers = Customer.list(CustomerListParams.builder().setEmail(email).build()).getData(); – cnmuc Mar 11 '20 at 09:35
  • in python `stripe.Customer.list(email=user_email)` – Fed Aug 27 '21 at 19:18
  • 4
    While this solution may work, I think it is still better to store information on customers, including their stripe ID's and emails, locally. A call to the stripe API is always going to be slower and less reliable than a query to your local database. You can use webhooks to process whenever a new customer is created, and save both Stripe's customer ID and any associated email in your database. Then, query them with any action that might trigger customer creation, and if a customer is found, pass the ID to Stripe in the relevant call. – cazort Oct 20 '21 at 19:32
26

I did this by using the following API request. This was not available in stripe docs.I got this by tracking down their search in the dashboard area using Browser Developer Tools.

    url :https://api.stripe.com/v1/search?query="+email+"&prefix=false",
    method: GET
    headers: {
      "authorization": "Bearer Your_seceret Key",
      "content-type": "application/x-www-form-urlencoded",
    }

Warning This uses an undocumented API that is specific to the dashboard. While it might work today, there is no guarantee it will continue to work in the future.

koopajah
  • 23,792
  • 9
  • 78
  • 104
Sufyan Ahmad
  • 818
  • 1
  • 13
  • 22
  • 1
    I think it is worth looking at this answer https://stackoverflow.com/questions/26767150/stripe-is-it-possible-to-search-a-customer-by-their-email#41743023 because it does not use a hack – Greeso Aug 04 '17 at 23:01
  • 1
    Works from Python lib `Requests` without `Content-Type`. – Vitaly Zdanevich Nov 01 '17 at 16:21
  • 1
    I like yours.. The prospect with while looping through 300,000 users doesn't seem a good use of network traffic. – baash05 Nov 30 '18 at 02:40
20

You need to retrieve and store the Stripe customer ID along with the other customer details in your database. You can then search for the email address in your database and retrieve the customer record from Stripe by using the Stripe customer ID.

Simeon Visser
  • 118,920
  • 18
  • 185
  • 180
17

UPDATE: Stripe now allows searching via email address

https://stripe.com/docs/api/php#list_customers https://stripe.com/docs/api/customers/search

/**
 * Remember that Stripe unfortunately allows multiple customers to have the same email address.
 * @see https://stackoverflow.com/a/38492724/470749
 * 
 * @param string $emailAddress
 * @return array
 */
public function getCustomersByEmailAddress($emailAddress) {
    try {
        $matchingCustomers = [];
        $lastResult = null;
        $hasMoreResults = true;
        while ($hasMoreResults) {
            $searchResults = \Stripe\Customer::all([
                        "email" => $emailAddress,
                        "limit" => 100,
                        "starting_after" => $lastResult
            ]);
            $hasMoreResults = $searchResults->has_more;
            foreach ($searchResults->autoPagingIterator() as $customer) {
                $matchingCustomers[] = $customer;
            }
            $lastResult = end($searchResults->data);
        }
        return $matchingCustomers;
    } catch (\Exception $e) {
        Log::error($e);
        return [];
    }
}
Ryan
  • 22,332
  • 31
  • 176
  • 357
  • if u know the date u might as well store and use the customerID – Martijn Scheffer Aug 05 '16 at 13:49
  • 2
    @MartijnScheffer I'm using ClickFunnels, and I'm emailing the new buyer a link to manage the details of her subscription. ClickFunnels doesn't expose the CustomerID. Plus, I'd prefer not to create and manage a database just for 1 or 2 columns of info. So, although I wish Stripe handled this, I've found no other way than my hack here. – Ryan Aug 06 '16 at 21:00
10

You can't directly search by email.

However, you can hack a little bit to list all users, and look after your email.

Here's my code (PHP) :

$last_customer = NULL;
$email = "EmailYou@AreLooking.for";
while (true) {
    $customers = \Stripe\Customer::all(array("limit" => 100, "starting_after" => $last_customer));
    foreach ($customers->autoPagingIterator() as $customer) {
        if ($customer->email == $email) {
            $customerIamLookingFor = $customer;
            break 2;
        }
    }
    if (!$customers->has_more) {
        break;
    }
    $last_customer = end($customers->data);
}
Julien
  • 231
  • 2
  • 8
  • 1
    Perfect, and thanks a lot :). It looks like this is your only answer on SO, and I think it is the best answer to this question. – Greeso Aug 04 '17 at 22:57
  • I really hate infinite loops with break statements...but it worked. – Vasileios Pallas Oct 27 '17 at 11:01
  • They may have changed the API rules in the time since this question was posted: I got the error `You passed an empty string for 'starting_after'. We assume empty values are an attempt to unset a parameter; however 'starting_after' cannot be unset. You should remove 'starting_after' from your request or supply a non-empty value.` on the first loop; therefore I had to insert `if($last_customer){ // ... }else { // .... }` to get this to work. – Inigo Feb 16 '22 at 16:32
  • i.e. `if($last_customer){ $customers = $stripe_client->customers->all(array("limit" => 100, "starting_after" => $last_customer)); }else { $customers = $stripe_client->customers->all(array("limit" => 100)); }` – Inigo Feb 16 '22 at 16:33
8

You only need to write this line

\Stripe\Customer::all(["email" => "YourDesiredEmail"]);

4

In NodeJs we can search for our desired customer with their email address like the following:

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

const findCustomerByEmail = async (email) => {
  try {
    const customer = await stripe.customers.list( {
      email: email,
      limit: 1
  });
   if(customer.data.length !== 0){
    return customer.data[0].id;
   }
  } catch (e) {
   return (e);
 }
};

The actual call to stripe is using the stripe.customers.list. If the email exists in our stripe account then the returned object will contain an element called data.

sediq khan
  • 515
  • 4
  • 10
3

Using "list()" and "search()", you can get customers by email with these Python code below:

customers = stripe.Customer.list(
    email="example@gmail.com",
)
customer = stripe.Customer.search(
    query="email:'example@gmail.com'"
)

You can also limit customers to get with "limit" parameter as shown below:

customers = stripe.Customer.list(
    email="example@gmail.com",
    limit=3
)
customer = stripe.Customer.search(
    query="email:'example@gmail.com'",
    limit=3
)
Henry Ecker
  • 34,399
  • 18
  • 41
  • 57
Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
2

Since you specified that

The documentation only indicate to search by created, ending_before, limit and starting_after, but no "email".

You are right, you can't search using emails.

If you still wish to do that, What you can do instead is to get a list of all the customer and filter on the response you get using email.

For Example, in ruby you can do it as follows:

customers = Stripe::Customer.all

customer_i_need = customers.select do |c|
  c.email == "foo@bar.com"
end

PS: Stripe can have multiple customers associated with one email address.

Sagar Ranglani
  • 5,491
  • 4
  • 34
  • 47
2

Please bear in mind when using Stripe API that it is case sensitive email (which is a bit stupid). Hopefully they change this.

  • This is causing me an issue. I'm trying to figure out a workaround now. – Nate S Feb 03 '21 at 20:22
  • The only thing I can think of is grabbing a hundred at a time and converting to lowercase before comparison. I'll have to make this into a laravel job. Talk about inefficient – Nate S Feb 03 '21 at 21:23
1

Stripe API does not supports any search-by-email feature. They have this search in their dashboard but not released any to API; from the architectural concept it seems that there is no possibility or plan from stripe to include this in API; every object in their API is retrievable only by that specific objects id given by stripe while its created. May be, they have kept it as a scope for third party application developers involvement!!

So, the obvious solution is to store the customers in your own database that you want to be searchable in future - as Simeon Visser has said above

btw, for a workaround, if you already have used the stripe API a lot and there are many customer data which you now need to be searchable - the only way is to go thru the 'List all customers' functionality of API & build the database for your own purpose; ofcourse, you've to use pagination shortcut to iterate thru the whole list for doing so.

$customers = \Stripe\Customer::all(array("limit" => 3));
foreach ($customers->autoPagingIterator() as $customer) {
  // Do something with $customer
}
sanmai
  • 29,083
  • 12
  • 64
  • 76
Arif
  • 308
  • 2
  • 8
1

You can try this. It worked for me. Below code will return empty list if not found data matching with email.

     $stripe = new \Stripe\StripeClient("YOUR_STRIPE_SECRET");

     $customers = $stripe->customers->all(['email'=>'jane.doe@example.com',
        'limit' => 15,
      ]);
U.Malik
  • 111
  • 11
0

Here is The Async- Await Way This Method can Be Used For All Third Party Hits with Nodejs Particularly

    const configuration = {
            headers: {
                "authorization": `Bearer ${Your stripe test key}`,
                "content-type": "application/x-www-form-urlencoded",
            }
          };
          const requestUrl = `https://api.stripe.com/v1/search?
    query=${'email you are to use'} &prefix=false`
        const emailPayment = await axios.get(requestUrl, 
    configuration)

Axiom is Npm for creating http requests... very cool and dead simple

0

Stripe allows the ability to have more than once customer with the same email. That said, if you wanted to, you can pass a filters hash param to the list method to return a single customer or array of customers.

Stripe::Customer.list(email: user.email).data

The above will return an array of Stripe::Customer instances with the email

Zach Colon
  • 177
  • 2
  • 11
0

Stripe Search API Beta now is available

youtube link

BIS Tech
  • 17,000
  • 12
  • 99
  • 148
0

Here it is in C#

private Customer GetCustomerByEmail(string email)
        {
            // gets the most recent customer https://stripe.com/docs/api/customers/list
            var options = new CustomerListOptions
            {
                Email = email,
                Limit = 1,
            };
            var service = new CustomerService();
            StripeList<Customer> customers = service.List(
              options);
            return customers.First();
        }