Skip to main content
Back to blog
Guides May 8, 2026 read

I built an AI headshot tool in 4 hours with Claude Code. Here's the full playbook.

Step-by-step playbook for building an AI headshot SaaS in a weekend with Claude Code and Runflow. Real prompts, real API shapes, real margins.

Apoorv Sharma
Apoorv Sharma
Performance Marketing Manager

The idea hit on a Friday night. AI headshot tools are charging $35-$79 per session, the underlying API costs $2.80 per user, and Claude Code can write 80% of the wrapper in an afternoon. The math is absurd if you can actually ship.

So I tried it. Four hours from blank repo to a working tool that takes selfies, runs them through Runflow's AI headshot pipeline, and delivers studio-quality headshots over Stripe checkout. This article is the full playbook: the prompts, the architecture decisions, the API call shapes, the Stripe integration, and where I got stuck.

A note on disclosure. Runflow is one of our products. The API costs I quote ($0.30 per headshot + $2.50 model training) are Runflow's, and I built this on Runflow because I know the API. The architectural pattern works with other AI headshot APIs too. I'll flag where you might swap things out. This is a buildable tutorial that happens to use the API I'm closest to.

If you've ever wanted to ship something AI-shaped that real people pay for, this is one of the cleanest starting points in 2026. Read the playbook below. Or skip to the prompts.

What you're building

The tool: a single-page app where users upload 8-12 selfies, pay a flat fee, and receive professional AI-generated headshots within 30 minutes.

The user experience is simple:

  1. User lands on your site, sees example outputs, clicks "Get my headshots"
  2. They upload 8-12 selfies through a drag-and-drop interface
  3. They pay $39 (or whatever you charge) via Stripe
  4. Your app calls Runflow's Analyze endpoint to score the photos for quality
  5. If photos pass, your app calls the Generate endpoint to train a model and produce headshots
  6. Runflow webhooks your app when results are ready
  7. User gets an email with a link to download their headshots

The economics are the interesting part. Each session costs you $2.80 in Runflow API fees ($2.50 one-time training + roughly $0.30 per delivered headshot, with 10-15 headshots per session). You charge $35-$79. That's 80%+ gross margin on every sale.

