Build an API SaaS using Next.js, Prisma, Stripe in under an hour (Get paid for your API)
Summary
TLDRThe video walks through building a paid API service using Next.js, Tailwind CSS, PlanetScale, Prisma, Stripe, and Vercel. It covers user authentication via NextAuth, restricting access to routes, creating customer profiles and subscriptions in Stripe, building the API endpoint, incrementing usage based on requests, logging requests to display in a dashboard, showing usage graphs and metrics, and deploying the full-stack web application.
Takeaways
- 😀 Building a full-stack API SaaS using Next.js, Prisma, PlanetScale, Stripe, and Vercel
- 📝 Using Next.js latest version and app router for easier routing
- 💡 Leveraging server side rendering for session checks and redirects
- 🔐 Adding authentication with NextAuth and Discord OAuth
- 🗄 Setting up PlanetScale MySQL database and Prisma for simplified interactions
- 💰 Integrating Stripe elements for subscriptions, billing and tracking usage
- 🌐 Creating API endpoints to return data and handle authentication
- 📊 Building admin dashboard to display usage graphs, logs and more
- ✏️ Generating unique API keys for users to access protected endpoints
- 💡 Challenges: add customer portal and improve graphs of usage logs
Q & A
What is the main goal of the video?
-The main goal is to build an API software-as-a-service that charges users to access data APIs.
What technologies are used to build the API SaaS application?
-The technologies used include Prisma, Tailwind, Stripe, Next.js, Vercel, and PlanetScale.
How is user authentication handled?
-NextAuth is used along with Discord OAuth for user authentication.
How are users billed for API usage?
-Stripe is integrated to bill users $1 for each API request. A metered billing model based on API usage is implemented.
How is the API usage tracked?
-A database log table tracks each API request with details like method, status code, timestamp etc. The top recent logs are displayed in the dashboard.
How can users check if they have an active subscription?
-The dashboard displays a message indicating if the user has an active subscription or needs to check out.
What databases are used?
-PlanetScale MySQL is used along with Prisma as the ORM for simplified interactions.
How are new users handled?
-When a new user logs in, a new Stripe customer is created if one does not exist. This associates the user with a billing account.
What additional challenges are proposed?
-Some proposed challenges are to add Stripe portal for self-service subscription management and visual graphs for API usage logs.
Where can I get the full source code?
-The full source code is available on the presenter's GitHub.
Outlines
🎧 Introducing the project idea and tech stack
The video will guide viewers through building an API software-as-a-service that charges users per API request. It will use Prisma, Tailwind, Stripe, Next.js, Vercel, and PlanetScale. The presenter explains the dashboard, billing, logs, and other pages that will be built.
💻 Setting up the Next.js app and database
The presenter initializes a Next.js app with TypeScript. They then create a PlanetScale database using Prisma for the ORM. Next Auth is configured for Discord authentication. Prisma is connected to PlanetScale and synced.
🔒 Adding authentication for dashboard page
The presenter adds authentication to lock down the /dashboard route. Users are redirected to sign in if not logged in. Session data is checked server-side before rendering dashboard.
🛒 Integrating Stripe for payments
Stripe is installed and setup using a test API key. Helper functions are created to retrieve the Stripe customer for a user or create one if it doesn't exist yet. A /checkout route is added.
💰 Creating checkout and subscription workflow
Functions are added to check if a user has an active subscription, and to generate a checkout link if not. The dashboard will now show a call to action to subscribe if needed.
🪙 Generating API keys and Stripe products
An API key is generated for each user and saved in the database. A Stripe product is created for metered billing per API request. The API key is displayed in the dashboard.
⚙️ Building the API endpoint
An API endpoint is created at /api/endpoint to return a UUID. It checks the validity of API key and subscription status before responding. Usage records are incremented.
📈 Logging and displaying API requests
API requests are logged to the database. The dashboard displays graphs and top requests. Current usage metrics are pulled from upcoming invoice to show billing.
🎉 Completing the web API SaaS
In closing, the presenter summarizes what was built - an API SaaS with billing, logging, authentication, and metrics. Additional challenges are proposed for enhancements.
Mindmap
Keywords
💡API
💡SAS
💡Next.js
💡PlanetScale
💡Stripe
💡Prisma
💡Authentication
💡Billing
💡Dashboard
💡Deployment
Highlights
We'll be using Prisma as our orm to easily interact with our database
We'll be using stripe as our payment processor
We'll be deploying this on Vercel and we're using PlanetScale as our MySQL provider
We'll build a dashboard, logs page, billing page, home page with API endpoint
We'll create our first API endpoint to start billing users
If no subscription, return code 403 forbidden
Create usage record to increment usage by 1 for billing
Return special key from API endpoint, can be anything - stock data etc
Log all requests to database for analytics
Show top 10 recent logs on dashboard
Show current month usage for upcoming invoice
Stripe stores currency without decimals, divide by 100 for count
See usage and logs update in real-time on dashboard
Challenges: Customer portal, graph events, move API key to headers
Get full code on GitHub, AI SaaS starter kit linked below
Transcripts
[Music]
guys today we'll be creating an API SAS
so you can get paid for your data so you
will be able to charge people for uh API
access to your API uh this comes
complete with billing and even log
records so we will be setting all this
up in under an hour
um it's gonna be a really good time I
hope you guys enjoy it and I'll see you
when we start what's up everyone today
we'll be building an API software as a
service so you can get paid uh for
having a bunch of data and selling it to
people
um so how this will work is when someone
makes an API request to your API it'll
charge them whatever amount you want so
for testing we'll just put it as a
dollar
so the tech stack for this is going to
be Prisma as our orm to easily interact
with our database
Tailwind for styling we'll be using
stripe as our payment processor
we'll be using the latest version of
nexjs so you can have access to the app
router and with that we'll be using next
auth
for our self-hosted authentication and
we'll be deploying this on versel and
we're using Planet scale as our uh MySQL
provider
so you'll basically be building this
with me and I'll show you what to do as
we go along some of the things we'll be
building is on a dashboard a dashboard
page which will show the usage with a
chart
a logs page which will show all of the
um requests the user has made
to the to your API a billing and
settings page which will show their API
key and a checkout button so they can
paid to get access to it and we'll also
build a home page with the API endpoint
so by the end of this you should be have
a fully production ready application and
start making money from your data
so the first thing you want to do is
open up
Visual Studio
and we'll create our next app so we'll
go into our console
Air Terminal and create do create next
app
my bad MPX
create next app at latest
we'll give this any name you want so
I'll name this cool API we'll use
typescript with eslint K1 CSS will use
the source directory app router import
Alias will be at symbol forward slash
and a star so
it'll be easier to import everything
while that's getting ready go to
planetscale.com
create an account this will this is a
free platform you can use to self-host a
database
or not self-host but to get in my SQL
database uh really easy to set up great
developer experience so once you have
your plan skill account you're going to
click new database
create new database
we'll do the free hobby tier and for the
database name we'll just name this test
and click create database
I'm going to create a new
uh notepad so I can write down
everything
so it's still initializing and our next
project just got done so we're going to
enter this
open
cool API
all right so this is our next uh JS
project with the app router we will be
using server actions so in your next
config
uh type in
experimental and then server actions is
true because we want to have access to
server actions
and just to get things set up we're
going to create a few folders in here
the first one is going to be components
this will house all of our components
some people have the components
in the app folder next to the page
routes but I actually I enjoy my life so
I'm not going to do that because I don't
hate myself it creates a lot of clutter
and if you do that you should rethink
that
um we're also going to create a folder
called actions this will have all our
server actions
inside of it and then the last one will
be a lib so this will be shared
utilities
between the client server
so by now our database is ready so we're
going to click connect
we're going to create a password
we will be using Prisma so it should be
the default so just copy this
and create a new file called dot in
and now we're going to set up our
database
so what we're going to do is have our
database we're going to do npm install
Prisma Dash Dash
save Dash Dev so this will install the
Prisma RM which will basically uh we'll
be able to create our schema schema from
the project and then push it to the
database with easy migrations and stuff
like that so now that Prisma is
installed we're going to do npx
Prisma init which will emit the schema
so as you see we have our schema file
first thing we need to do in here change
the provider to mySQL
and leave this and then relation mode
needs to be set to
oops
needs to be set to Prisma because no
foreign keys with playing scale there
are no foreign keys so prism will take
care of that
okay
so now that we have our database set up
let's install next auth
so go to our terminal terminal type npm
install next Dash auth
while this is installing
um we're going to use Discord as our
oauth provider so log in with Discord so
type in Discord developer
go to your applications create a new
application I've already created one
called test API
go to oauth
copy the client ID
and put it in your dot in so you'll have
access to it so this will be Discord
apply underscore ID like this boom and
then we're also creating one Discord
client Secret
uh so I'll just reset mine
copy
last thing you need to need to do here
is create a callback or a redirect URI
so this so for testing it would be HTTP
localhost 3000 forward slash API forward
slash auth forward slash callback
forward slash Discord
so that will be the redirect you must
have in here
next thing you need to do
I forgot to copy the database uh URL
okay
so now in your dot in you should have
your database URL your Discord client ID
and Discord client Secret
so now we need to set up next auth with
Prisma so to do that we're going to go
to the docs for next auth
we will click getting started
Okay so
what we're going to do is we're going to
create a new uh
in our source folder we're going to
create a new uh folder called pages
and in Pages we're going to create a
folder called API forward slash auth
bracket dot dot next auth
dot TS
that is not a file
I messed this up let me restart
so in in API auth you're going to create
a file called dot next auth dot TS
yep dot dot dot triple dot next off.ts
uh in here we're just going to copy and
paste
from the docs
and then in here we're going to
npm
install next auth
I forgot if we installed this but we'll
just install it one more time okay
so that we're going to change this to
Discord provider
and the import will be providers Discord
client ID
copy this
copy this
like this
so this might be null so just put this
in a string
so we'll stop here to that type error
okay next thing we need to do is set up
to work with Prisma
so Prisma is an adapter so we're coming
to here
we'll run these commands so first thing
we need to do
is run npm install then install command
we need to create a new Prisma client
like this so we'll say import Prisma
client and then cons Prisma equals new
Prisma client and then set up the
adapter like this whoops
say Oops why is this not
and of course we need to
bring it in like this and then this
seems to be as
uh
options to get rid of that type of error
so next thing we need to do is add the
schema it needs
oops
so copy and paste the schema
into here
now you're going to go into the terminal
and do
MPX Prisma DB push
so this will push the schema to your
newly created my squirrel
platform
next thing you want to do is run npm run
Dev
so now we should be set up with Prisma
and next auth
all right
so now if everything's set up correctly
we should be able to go to
um API auth sign in
so there we go we have our Discord sign
in button we'll click sign in
will this work on the first try
and it did so if you set everything
correctly should we bring you back to
this home page
and now if we inspect in our cookies we
should see the next auth session token
so that means we are logged in and to
verify this let's go back to Planet
scale
go to console
first of all
we need to downgrade this branch
um
downgrade this Branch to not production
so we can access
uh so click allow web console access to
production branches because we want to
be able to see the data
not recommended though so select all
from user and here is the user so this
is me so I just signed in so any users I
create accounts with Discord on your app
will appear here
so cool next thing we want to do is in
our app
page.txs let's get rid of the
boilerplate that versel provided us
boom so now
should just be a blank white screen
oh we also want to clear out the CSS
they put
so now it should just be a blank white
screen
okay cool
first thing uh I want to do is in the
layout let's change the font from enter
to Poppins
a far superior font
I want it to look nice so we will not be
using enter
so for some reason with this font you
have to manually
like specify
the uh the widths
okay
so now we have just a nice white canvas
to create our app on so first thing we
want to do let's create a a header a
navbar so in our components create a
file called header.tsx
export function header
boom uh let's wrap this in a nav
and in here we'll do Flex item Center
let's do a gap of eight
so here will be our logo and we'll do
justify between
so in here this can be our our local
logo and we'll just do a simple text
logo and with the href we'll just point
back to the main page
um so this can just be logo
and let's make this a size of 2XL font
semi-bold
text black and when you hover it lower
the opacity
so now if we go back we should see
we also but first thing we need to do is
in our head uh
page.txx import the header component
so now we should see our logo there
then
we'll create another group
of item Center this time with a gap of
four just to shrink it
the link so this so if we go to our
little design document
oops I got rid of it uh so we're gonna
have two sections on the
home page we're going to have one for
the features so this will be slash
hashtag features
that's the href and then we'll have one
for pricing
which will be
#pricing
uh we'll make the font medium text small
text black new hover we'll just lower
the opacity
and we will copy and paste this
so there we go
and we'll also create one more button
to go to the dashboard
this would be forward slash dashboard
dashboard
uh let's set the text to White BG black
let's add some padding
round it out a little bit
so now it should be look like a button
there we go
now let's add some padding on the y-axis
let's see py2
like this
and then let's let's set a Max width on
the snap
let's do 5xl
like this M Auto PX of four so we want
to have padding on the sides instead of
Max width
so there we go I think it could use a
little more padding on the Y so let's do
four
there we go okay
so that's already looking pretty good
um
next thing I want to do is let's get
start working on the dashboard
so in the app we're going to create a
folder called dashboard
and I like to mock everything out before
I implement it just so we have something
to look at
make sure on the right track in the
dashboard we're going to create a
layout.tsx
export function
this has to be default function
and if I'm going too fast all this code
will be on GitHub so you can
follow along if I'm moving too fast
two and then in here we need to put the
children
so in the dashboard
we'll call this page
we'll wrap this in the main tag we'll
say
dashboard okay
so now let's go to forward slash
dashboard and there is our dashboard uh
text so first thing I want to do is
throw in the header here
um
and the code we used to set the max
width
um let's let's bring that on for the
children so the children are
locked in to the max with the 5xl with
the padding and stuff
like this all right so that's already
looking pretty good
trying to think okay
so now I have the dashboard page and we
don't want them to see this dashboard
page if they're not logged in so in the
layout
what we're going to do is we're going to
just export
default async functions will be a server
side function and we'll say
you have to make sure the auth options
are exported from this but where I did
that so we're going to say const session
equals await get server session
with the off options
um from the page so in the pages route
we have the auth options so we're going
to import that from there
we're going to say if session
console.log
user is logged in else if session oops
I'm just saying we're just going to say
else console.logged user is not logged
in
so now if we go to the terminal
we will see
that the user is logged in but if I go
to my cookies
well if we go to the API
auth sign
out
let's sign out which will clear the
cookies and go to dashboard user is not
logged in so what we want what do we
want to do if the user is not logged in
let's redirect to API auth sign in
and we'll say await
oops wrong import redirect
you have to import from navigation next
slash navigation
so boom as you see
if we go to dashboard when we're not
logged in it will redirect us to the
sign-in page so now let's sign in with
Discord
authorize
now we can go to the dashboard page and
we see the dashboard page so this will
work on all sub routes of dashboard so
if we do dashboard slash billing we
don't have to implement that logic again
since it's on the root layout and
execute it on the server so they won't
even see that page we'll intercept them
before
next thing I want to do is let's set up
stripe
which is the billing software so we're
going to do is we're going to say stripe
uh
uh what is this stripe Js
so let's do include
my bad stripe node.js
here's what we're going to do we're
going to run npm install stripe
um we also want
this should come
if I'm not mistaken
let me
this should come with type safety
I believe that does come with type
safety
let me make sure oh is it
yep okay sorry about that had to make
sure it came with type safety
um so it does by default next thing you
want to do is go to strike.com
we're going to
uh go into test mode
actually I'm gonna go to a different
account let's get my testing account
so this account is in test mode so we're
going to do is we're going to go to
we're going to search for API key
reveal secret key copy the secret key
into our DOT in environment we're going
to say
right Secret
like this
so now if we go to our layout
when we create a new stripe
we're going to pass in
uh we're going to stringify this and
we're going to do process.m dot strike
Secret
now to keep us from having to type this
every time in our lib we're going to
create a file called just called
stripe.ts
and we're just going to copy this code
into here
we're going to export this stripe object
so now look at that so now
we should be able to import
stripe
from our
um
lid folder and now we have access to all
the stripe apis using our authenticated
key
also for this we can clean this up and
we'll say We'll create a new file called
auth
.ts we'll say export default async will
not default X4 async function
called
say check if user is logged
we'll call this function must be
logged in
and basically we're just going to copy
this code to here
like this
get server session
and we can say if so if there's not a
session redirect else do nothing
and we need to import auth options
so now in our layout we can just say
await
must be logged in so now
we don't have to type that code every
time we want to lock down a route
which is pretty good
next thing we want to do
is we want to create a stripe customer
for our user if they if there's already
not a stripe customer so in our schema
we're going to do is we're going to say
stripe customer ID as a string
which maybe null
and the default
now we don't need default so stripe
underscore customer ID
and we're going to push this schema so
close down the other running instance
and do npx Prisma DB
push so this will push the schema and
automatically migrate
our databases so everything's in sync
and now we can do npm run Dev to get the
dev server running again
and in here
well we'll say well actually in our
stripe we'll say
export
async function
create
customer
uh
if
null
so first thing we're going to do is
we're gonna get the session so get
server session pass in the auth options
um if just a redundant check
if there's a session
and you have to await this this is a
promise so if there's a session if
session
first of all so the session that returns
just returns the email username and and
the image so we need to fetch the user
from the database based off the email so
first thing we're going to do is we're
going to say const user equals
before we can do that though
we must initialize Prisma
which are orm don't forget to do that I
almost forgot to do that so constant
Prisma equals await Prisma dot user dot
find first where we're going to say
email is session.user.email
okay
so if user
dot stripe customer ID so if not
user.stripe customer goody we're going
to create a customer
so we're going to say const customer
equals stripe dot customers dot create
email is going to be user.email
and we're going to put this in a string
to make sure that the string exists so
then we're going to do await Prisma dot
user dot update
where the ID is our user.id
the data we want to overwrite is stripe
customer ID and this is going to be
customer dot ID
you want to await this
so this is going to be
customer.id
like this
so now we're also going to do create
customer if null we're going to call
that function from our dashboard layout
so now
let's just
refresh
check the terminal make sure there's no
errors
no errors internal
so then if we go back to our database
we should see yep there's our customer
so we have successfully created a
customer but now if we refresh
the number so this is oncc starting with
oncc
let's refresh this a couple times it
shouldn't overwrite this customer so now
if we refresh
yep same customer and we can triple
check this in stripe by going to the
customers
let that load
that's taking a second to load
and it's taking a really long time to
load
but it's there if you check your stripe
it'll be there
so next thing we need to do
is create a product
in stripe which we will use to measure
the API usage
so first thing we need to do is add to
our schema
stripe
subscription
item this is going to be a string with a
question mark
while we're here we're also going to be
logging all the API bins so let's call
this log
uh copy the ID from user we just want a
random ID
so we'll say We'll bind this to a user
by their ID
and we'll say the method can be a string
so this will be get or post all of them
what we get for our use case
and the status will be an INT
and also thrown at created which will be
a date time
and the default for date time can just
be now
so now if we go here and do MPX Prisma
DB push this will sync our schemas
so everything will be in sync
okay for some reason stripe has decided
to come back
let's close down some of these tabs
so in products
there's anything unload
nothing's loading right now what
do nothing's loading
let's try it for some reason
uh let me
just reach there we go okay
so resetting my cash work okay so here's
the um the customer created earlier it's
now in products
we're gonna do add product
we'll call this API access the
description we gain access to our API
so what we're going to do is we're going
to say the usage is metered it's gonna
be the sum of usage valids uh During the
period and we'll say one dollar
per API
request
was recent okay so we're going to save
the product
and this is important we need the price
ID right here
okay so let's go back here
and in our stripe.ts I'm just going to
put paste the price ID right here
boom
so now what we need to do is
we need to create a checkout link
um so they can check out and actually
get paid for the subscription because we
can't increment their usage if there's
no subscription to increment
so first thing what we're going to do
we're going to create a function called
export async function create
check out link
we're also going to create another
function
called has
subscription
so we're uh in this has subscription
we're going to copy this from our create
customer if null just to get the session
and we're going to return a weight
stripe
dot subscriptions Dot
what does this retrieve
is this
actually I think what we can do is we
can actually do con subscriptions
equals away
stripe.customers.retrieve the
user.strike customer ID
let's say subscriptions
object what
hmm
what we can do actually is we'll say
stripe git
subscriptions by customer
node.js
actually what we can do is we can use
chat gbt
to speed this up because I'm actually
why they don't have a stripe dot
customers
for subscription item like
list
oh
they do my bad
stripe customer ID okay so this
stripe.scriptions.list and the customer
is a customer ID
so we'll say this
okay let's
this needs to be in a string like this
we'll leave chat DBT open we might be
coming back to that
uh we'll say return
subscriptions.data dot length is bigger
than
zero so if they have a subscription
turn else turn false oops
whoops okay
so now we'll say has sub equals await
has subscription
console.log has sub
if they have a subscription we'll say
has
not
go into our terminal
refresh the page we can see
has not okay so we don't have a
subscription
so back in our stripe.ts we're going to
say in our checkout link we're going to
say const checkout equals await stripe
dot checkout dot sessions dot create
and we're going to say line items
so the first so we're only have one line
item and the price ID
is this price
we also need to define a success URL
which will just be localhost 3000 we'll
say dashboard slash billing success it's
true
B like this
I'll say cancel
cancel URL like this
be sure to put this in a string
finally we're going to say return
check out Dot
URL
and I think in here
so create checkout link will take in
a customer ID
like this
so now in here we'll say
and then create customer if null
what we can do
is down here
we'll say user two
I'm going to refetch the user
let's say return user2 Dot
Drive customer
ID
uh so in here we'll say stripe we'll say
const customer equals this
will say console.log customer
so now in the console we should have our
yep there it is already
uh customer ID so now we'll say const
checkout
link equals await
create
checkout link for our customer
we'll put this in a string make sure it
it's a valid string
and let's just
whoops
and I forgot this
mode is going to be
subscription so the mode has to be
subscription is recurring
so now
we should see a link in the terminal
yep so now if we copy and paste this
link that's in the terminal
it is um it autofills the email with the
customer and as you see it says we will
be build one dollar per API call or
usage
so great
so now what we can do
now that we have all this we can get rid
of these console logs
and we can say down here
we can actually move
um
these two things into the page
so we'll change this to async
like this and we say has subscription
create
checkout link
we also we need this customer
create customer if null like this and
we'll say if they have a subscription
we'll do this with our ternary operator
so if they have a secret if not what
we'll do is we'll say
we'll say Min height of 60 view heights
grid
Place item Center we'll round it
and give it a padding X of 6 padding y
of 10 BG slate 100 just to darken it a
little bit
and this will be
this will say
you have no subscription
check out now
in the href will be the checkout link
and then for styling we say font medium
text SM and then on Hover we'll
underline
we'll throw this in a string just to
make sure it is a string
so now boom
and actually we can take we can put this
at text base so it's a little bigger
so now
if they go to their dashboard and they
don't have subscription it will say hey
check out
so now if we click this
uh and we put in our test data so for
stripe it is just four two four oops my
bad four two four two four two all the
way down
like this
say 39651
let me subscribe now we should get a 404
error because the page we're redirecting
to doesn't exist actually
but if we go back to our dashboard
that message doesn't go away because we
have a subscription
so now
at the top here
we'll say
uh throughpx
four py2 BG Emerald say 100 text white
actually
let's do BG Emerald 400 text White
font medium
we'll say
you have a subscription
boom just like that
so now what we've done is we've created
a way to check out if you don't have a
subscription
and if you do have subscription it tells
you and gives you a nice message
so now what you can do
to take that font size
okay so now that we have the basics of
billing in place
lettuce
um
create the API endpoint
so how are we going to do this so in our
schema what we can do is an under user
we'll create a thing called API key and
this is going to be a string
it's like this and we'll say npx
Prisma DB push we'll sync the schemas
again
and now if we rerun the project every
time you change the schema you have to
rerun the project to regenerate Prisma
so now
if we head down
to our um the stripe where we say create
customer if null if we have to create a
customer what we can do is we can just
create their API key right here which
will just be random uid
uh we can make a custom we'll say API
key
like this
actually this will be a separate thing
so if not user.api key
copy this
say API key
we'll say
secret change it up random uid
so now
if we go back to our test console after
you go back to this page
you see the API Keys generated
so let's display this to the user so
they know how to interact with the API
so first thing here is we'll just make
this a column
and this
and we're just let's design a nice card
so the card will have a couple sections
the first one will just be the label
called API key
as let's have a divide between them
divide y divide zinc 200 border let's
give it a border of zinc 200. rounded in
b
let's give this some padding of py6 py4
and then
let's also fetch the user so here we'll
say const user equals await prisms
oh wait Prisma
what am I thinking we have to
import Prisma again
at the top here
prisma.user.findfirst
where email
when I get the session so this will be
await get server session
of the auth options
so we're going to get the the user from
the database of the current sessions
just like that
so now we'll say user dot API key
and we'll say uh we'll make the font
small the font mono space
we'll make it text zinc 800 we'll add py
of six p y or PX of six py of eight
and now look at that so now uh p y of a
is a little excessive so boom so now
we have created a way for the user to
see their API key
and know if they need to have a
subscription or not
so this is pretty cool so now what we
can do is recreate our first API
endpoint
um
uh first API endpoint so we can start uh
billing them
so under app we're gonna actually we'll
do this in the Pages directory the page
is directly for me is easier to work
with so do API let's call this inpoint
rename employee.ts
export default
async function called Handler
this takes in a request of next API
request response next API response
we're going to say res Dot
status 200.json
works
true
so now if we go here
API in point
we get that response back
so first thing we want to do
and this API endpoint will just return a
random uuid and then and we'll charge
them a dollar for that and then you can
replace this with your own logic so
first thing we need to do is
in this request we want to bring the key
along so we'll say API key equals
our API key like this so we'll say
const
Avi key equals request.query
if not API key so if there's not an API
key let's say res dot status
I forgot what the proper I think it's
401 I believe is the right status code
Dot
Json we'll say error is
must have a valid API key
so we shouldn't get that here but if we
remove it
we'll say must have a valid API key
so now we'll say
const user equals await and then we'll
need to import Prisma again
so we'll bring in Prisma here
just like this
await Prisma dot user.findfirst where
the API key is the one from the query
parameter
um
a smart thing as a challenge is you
might want to put this in the header so
you might want to put this as a bearer
token
um so that but you guys can guys figure
out how to do that so if there's not a
user with this API key with this API key
we can say
there is no user with such
apiki
so we shouldn't get that here but if we
jamble it we'll say there's no user of
the API key
but we get that boom
status true okay
so now we have a request
uh we have an authenticated request with
the user object so we have the user
that's making the request next thing we
need to do
is get the subscription item and then
increment the usage
so basically what we're going to do
we're going to say cons
sub item
well first of all let's get the customer
so we'll say await stripe import the
Stripe from a library customers.retrieve
user dot stripe customer ID
like this
then we're going to say const
subscription equals await dot Subs um
how do we do that
I'll just copy and paste this no need to
rewrite it
I'm going to say cons item equals
subscriptions
.data dot get let's get the
first one
oh it's ah my bad
items
dot data dot get oops dot at my bad
the first one so now we can do item id
all right
so now if not item
let's return a code that says 403
you don't have a subscription
you have no subscription so now we
shouldn't get that if we do this
so basically
on all stripe subscriptions there's an
item with the price uh the price object
attached to it so we're basically saying
if there's no items in the subscription
then there they have no subscription so
that's how you check if they have paid
for it or not so next what we want to do
is want to do a weight stripe
the subscription items
dot create usage record
so the ID will be item.id
we'll say the quantity will be one so
they have
incremented their usage
by one
and we'll say
and we let's just return this in the
result
just so we can see it so now if we do
this
boom
we can see we have created a usage
record
so now let's return the actual data
constant data equals
random uuid like this
so some kind of special key so boom
every time I hit this API endpoint with
my valid API key we're getting our
special key back and this special key
can be anything you want this can be
stock price data
um just data from your database can be
anything
so now if we go back to our customers in
stripe
we can see
that they have a subscription and can I
we can see in their most recent invoice
whoops
ah we can see the usage record so this
is all the API calls
um
that they have made so now what we want
to do is we have our log that we wanted
to maintain
so what we can do here is we can do
await
prisma.log dot create
the user
data so
prisma.log.create with our data
the user ID is going to be user.id
the status code is 200.
the method
is going to be git
this has um
get rid of this type error by wrapping
this in a string
just like that and we'll say we'll
actually let's get past the log along
this log log so now
if you go to your API key you see you
get the data back you requested and the
response that we've logged
cool so now what we can do is we can
show in the dashboard
um
all the requests we've made but so like
the top 10 or something so in here what
we can do is we can say
const top 10
top 10 recent logs equals oh wait Prisma
DOT log dot
find mini
where the user ID is user.id
let's do order by
created descending
and then we're also going to
take so 10 take 10.
so we're going to get all the logs by
the user we're going to order them by
the created date that's automatically
assigned and we're going to take the
first 10.
so now we can do
is let's just copy and paste this little
card we had for API key we'll say log
events
we can do top 10 log events
this is Thompson log events Dot
map
item
index
like this now you have to put a key for
each one we'll do item dot method just
to make sure it works
we'll put this in a P tag
boom just like that
now it's going to yell at us if we do
that so move this stuff around
say item dot method
so let's go ahead and create a few more
logs so just go hit this endpoint a
couple times and we come back
we should see all our requests
so in here let's make this a flex
item Center and give it a gap of four
we'll give it the status
and then
the date
or dot created dot to date string like
this
so now we have our API key with the log
events so
next thing we need to do is show the
current usage for this month so they can
see how much they're about to get billed
so what can do up here
let's copy and paste this
let's do
current usage
uh we'll put this as a variable called
current
usage now let's go back up here
we'll say let current usage equals zero
and then what we'll say is oh um
const invoice oh wait stripe
in
retrieve upcoming
like this
so first thing we need to do is we need
to get the subscription for this user
like this
description equals the dot at to get the
data that the oops data Dot
at zero
dot ID
and then we're only going to do this if
they have a subscription
so let's do this
and then current usage equals invoice
dot Syria
amount uh a Mountain Dew I believe
boom now stripe Stores
um numbers without decimals so you're
going to want to divide it by a hundred
to get the usage because each usage is
one dollar so we just divide it by 100
we'll get the usage count so boom
so this is um our API so every time we
hit this endpoint
we'll get data back
and we'll see it reflected in real time
in our dashboard we'll see
the current usage go up
with the log event logged
so that is how you create a simple API
SAS using next.js in the app router with
stripe
so some challenges I want you guys to do
is I want you guys to create a way to
manage the invoices with stripe customer
portal
and then I want you guys to create a
graph of the log events so now you have
all the logs here it's very trivial to
create just a simple graph join the
Discord below if you need any help this
code will be on git cup GitHub pretty
soon
um and also I have a AI SAS kit if you
want to build your own AI SAS
I have a kit linked down below right now
it's on sale for 74 dollars you can get
a full stack production ready AI SAS kit
complete with billing and open AI
integration so I hope you guys learned
something and I'll see you guys another
day
関連動画をさらに表示
My SIMPLE Tech Stack To Land Interviews This Year
My Complete Tech Stack For Full-Stack development - 2024
Asp.Net Core Web API Client/Server Application | Visual Studio 2019
Integrate Salesforce with Postman using connected app with OAuth 2.0 to perform API calls.
JWT Authentication with Node.js, React, MySQL | Node JS Authentication With JSON Web Token
[Legacy] Use Firebase for Auth in Wized
5.0 / 5 (0 votes)