Integrating Stripe’s Product API Into Your Rails API
A hands-on guide on Stripe’s Product API Integration

Getting Started
Stripe APIs have amazing features for e-commerces and marketplaces. To make our developer’s life easier, they offer SDK for some programming languages, including Ruby.
We will start adding the Stripe SDK Gem to our Gemfile using the following command:
gem 'stripe'
Don’t forget to run bundle install
in your terminal after that.
Now you will need to create a stripe initializer file in your application. For that, run the command below in your terminal:
touch config/initializers/stripe.rb
Then, open the stripe.rb
file and write the content below:
Stripe.api_key = Rails.application.credentials.stripe_secret_key
We didn’t add that Stripe’s Secret Key in our credential file, so let’s do this.
To open your credential file, run the following in your terminal:
EDITOR=nano rails credentials:edit
Get your Stripe Secret Key here.
Your credential file must look like this:
# aws:
# access_key_id: 123
# secret_access_key: 345
# Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies.secret_key_base: [YOUR SECRET KEY BASE]
stripe_secret_key: [YOUR SECRET KEY HERE]
Note that the secret_key_base
is autogenerated; you don’t need to edit.
The Product Logic
This section is about the product logic on our side, our API. It will consist of two models: Product and Price.

Our product model will have as many Prices
related to it as the application needs. But why?
Let’s assume one of your products is an iPhone 13. As you may know, the iPhone 13 has a bunch of variants, including different colors and storage. We want to create a single Product
record that represents the iPhone, and a Price
record for each color variant.
The Product Code
Now we will code the Product
based on the logic we saw above.
Run the following in your terminal:
rails g model Product name description:text stripe_id
Take a closer look at the Product
attributes:
name
will be a string that represents the name of the product;description
will be a string that represents a short text, describing the product;stripe_id
will be a string that represents a reference to ourProduct
in the Stripe API.
Now, run:
rails g model Price title details:text amount_cents:integer product:references stripe_id
When we take a closer look at the Price attribute, we see the following:
title
will be a string that represents the variant of the product we are selling; it could be "Green" for exampledetails
will be a string that represents a short text, describing the product variantamount_cents
will be an integer that represents the value of the product in centsproduct_id
will be an integer that represents a reference to aProduct
stripe_id
will be a string that represents a reference to ourPrice
in the Stripe API.
The product model
- Validation to make sure that
name
andstripe_id
attributes will be always present. - Validation to make sure that
stripe_id
will be unique in the database. - Setup for accepting nested attributes through the product JSON object on creating the endpoint.
- Has Many associations with prices.
- The "after" callbacks will be triggered when one of the record-handling actions is called. This is important to keep our stripe records up to date with our database.
The price model
- Validation to make sure that
title
,stripe_id
, andamount_cents
attributes will be always present. - Belongs To association with a product.
- The “after” callbacks will be triggered when one of the record-handling actions is called. This is important to keep our stripe records up to date with our database.
The products controller
Through this step, we will create a controller for products. The actions will be a simple CRUD.
Run in your terminal:
rails g controller Api::V1::Products index show create update destroy
With the controller created, you will need to edit it and make it look like this:
I will not describe this controller code once I consider you probably already know the logic of a Rails Controller. If you are not familiar, I encourage you to read this article.
The prices controller
Through this step, we will create a controller for prices. The actions will be a simple CRUD.
rails g controller Api::V1::Prices index show create update destroy
With the controller created, you will need to edit it and make it look like this:
Our controllers look awesome!!
The Routes
We will have to edit our routes.rb
file now.
It must look like this:
Rails.application.routes.draw do
namespace :api do
namespace :v1 do
resources :products, except: %i[new edit] do
resources :prices, only: %i[index create]
end resources :prices, only: %i[show update destroy]
end
end
end
Basically, we are setting up CRUD routes for products and prices, but the price routes will be under a product namespace. That means that the format for prices endpoint will always be the following:
/api/v1/products/:product_id/prices
Testing Our API on an HTTP Client
To test our API, you need to raise your server, and run it on your terminal using the following command:
rails s
Creating the product
Method: POST | URL: http://localhost:3000/api/v1/products
Headers: { “Content-Type”: “application/json” }
Updating the product
Method: PUT | URL: http://localhost:3000/api/v1/products/1
{
"product": {
"name": "iPhone 13"
}
}
Listing all products
Method: GET | URL: http://localhost:3000/api/v1/products
Retrieving product
Method: GET | URL: http://localhost:3000/api/v1/products/1
Destroying product
Method: DELETE | URL: http://localhost:3000/api/v1/products/1
Creating price (for an existing product)
Method: POST | URL: http://localhost:3000/api/v1/products/1/prices
Headers: { “Content-Type”: “application/json” }
{
"price": {
"title": "Black - 128GB",
"details": "New Green Finish",
"amount_cents": 69900
}
}
Updating Price
Method: PUT | URL: http://localhost:3000/api/v1/prices/1
Headers: { “Content-Type”: “application/json” }
{
"price": {
"amount_cents": 59900
}
}
Retrieving price
Method: GET | URL: http://localhost:3000/api/v1/prices/1
Destroying price
Method: DELETE | URL: http://localhost:3000/api/v1/prices/1
Stripe makes the integration with their API pretty simple and easy with the SDK.
There are a lot of resources on Stripe API that were not explored during this article. I mean to publish other ones in the future, related to charges payment intent, and webhooks.
You can check the complete Stripe Docs here.
Want to Connect?If you have any questions or suggestions, text me on Twitter.