Worth grounding that number in real data. BetterPic, the largest AI headshot company on Runflow's API, ran this pattern to 35 million images, $2.2M in revenue, and 87% gross margins. The margin didn't come from cheap GPUs. It came from candidate over-generation and quality filtering: BetterPic generates 240 headshots per user, scores them through Sentinel (Runflow's QA layer), and delivers the top 60. GPU cost as a share of revenue dropped from 40% to 11%. That over-generation and filtering is why the Runflow Generate endpoint returns "auto-ranked, best first" without you writing a scoring pipeline. You inherit the work that took BetterPic to 87%. The longer engineering story behind that pipeline lives in Building an AI Image Generator API: 14 things that broke if you want to see what you're skipping.

Why Claude Code makes this possible

A year ago, building this would have taken a week. Frontend, backend, payment flow, webhook handling, file uploads, queue management, error handling, retry logic. None of it hard individually. Together it's a sprint.

Claude Code collapses that. The pattern that works:

  • You describe the app in plain language
  • Claude scaffolds the project structure and writes the initial files
  • You point Claude at the Runflow API docs and tell it which endpoints to integrate
  • Claude writes the API client, the routes, the webhook handler, the Stripe integration
  • You spot-check, run it, iterate

What's left for you is the parts that need judgment: the UX copy, the pricing decision, the marketing landing page, the launch strategy. The boilerplate is the part Claude does best.

ChatGPT Codex works for this too. If you're already on a ChatGPT Plus subscription and prefer that flow, the prompts below translate. The architectural decisions are tool-agnostic.

The stack

I went opinionated on stack choice because indecision kills weekend projects. If you don't already have a framework preference, use this one:

  • Next.js (App Router) for the frontend and API routes. One repo, one deployment, no separate backend service.
  • Vercel for deployment. Free tier handles a meaningful amount of traffic. Pushes from git.
  • Stripe Checkout for payments. Hosted checkout means you don't handle card data, PCI compliance is automatic.
  • Runflow for the AI headshot generation. Two endpoints, $0.30/headshot + $2.50 training, webhook-driven.
  • Resend for transactional email (delivering results to the user). Free tier covers your first 3,000 emails/month.
  • Supabase or Cloudflare R2 for storing user-uploaded photos and generated outputs. Either works.

If you have strong preferences, swap. The shape of the integration is what matters; the framework is mostly aesthetic.

Hour 1: scaffolding the app with Claude Code

Start with a clean directory. Open Claude Code and give it the first prompt.

The opening prompt (the one that scaffolds everything):

I'm building an AI headshot tool. Users upload 8-12 selfies, pay $39 via
Stripe, and receive professional AI-generated headshots within 30 minutes.

Set up a Next.js 15 (App Router) project with TypeScript. Add:
- Tailwind for styling
- A landing page with a hero section, example outputs (placeholder for now),
  and a primary CTA
- A multi-step upload flow (selfies → contact info → Stripe checkout)
- An /api/checkout route that creates a Stripe Checkout session
- An /api/stripe-webhook route that handles successful payments
- An /api/runflow-webhook route that receives generation completion
  callbacks from Runflow
- A results page that shows the user their headshots after generation completes
- Use Supabase for storing user uploads and generated outputs

Don't write the Runflow integration yet. Just scaffold everything else
and stub the Runflow calls with comments showing where they go.

Claude scaffolds the project. About 15 minutes to get a working skeleton: routes, schemas, page components, Stripe integration shape. The output isn't production-ready but it runs.

Skim what Claude wrote. Two things to verify:

  • Stripe Checkout is using the hosted flow, not a custom card form. The hosted flow handles PCI compliance for you.
  • The Supabase tables have an orders table with fields for user email, session ID, payment status, and a foreign key to the uploaded files. If Claude split things differently, ask it to consolidate.

If anything looks off, push back. Tell Claude what's wrong specifically.

The orders table should track the Runflow training_id and generation_id
separately since those return at different times in the flow. Update the
schema and the webhook handlers to match.

Claude fixes it. Move on.

Hour 2: integrating Runflow

The Runflow AI Headshot API has two endpoints. They map directly to the user flow.

Analyze endpoint: scores uploaded photos for quality (face clarity, lighting, resolution, obstructions). Returns a per-image quality score with configurable pass/fail thresholds. Use this before charging the user, to catch bad inputs early.

Generate endpoint: trains an AI model on the user's approved photos and generates headshots across multiple styles. Returns asynchronously via webhook with auto-ranked results.

The full API documentation lives at runflow.io/api/ai-headshots. For Claude Code, you give it the two endpoint shapes and tell it where they fit in your flow.

The Runflow integration prompt:

Integrate the Runflow AI Headshot API. Two endpoints:

1. POST https://api.runflow.io/v1/run/headshot-analyze
   Input: { image_urls: [list of public URLs] }
   Output: { results: [{ url, score, pass: boolean, issues: [...] }] }
   Use this to validate photos before charging the user.

2. POST https://api.runflow.io/v1/run/headshot-generate
   Input: {
     image_urls: [approved photos],
     styles: ["professional", "creative", "casual"],
     webhook_url: "https://yourdomain.com/api/runflow-webhook",
     user_id: "your internal user id"
   }
   Output: { generation_id, training_id }
   This is async; Runflow webhooks you when results are ready.

Webhook payload from Runflow looks like:
{
  generation_id, status: "completed",
  results: [{ url, style, likeness_score }]  // auto-ranked, best first
}

Auth: Bearer token via RUNFLOW_API_KEY environment variable.

Update the flow:
- After upload, call Analyze; if any photo fails, show user a "replace these
  photos" screen
- After payment succeeds, call Generate with the approved photos
- When the Runflow webhook fires, store the results, send a "your headshots
  are ready" email via Resend with a link to /results/[order_id]
- Build the /results/[order_id] page showing the headshots with download buttons

Claude wires this up. Another 30-45 minutes. The shape of the integration:

// app/api/checkout/route.ts (after analyze passes)
async function callAnalyze(imageUrls: string[]) {
  const response = await fetch('https://api.runflow.io/v1/run/headshot-analyze', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.RUNFLOW_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ image_urls: imageUrls }),
  });
  return response.json();
}

