Private BetaProposeFlow is currently in private beta.Join the waitlist

Quickstart

Get up and running with ProposeFlow in under 5 minutes. This guide will walk you through installation, configuration, and your first AI-generated proposal.

1Install the SDK

Install the ProposeFlow SDK and Zod for schema validation.

Terminal
npm install @proposeflow/sdk zod

2Get your API key

Sign up at proposeflow.dev and create an API key from your dashboard. Store it securely as an environment variable.

.env
PROPOSEFLOW_API_KEY=pf_live_xxxxxxxxxxxx

3Define your schema

Create a Zod schema that describes the structure of the objects you want to generate. Initialize the ProposeFlow client with your schema.

lib/proposeflow.ts
import { ProposeFlow } from '@proposeflow/sdk';
import { z } from 'zod';

// Define your schema
const BlogPostSchema = z.object({
  title: z.string().describe('A compelling blog post title'),
  summary: z.string().describe('A 2-3 sentence summary'),
  tags: z.array(z.string()).describe('Relevant topic tags'),
  readingTime: z.number().describe('Estimated reading time in minutes'),
});

// Initialize the client with your schemas
export const pf = new ProposeFlow({
  apiKey: process.env.PROPOSEFLOW_API_KEY!,
  schemas: {
    blogPost: BlogPostSchema,
  },
});

// TypeScript automatically infers the type
export type BlogPost = z.infer<typeof BlogPostSchema>;

4Generate a proposal

Use natural language to generate a structured proposal. The AI will return data matching your schema.

app/actions.ts
import { pf } from '@/lib/proposeflow';

export async function generateBlogPost(topic: string) {
  // Generate a proposal from natural language
  const { proposal } = await pf.generate('blogPost', {
    input: `Write a blog post about ${topic}`,
  });

  // proposal.generatedObject is typed as BlogPost
  console.log(proposal.generatedObject);
  // {
  //   title: "Understanding TypeScript Generics",
  //   summary: "A deep dive into...",
  //   tags: ["typescript", "programming"],
  //   readingTime: 8
  // }

  return proposal;
}

Tip: You can specify a modelTier option (fast, balanced, or quality) to control quality/speed/cost tradeoffs. See Model Tiers & Credits for details.

5Capture the decision

Present the proposal to your user and capture their decision. They can approve (with optional edits), or reject with feedback to trigger a new generation.

app/review/page.tsx
import { pf } from '@/lib/proposeflow';

export async function handleApprove(proposalId: string, edits?: Partial<BlogPost>) {
  const decision = await pf.proposals.decide(proposalId, {
    action: 'approve',
    edits,  // Optional: user's modifications
  });

  // Save the final object to your database
  await saveBlogPost(decision.finalObject);
  return decision;
}

export async function handleReject(proposalId: string, feedback: string) {
  // Rejection triggers regeneration with user feedback
  const { proposal } = await pf.proposals.regenerate(proposalId, {
    feedback,  // "Make it more concise" or "Focus on beginners"
  });

  // Show the new proposal to the user for another review
  return proposal;
}

Iterative refinement: When users reject with feedback, the AI generates a new proposal incorporating their input. This cycle continues until they're satisfied.

Next Steps

  • Learn about Schemas and how to define complex data structures
  • Set up Webhooks to receive notifications when decisions are made
  • Explore the React integration for building approval UIs