Tutorials > Protected API Calls
Go into the /app/api folder – any file named route.js is your API endpoint! ✨ For an extra dash of simplicity, reach for the /libs/api.ts helper (it's like an axios wizard with interceptors).
1. Auto error messaging for the general cases such as Please Login , Paid Plan Required to use this feature etc.
2. Redirect to login page upon error 401
3. Add /api as a base URL: converts /api/leads → /leads
🍪 Supabase has your back with authentication using cookies – it's automatic! 🚀 Just fire off a regular API call on the front-end, like a breeze:
1
2    "use client"
3
4    import { useState } from "react";
5    import apiClient from "@/libs/api";
6    
7    const UserDetails = () => {
8        const [isLoading, setIsLoading] = useState(false);
9        const supabase = createServerComponentClient({ cookies });
10
11        const {
12          data: { session },
13        } = await supabase.auth.getSession();
14    
15        const saveUser = async () => {
16        setIsLoading(true);
17    
18        try {
19            const { data } = await apiClient.post("/user", {
20            email: session.user.email,
21            });
22    
23            console.log(data);
24        } catch (e) {
25            console.error(e?.message);
26        } finally {
27            setIsLoading(false);
28        }
29        };
30    
31        return (
32        <button className="btn btn-primary" onClick={() => saveUser()}>
33            {isLoading && (
34            <span className="loading loading-spinner loading-sm"></span>
35            )}
36            Save User
37        </button>
38        );
39    };
40    
41    export default UserProfile;
42    🔙 On the backend, we grab the session magic and use it to fetch the user from the database. But first things first – configure that database! 🛠️ Your API file is the secret sauce and should have a vibe like this:
1
2    import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs";
3    import { NextResponse } from "next/server";
4    import { cookies } from "next/headers";
5
6    export const dynamic = "force-dynamic";
7
8    export async function POST(req) {
9      const supabase = createRouteHandlerClient({ cookies });
10      const { data } = await supabase.auth.getSession();
11      const { session } = data;
12
13      // Check authentication by the object returned by Supabase
14      if (session) {
15          const body = await req.json();
16
17          if (!body.email) {
18              return NextResponse.json({ error: "Email is required" }, { status: 400 });
19          }
20
21          try {
22              // For this call, you need to create a table named "users" in your database
23              const { data } = await supabase
24                  .from("users")
25                  .insert({ email: body.email })
26                  .select();
27
28              return NextResponse.json({ data }, { status: 200 });
29          } catch (e) {
30              console.error(e);
31              return NextResponse.json(
32                  { error: "Something went wrong" },
33                  { status: 500 }
34              );
35          }
36      } else {
37          // Unauthenticated
38          NextResponse.json({ error: "Not signed in" }, { status: 401 });
39      }
40    }
41