// app/api/stripe-webhook/route.ts (on payment.succeeded)
async function callGenerate(order: Order) {
  const response = await fetch('https://api.runflow.io/v1/run/headshot-generate', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.RUNFLOW_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      image_urls: order.approved_photos,
      styles: ['professional', 'creative', 'casual'],
      webhook_url: `${process.env.APP_URL}/api/runflow-webhook`,
      user_id: order.id,
    }),
  });
  const data = await response.json();
  await updateOrder(order.id, {
    generation_id: data.generation_id,
    training_id: data.training_id,
  });
}

Two things to verify when Claude is done:

  1. The webhook handler validates the request is from Runflow. Include a shared secret in the webhook URL or validate a Runflow signature header. This prevents random people from posting fake "generation complete" events to your endpoint.
  2. Error handling is real. If Generate returns a 4xx or 5xx, your app should refund the user automatically (or queue for manual review). Tell Claude this explicitly if it didn't include it.

Hour 3: payments, emails, and the production gotchas

Stripe is the part most weekend builders underestimate. Claude scaffolded the integration. Now make it production-shaped.

Stripe checklist Claude should have handled:

  • Stripe Checkout session creates with the correct price, currency, and success/cancel URLs
  • The webhook signature is validated using STRIPE_WEBHOOK_SECRET
  • On checkout.session.completed, the order moves to paid status and Generate is called
  • On checkout.session.async_payment_failed, the order moves to failed and the user is emailed

The thing Claude often misses: idempotency. Stripe can deliver the same webhook event twice. Your handler needs to check whether you've already processed an event ID before doing work. One line:

const existing = await db.query('SELECT id FROM webhook_events WHERE stripe_event_id = $1', [event.id]);
if (existing.rows.length > 0) return new Response('Already processed', { status: 200 });

If Claude didn't include this, ask for it.

Resend (transactional email) integration:

Add Resend for sending two emails:
1. Order confirmation (after Stripe payment succeeds): "Your headshots are
   training, you'll get them within 30 minutes"
2. Results delivery (after Runflow webhook fires): "Your headshots are ready,
   download here: [link to /results/[order_id]]"

Use the orders table for tracking which emails have been sent to handle
retries cleanly.

Claude writes the email handler. Another 20 minutes.

Production gotchas to mention to Claude explicitly:

  • Image uploads should be size-validated client-side AND server-side. Tell Claude "max 10MB per image, max 12 images, validate on both sides."
  • The Runflow webhook URL needs to be publicly accessible. Local development needs ngrok or similar; production needs a real domain.
  • Stripe live keys vs test keys are different. Use environment variables and never commit live keys.
  • Set up Stripe webhook endpoints in both test and live mode in the Stripe dashboard. Both need the signing secret.

These are the four things that break weekend projects between localhost and production. None of them are hard; they just need to be on your list.

Hour 4: deployment and the first real test

Vercel deployment is one push from working. Connect the repo, set environment variables, deploy.

Environment variables you need:

RUNFLOW_API_KEY=
STRIPE_SECRET_KEY=
STRIPE_WEBHOOK_SECRET=
RESEND_API_KEY=
SUPABASE_URL=
SUPABASE_ANON_KEY=
SUPABASE_SERVICE_ROLE_KEY=
APP_URL=https://yourdomain.com

After deploy:

  1. Update your Stripe webhook endpoint to point at https://yourdomain.com/api/stripe-webhook (live mode dashboard).
  2. Update your Runflow webhook URL in the Generate call to point at production.
  3. Test the full flow end-to-end with your own photos. Use a real Stripe test card (4242 4242 4242 4242). Upload selfies, pay, wait for the email, download results.

If anything breaks, Claude is your debugging partner. Paste the error, paste the relevant code, ask what's wrong. Most weekend bugs are 5 minutes of Claude debugging.

