DEV Community

Alex Spinov
Alex Spinov

Posted on

Clerk Has a Free API You're Not Using

Clerk is a complete authentication platform with pre-built UI components. Most developers use SignIn/SignUp — but Clerk has powerful APIs for organization management, webhooks, and more.

The Free APIs You're Missing

1. Organizations — Multi-Tenant Auth

import { OrganizationSwitcher, useOrganization } from "@clerk/nextjs";

function Dashboard() {
  const { organization, membership } = useOrganization();

  return (
    <div>
      <OrganizationSwitcher />
      <h1>{organization?.name} Dashboard</h1>
      <p>Your role: {membership?.role}</p>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

2. User Metadata — Custom Fields

import { clerkClient } from "@clerk/nextjs/server";

// Set custom metadata
await clerkClient.users.updateUser(userId, {
  publicMetadata: { plan: "pro", onboarded: true },
  privateMetadata: { stripeCustomerId: "cus_xxx" },
});

// Read in component
function Profile() {
  const { user } = useUser();
  const plan = user?.publicMetadata?.plan;
  return <Badge>{plan}</Badge>;
}
Enter fullscreen mode Exit fullscreen mode

3. Webhooks — Sync Auth Events

// app/api/webhooks/clerk/route.ts
import { Webhook } from "svix";

export async function POST(req: Request) {
  const payload = await req.json();
  const headers = Object.fromEntries(req.headers);

  const wh = new Webhook(process.env.CLERK_WEBHOOK_SECRET!);
  const evt = wh.verify(JSON.stringify(payload), headers);

  switch (evt.type) {
    case "user.created":
      await db.users.create({ data: { clerkId: evt.data.id, email: evt.data.email_addresses[0].email_address } });
      break;
    case "user.deleted":
      await db.users.delete({ where: { clerkId: evt.data.id } });
      break;
  }

  return new Response("OK");
}
Enter fullscreen mode Exit fullscreen mode

4. Middleware — Route Protection

// middleware.ts
import { clerkMiddleware, createRouteMatcher } from "@clerk/nextjs/server";

const isProtected = createRouteMatcher(["/dashboard(.*)", "/api/(.*)" ]);
const isAdmin = createRouteMatcher(["/admin(.*)"]);

export default clerkMiddleware((auth, req) => {
  if (isProtected(req)) auth().protect();
  if (isAdmin(req)) auth().protect({ role: "org:admin" });
});
Enter fullscreen mode Exit fullscreen mode

5. Session Claims — Custom JWT

// In Clerk Dashboard: Sessions > Customize session token
// Add: { "metadata": "{{user.public_metadata}}", "org_role": "{{org.role}}" }

// Then in your API:
export async function GET() {
  const { sessionClaims } = auth();
  const plan = sessionClaims?.metadata?.plan;
  const role = sessionClaims?.org_role;
  // No extra API call needed — it is in the JWT
}
Enter fullscreen mode Exit fullscreen mode

Getting Started

npm install @clerk/nextjs
Enter fullscreen mode Exit fullscreen mode

Need data from any website delivered as clean JSON? I build production web scrapers that handle anti-bot, proxies, and rate limits. 77 scrapers running in production. Email me: Spinov001@gmail.com

Check out my awesome-web-scraping list for the best scraping tools and resources.

Top comments (0)