Reputation: 213
When calling Stripe::Customer.all(:limit => 100)
there is a limit of 100 per call. We have a lot more customers than that, and I would like to get them all at once. Am I missing something, or is this only possible by writing a naive loop that checks on the has_more
attribute and then makes a new call until has_more = false
?
Upvotes: 21
Views: 13388
Reputation: 14145
Since Google points here and the question only mentions ruby in the tags, if someone needs the python code, here is @Doug's answer "translated" to the python stripe api, then generalized to get any stripe object:
import stripe #https://stripe.com/docs/api?lang=python
# must loop e.g.: https://stackoverflow.com/questions/23393300/what-is-the-best-practice-to-retrieve-all-customers-from-stripe-api-into-one-lis
def get_all_stripe_objects(stripe_listable):
objects = []
get_more = True
starting_after = None
while get_more:
#stripe.Customer implements ListableAPIResource(APIResource):
resp = stripe_listable.list(limit=100,starting_after=starting_after)
objects.extend(resp['data'])
get_more = resp['has_more']
if len(resp['data'])>0:
starting_after = resp['data'][-1]['id']
return objects
all_stripe_customers = get_all_stripe_objects(stripe.Customer)
all_stripe_products = get_all_stripe_objects(stripe.Product)
Upvotes: 1
Reputation: 675
Adding to docs "auto pagination", https://stripe.com/docs/api/pagination/auto
customers = Stripe::Customer.list({limit: 10})
customers.auto_paging_each do |customer|
# Do something with customer
end
Upvotes: 10
Reputation: 1647
Probably a little late to the game here, but here's a yielding version of Doug's answer which loops through every customer, yielding them to a block:
def each_stripe_customer
starting_after = nil
loop do
customers = Stripe::Customer.list(limit: 100, starting_after: starting_after)
break if customers.data.length == 0
customers.each do |customer|
yield customer
end
starting_after = customers.data.last.id
end
end
You can use this as follows:
each_stripe_customer do |customer|
puts customer.id
end
This abstracts away the fetching of customers from however you actually want to use them.
Upvotes: 13
Reputation: 15523
You are right, you must write a naive loop with a cursor per the stripe docs:
starting_after
optional
A cursor for use in pagination.
starting_after
is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending withobj_foo
, your subsequent call can includestarting_after=obj_foo
in order to fetch the next page of the list.
Here's one in case anyone needs a quick copy-paste.
def self.all_stripe_customers
starting_after = nil
customers = []
loop do
results = Stripe::Customer.list(limit: 100, starting_after: starting_after)
break if results.data.length == 0
customers = customers + results.data
starting_after = results.data.last.id
end
return customers
end
Upvotes: 21
Reputation: 131
Another option is to go to Stripe Dashboard and export all customers to a CSV file. Maybe not the best approach since you will not get the updates, but it's an option.
Upvotes: 2
Reputation: 34155
I would suggest to keep a local copy of customer data. so you get the data from Stripe API only once & use that local copy instead of asking that same data again-again.
For syncing changes, There are two main approaches you might use to make sure your database has the latest state:
In your code that makes API calls to Stripe, be sure you're also updating your local copy, or
Use webhooks to listen for events related to your customers (e.g., customer.created
, customer.deleted
etc). By doing this, you can be sure your local database always matches up with Stripe – even if you change your customer's plan via the dashboard, your webhook endpoint will receive the update.
The primary benefit to storing this data locally apart from getting around API limitations, is speed.
You will want to make sure you're storing the customer ID in your database so that you can match up the Stripe customer with your local user.
Hope it helps
Upvotes: -2