The first time you watch your tool turn $0 of input into $39 of Stripe-confirmed revenue (yes, refund it; this was a test), the whole thing feels real.

What to charge

The Runflow API costs you about $2.80 per session. The market charges $35-$79 per session. Where you land depends on your audience and your positioning.

A useful starting framework:

  • Consumer / LinkedIn upgrade: $29-$49 per session
  • Professional / job seeker: $49-$79 per session
  • Bulk / B2B (10+ headshots for a team): discount per session, charge per seat
  • White-label / partner: custom contracts with revenue share

Most successful indie headshot tools land at $39-$49 for the consumer tier. It's the sweet spot for "I'll just buy it" without thinking, and the margin is comfortable.

Run the math on volume. If you sell 100 sessions in your first month at $39, that's $3,900 revenue and roughly $3,620 gross profit after Runflow costs. Stripe takes 2.9% + 30 cents per transaction, so net is closer to $3,510. Vercel/Supabase/Resend at this volume are free or near-free.

Volume comes from the marketing, not the code. The code is the easy part.

What I'd add in week two

Four things I'd add after the v1 ships, in priority order:

1. Quality auto-rejection at upload time. Don't make the user wait until after Stripe to find out their photos aren't usable. Call Runflow's Analyze endpoint during upload (before checkout) and surface rejected photos immediately. This raises conversion meaningfully because users get a "fix these and try again" loop instead of a refund.

2. Style selection on the order page. Let users pick between professional/creative/casual styles before checkout. Runflow's Generate endpoint accepts a styles array. Don't make it 20 options; offer 3-4 curated combinations that look noticeably different in the example gallery.

3. Refund automation. If the Runflow likeness score on any output is below your threshold, automatically refund the user (or offer a free retry with different photos). The cost of an automatic refund is much lower than the cost of a bad review.

4. Affiliate or referral. AI headshot tools have strong word-of-mouth. A "refer a friend, you both get $10 off" link generated post-purchase converts at meaningful rates with zero ongoing maintenance.

None of these are hard. Each is a 1-2 hour Claude Code session.

Where this falls down

I want to be honest about the things this tutorial doesn't solve.

Marketing is the actual hard part. Building the tool is 4 hours. Getting customers to know it exists is months. The four-hour-tool framing here is true and also misleading; nobody ships an AI headshot tool in a weekend and retires. The tools that work have founders who post on Twitter and LinkedIn daily, run paid acquisition, iterate on their landing pages, and grind. Read this as: you can ship the product in a weekend. Building the business takes longer.

Stripe approval can be slow. New Stripe accounts sometimes need to verify business details before they can accept live payments. Apply early. If you're in a country with stricter Stripe onboarding (some emerging markets, some adult-adjacent verticals), expect 1-2 weeks of paperwork.

AI headshot quality is sensitive to input quality. Users will upload garbage and expect studio-quality output. The Analyze endpoint catches the worst inputs, but borderline cases (mediocre lighting, partial face occlusion) will still generate mediocre results sometimes. Your refund policy needs to handle this.

Competition is real. This category has BetterPic, Aragon, HeadshotPro, and dozens of indie tools competing for the same audience. You need a wedge: a niche, a price point, a style aesthetic, or a distribution channel that's underserved. "AI headshot tool" as a generic product is a crowded shelf.

If you don't have a wedge yet, the data points at real-estate agents. They're one of the biggest validated user bases for AI headshots, the platforms that serve them upsell at $35-79 per session and keep 75%+ margin, and 8 selfies is enough input. Build the tool in their language (broker brand colors, headshot dimensions that match MLS and Zillow profile specs, team-of-agents bulk pricing) and you have a niche that's already paying for the category.

The good news: the API layer is the same model quality for everyone. The moat is positioning, distribution, and product polish. Those are problems you can actually solve.

FAQ

How long does it actually take to build an AI headshot tool with Claude Code?
The core integration (upload, Stripe checkout, Runflow Analyze + Generate, webhook handling, results page) takes a focused 4-6 hours with Claude Code. Deployment to Vercel adds 30 minutes. End-to-end testing adds another hour. Adding production polish (idempotency, error handling, refund automation) is another 2-3 hours. A realistic timeline for a working v1 you'd ship: a focused weekend.

