@potion5/sdk
v1.0.0
Published
Official TypeScript SDK for the Potion API - AI-powered beverage formulation platform
Downloads
121
Maintainers
Readme
Potion TypeScript/Node.js SDK
Official TypeScript SDK for the Potion API - AI-powered beverage formulation platform.
Installation
npm install @potion/sdk
# or
yarn add @potion/sdk
# or
pnpm add @potion/sdkQuick Start
import { Potion } from '@potion/sdk';
// Initialize the client
const client = new Potion({ apiKey: 'pk_live_your_key_here' });
// Generate a formulation
const formulation = await client.formulations.generate({
prompt: 'A refreshing citrus energy drink with natural caffeine',
category: 'nonalc',
subcategory: 'csd.energy_drink',
constraints: ['natural', 'under-100-calories'],
});
console.log(`Created: ${formulation.name}`);
console.log(`Calories: ${formulation.nutrition.calories}`);Features
- Full TypeScript support - Complete type definitions
- Promise-based - Async/await ready
- Automatic retries - Built-in retry logic with exponential backoff
- Streaming - Support for SSE streaming responses
- Rate limiting - Automatic rate limit handling
- Tree-shakeable - Import only what you need
Usage
Formulations
import { Potion } from '@potion/sdk';
const client = new Potion({ apiKey: 'pk_live_your_key_here' });
// List formulations
const { data: formulations } = await client.formulations.list({
limit: 20,
status: 'active',
});
// Get a specific formulation
const formulation = await client.formulations.get('formulation-uuid');
// Generate with AI
const generated = await client.formulations.generate({
prompt: 'Low-sugar probiotic kombucha',
category: 'nonalc',
subcategory: 'functional.kombucha',
});
// Create variations
const variations = await client.formulations.createVariations(
'formulation-uuid',
{
variationType: 'flavor',
count: 3,
}
);
// Get substitutions
const substitutions = await client.formulations.getSubstitutions(
'formulation-uuid',
{
ingredientName: 'Organic Cane Sugar',
reason: 'cost',
}
);Ingredients
// List ingredients
const { data: ingredients } = await client.ingredients.list({
category: 'sweetener',
});
// Search ingredients
const results = await client.ingredients.search('natural caffeine');
// Augment ingredient with AI
const augmented = await client.ingredients.augment({
ingredientName: 'Guarana Extract',
physicalState: 'solid',
});
// Batch augment
const batchResults = await client.ingredients.augmentBatch({
ingredients: ['Stevia', 'Monk Fruit Extract', 'Erythritol'],
});
// Check compatibility
const compatibility = await client.ingredients.checkCompatibility(
'Citric Acid',
{
withIngredients: ['Sodium Benzoate', 'Potassium Sorbate'],
}
);SOP Generation
// Generate SOP for a formulation
const sop = await client.sop.generate('formulation-uuid', {
productionScale: 'commercial',
includeHaccp: true,
});
// Get SOP profiles
const profiles = await client.sop.listProfiles();
// Retrieve existing SOP
const existing = await client.sop.get('sop-uuid');Labeling
// Generate labeling requirements
const labeling = await client.labeling.generate('formulation-uuid', {
containerSizeMl: 355,
servingSizeMl: 355,
targetMarkets: ['US', 'CA'],
});
// Check claims eligibility
const claims = await client.labeling.checkClaims({
formulationId: 'formulation-uuid',
claims: ['organic', 'non_gmo', 'low_calorie', 'natural'],
});Assistant
// Chat with the assistant
const response = await client.assistant.chat({
message: "What's the best natural sweetener for an energy drink?",
formulationId: 'formulation-uuid', // Optional context
});
// Streaming response
const stream = await client.assistant.chatStream({
message: 'Explain the FDA requirements for caffeine labeling',
});
for await (const chunk of stream) {
process.stdout.write(chunk.content);
}
// List conversations
const conversations = await client.assistant.listConversations();
// Get conversation history
const conversation = await client.assistant.getConversation('conversation-uuid');Supply Chain
// Search copackers
const copackers = await client.supplyChain.searchCopackers({
capabilities: ['hot_fill', 'aseptic'],
state: 'CA',
certifications: ['SQF', 'Organic'],
});
// Get AI recommendations
const recommendations = await client.supplyChain.recommendCopackers({
formulationId: 'formulation-uuid',
requirements: {
minVolume: 10000,
certifications: ['Organic'],
},
});
// Search distributors
const distributors = await client.supplyChain.searchDistributors({
region: 'West Coast',
channels: ['natural_grocery', 'specialty'],
});Compliance
// Run compliance check
const compliance = await client.compliance.check({
formulationId: 'formulation-uuid',
targetStates: ['CA', 'NY', 'TX'],
});
// Get DTC shipping rules
const dtcRules = await client.compliance.getDtcShipping({
states: ['CA', 'NY'],
productType: 'non_alcoholic_beverage',
});
// Get regulatory updates
const updates = await client.compliance.getUpdates({
category: 'fda',
since: '2024-01-01',
});Webhooks
// Create webhook
const webhook = await client.webhooks.create({
url: 'https://your-server.com/webhook',
events: ['formulation.created', 'formulation.updated'],
secret: 'your-webhook-secret',
});
// List webhooks
const webhooks = await client.webhooks.list();
// Test webhook
const result = await client.webhooks.test('webhook-uuid', {
eventType: 'formulation.created',
});
// Get delivery history
const deliveries = await client.webhooks.getDeliveries('webhook-uuid');Idempotency
Prevent duplicate operations on retries using idempotency keys:
import { Potion, generateIdempotencyKey } from '@potion/sdk';
const client = new Potion({ apiKey: 'pk_live_your_key_here' });
// Generate a unique idempotency key
const idempotencyKey = generateIdempotencyKey();
// Use the key for mutation operations
const formulation = await client.formulations.generate(
{
prompt: 'A refreshing citrus energy drink',
category: 'nonalc',
subcategory: 'csd.energy_drink',
},
{ idempotencyKey }
);
// If you retry with the same key, you'll get the cached response
// This prevents duplicate formulations from being createdIdempotency keys:
- Must be 10-255 characters (alphanumeric, hyphens, underscores)
- Are retained for 24 hours
- Only apply to mutation operations (POST, PUT, PATCH, DELETE)
Error Handling
import { Potion, PotionError, RateLimitError, NotFoundError } from '@potion/sdk';
const client = new Potion({ apiKey: 'pk_live_your_key_here' });
try {
const formulation = await client.formulations.get('invalid-uuid');
} catch (error) {
if (error instanceof NotFoundError) {
console.log(`Formulation not found: ${error.message}`);
} else if (error instanceof RateLimitError) {
console.log(`Rate limited. Retry after ${error.retryAfter} seconds`);
} else if (error instanceof PotionError) {
console.log(`API error: ${error.code} - ${error.message}`);
} else {
throw error;
}
}Configuration
import { Potion } from '@potion/sdk';
const client = new Potion({
apiKey: 'pk_live_your_key_here',
// Optional configuration
baseUrl: 'https://api.potion.com', // Custom base URL
timeout: 30000, // Request timeout in milliseconds
maxRetries: 3, // Max retry attempts
});Sandbox Mode
Use sandbox keys for development and testing:
import { Potion } from '@potion/sdk';
// Use sandbox key
const client = new Potion({ apiKey: 'pk_sandbox_your_key_here' });
// Check if in sandbox mode
console.log(client.isSandbox); // true
// Check sandbox status
const status = await client.sandbox.getStatus();
console.log(`Requests remaining: ${status.usage.requestsLimit - status.usage.requestsToday}`);
// Reset sandbox data
await client.sandbox.reset();
// Load test scenario
await client.sandbox.loadScenario('energy-drink-launch');TypeScript Types
All types are exported for your convenience:
import type {
Formulation,
Ingredient,
SOPDocument,
LabelingRequirements,
Copacker,
Distributor,
Webhook,
Conversation,
ComplianceCheck,
NutritionInfo,
} from '@potion/sdk';Requirements
- Node.js 18+ (or compatible runtime)
- TypeScript 4.7+ (for TypeScript users)
License
MIT License - see LICENSE file for details.
Support
- Documentation: https://potion.com/documentation
- API Reference: https://potion.com/api/v1/docs
- Email: [email protected]
