Private BetaProposeFlow is currently in private beta.Join the waitlist

Schema Registry

The schema registry provides type-safe access to your registered schemas with full TypeScript inference via discriminated unions.

Registering Schemas

Pass your Zod schemas in the schemas option when initializing the client. Each schema is identified by a unique key.

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

const blogPostSchema = z.object({
  title: z.string(),
  content: z.string(),
  tags: z.array(z.string()),
});

const productSchema = z.object({
  name: z.string(),
  price: z.number(),
  description: z.string(),
});

// Register schemas in the constructor
export const pf = new ProposeFlow({
  apiKey: process.env.PROPOSEFLOW_API_KEY!,
  schemas: {
    blogPost: blogPostSchema,
    product: productSchema,
  },
});

Type Inference

TypeScript automatically infers the correct types based on your schemas using discriminated unions.

usage.ts
// The generate() method knows the return type based on schema name
const { proposal: blogProposal } = await pf.generate('blogPost', {
  input: 'Write about TypeScript',
});

// blogProposal.generatedObject is typed as { title: string; content: string; tags: string[] }
console.log(blogProposal.generatedObject.title);  // ✓ TypeScript knows this is a string
console.log(blogProposal.generatedObject.price);  // ✗ Error: 'price' doesn't exist

const { proposal: productProposal } = await pf.generate('product', {
  input: 'A wireless keyboard',
});

// productProposal.generatedObject is typed as { name: string; price: number; description: string }
console.log(productProposal.generatedObject.price);  // ✓ TypeScript knows this is a number

Automatic Schema Registration

The easiest way to manage schemas is with automatic registration. Enable autoRegisterSchemas and the SDK will automatically register schemas when you call generate().

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

const blogPostSchema = z.object({
  title: z.string(),
  content: z.string(),
  tags: z.array(z.string()),
});

export const pf = new ProposeFlow({
  apiKey: process.env.PROPOSEFLOW_API_KEY!,
  schemas: {
    blogPost: blogPostSchema,
  },
  schemaSync: 'hash',           // Use content-based versioning
  autoRegisterSchemas: true,    // Auto-register on first generate()
});

// No manual registration needed - just generate!
const { proposal } = await pf.generate('blogPost', {
  input: 'Write about TypeScript generics',
});

With hash-based sync, schemas are versioned by their content. If you modify your Zod schema, a new version is automatically registered on the next generate() call.

Manual Schema Registration

You can also register schemas manually with explicit version strings. This gives you more control over versioning and lets you add descriptions and event field allowlists.

register.ts
// Register a single schema from the registry
const schema = await pf.schemas.register('blogPost', {
  version: '1.0.0',
  description: 'A blog post for a tech company website',
  eventFields: ['title', 'content', 'tags'],
});

// Or register all schemas at once
const schemas = await pf.schemas.registerAll({
  version: '1.0.0',
});

console.log(schemas);
// { blogPost: { id: 'sch_abc...', ... }, product: { id: 'sch_xyz...', ... } }

Discriminated Unions

When fetching proposals, use the schemaName field to narrow the type.

narrowing.ts
// Fetch proposals - returns a discriminated union
const { data: proposals } = await pf.proposals.list({ status: 'pending' });

for (const proposal of proposals) {
  // Use schemaName to narrow the type
  if (proposal.schemaName === 'blogPost') {
    // TypeScript knows this is a BlogPost
    console.log(proposal.generatedObject.title);
    console.log(proposal.generatedObject.tags);
  } else if (proposal.schemaName === 'product') {
    // TypeScript knows this is a Product
    console.log(proposal.generatedObject.name);
    console.log(proposal.generatedObject.price);
  }
}

Listing Registered Schemas

list.ts
// List all schemas registered to your account
const { data: schemas, nextCursor } = await pf.schemas.list({
  limit: 10,
});

for (const schema of schemas) {
  console.log(schema.name, schema.id, schema.version);
}

// Get a specific schema by ID
const schema = await pf.schemas.get('sch_abc123');

// Delete a schema by ID
await pf.schemas.delete('sch_abc123');

Type Helpers

Use the InferSchema helper to extract types from your schemas.

types.ts
import { InferSchema } from '@proposeflow/sdk';

const blogPostSchema = z.object({
  title: z.string(),
  content: z.string(),
});

// Extract the type
type BlogPost = InferSchema<typeof blogPostSchema>;
// { title: string; content: string }

// Or use z.infer directly
type BlogPost = z.infer<typeof blogPostSchema>;