Can I build this without writing any code myself?
Mostly. Claude Code writes the code; your job is to read it, ask the right questions, and verify it makes sense. You need enough technical literacy to deploy a Next.js app, set up environment variables, and debug when something breaks. If you've never deployed anything before, expect to spend an extra weekend learning Vercel and Supabase basics.

What does the Runflow AI Headshot API cost?
$0.30 per generated headshot plus a one-time $2.50 model training fee per user. For a typical session generating 10-15 headshots, this is roughly $2.80-$3.30 in API costs per user. New accounts get $10 in free GPU credits on signup.

How much should I charge for AI headshots?
The market range is $35-$79 per session. Consumer/LinkedIn upgrade tier sits at $29-$49. Professional/job seeker tier sits at $49-$79. Bulk/B2B and white-label deals are priced separately. Most successful indie tools land at $39-$49 for the main consumer tier. Match your price to your positioning and your audience's willingness to pay.

Can I use ChatGPT Codex instead of Claude Code?
Yes. The prompts in this tutorial translate directly. The architectural decisions are tool-agnostic. Use whichever AI coding assistant fits your existing subscription and workflow preferences.

Do I need ML expertise to build this?
No. The Runflow API handles all the AI: photo analysis, model training, generation, quality filtering, likeness ranking. You write a wrapper that calls two HTTP endpoints. Zero ML knowledge required.

Can I use a different AI headshot API?
Yes, the architectural pattern in this tutorial works with most providers. The endpoint shapes will differ. Replace the Runflow Analyze and Generate calls with whichever API you choose, keep the rest of the structure. For a comparison of the major options, see our AI Headshot Generator API guide.

What's the right legal/business setup?
For the first month, an LLC or sole proprietorship and a Stripe account are enough. Add a privacy policy and terms of service before launch (a basic template generator like Termly works for v1). Once you cross $10K in monthly revenue, talk to an accountant about tax structure. Don't over-engineer this; ship first, formalize later.

How do I handle the user's data?
Runflow processes images in isolated environments with automatic cleanup and zero data retention by default. Your job is to handle the data your own app stores: user emails, payment records, generated outputs. Use Supabase Row Level Security or Cloudflare R2 access controls. Tell users in your privacy policy what you store and for how long. Most indie tools keep generated outputs for 30 days then delete.

Will my AI headshot tool actually make money?
Realistic answer: probably not for the first few months, and then maybe yes. Most indie AI tools fail to find customers, not because the product is bad but because marketing is hard and competitive. The tools that succeed have founders who treat distribution as a daily job. The product is the cost of entry. Distribution is what closes the gap.

Where to go from here

If you've read this far, you have everything you need to ship. The remaining work is doing it.

  1. Open Claude Code, create a new project, paste the scaffolding prompt from Hour 1. Don't customize until you have something running.
  2. Get the Runflow API key at runflow.io/api/ai-headshots. $10 in free credits on signup covers your first few test sessions.
  3. Deploy to Vercel within the first day, even if it's broken. Public URL forces the production-shape issues to surface early.
  4. Test the full flow end-to-end with your own photos and a Stripe test card before you let anyone else touch it.
  5. Pick your wedge (audience, price, aesthetic) before you announce. Launching to "everyone who wants AI headshots" is launching to nobody.

The tools that ship are the ones where the founder stops planning and starts pushing code. Claude Code handles the code. Runflow handles the AI. What's left is your decision to build the thing and tell people about it.

For the full Runflow AI Headshot API documentation including the Analyze and Generate endpoint specs, see runflow.io/api/ai-headshots. If you want to compare across providers before committing to one, our AI Headshot Generator API comparison covers the four credible options. And if you want to see the engineering work the Runflow API absorbs for you, Building an AI Image Generator API: 14 things that broke is the long version.

Ship something this weekend. The market is large enough for another good tool.

Want custom benchmarks for your workload?

We'll run our evaluation pipeline against your production data, for free.

Talk to Founders