Skip to content

JavaScript SDK

The official JavaScript SDK for Splinterpic provides a simple, type-safe way to interact with the API.

Terminal window
npm install @splinterpic/sdk
Terminal window
yarn add @splinterpic/sdk
Terminal window
pnpm add @splinterpic/sdk
import { SplinterpicClient } from '@splinterpic/sdk';
const client = new SplinterpicClient({
baseUrl: 'https://your-worker.workers.dev'
});
// Generate an image
const image = await client.generate({
prompt: 'A beautiful mountain landscape at sunset',
model: '@cf/black-forest-labs/flux-1-schnell'
});
console.log('Image URL:', image.r2_url);
import { SplinterpicClient, type GenerateImageRequest } from '@splinterpic/sdk';
const client = new SplinterpicClient({
baseUrl: 'https://your-worker.workers.dev'
});
const request: GenerateImageRequest = {
prompt: 'A beautiful mountain landscape at sunset',
model: '@cf/black-forest-labs/flux-1-schnell'
};
const image = await client.generate(request);

Until the official SDK is published, use this reference implementation:

class SplinterpicClient {
constructor(config) {
this.baseUrl = config.baseUrl;
this.defaultModel = config.defaultModel || '@cf/black-forest-labs/flux-1-schnell';
}
async request(endpoint, options = {}) {
const url = `${this.baseUrl}${endpoint}`;
const response = await fetch(url, {
...options,
headers: {
'Content-Type': 'application/json',
...options.headers
}
});
if (!response.ok) {
const error = await response.json().catch(() => ({ error: 'Request failed' }));
throw new Error(error.error || `HTTP ${response.status}`);
}
return response.json();
}
// Generate a new image
async generate({ prompt, model, template_id }) {
return this.request('/api/generate', {
method: 'POST',
body: JSON.stringify({
prompt,
model: model || this.defaultModel,
template_id
})
});
}
// List images
async listImages({ limit = 20, offset = 0 } = {}) {
return this.request(`/api/images?limit=${limit}&offset=${offset}`);
}
// Get a specific image
async getImage(imageId) {
return this.request(`/api/images/${imageId}`);
}
// Delete an image
async deleteImage(imageId) {
return this.request(`/api/images/${imageId}`, {
method: 'DELETE'
});
}
// List collections
async listCollections() {
return this.request('/api/collections');
}
// Create a collection
async createCollection({ name, description }) {
return this.request('/api/collections', {
method: 'POST',
body: JSON.stringify({ name, description })
});
}
// Get collection details
async getCollection(collectionId) {
return this.request(`/api/collections/${collectionId}`);
}
// List images in a collection
async getCollectionImages(collectionId) {
return this.request(`/api/collections/${collectionId}/images`);
}
// Delete a collection
async deleteCollection(collectionId) {
return this.request(`/api/collections/${collectionId}`, {
method: 'DELETE'
});
}
// List available models
async listModels() {
return this.request('/api/models');
}
// Get model details
async getModel(modelId) {
return this.request(`/api/models/${encodeURIComponent(modelId)}`);
}
// Get usage analytics
async getUsageAnalytics() {
return this.request('/api/analytics/usage');
}
// Get cost analytics
async getCostAnalytics() {
return this.request('/api/analytics/costs');
}
}
// Export for use
export { SplinterpicClient };
const client = new SplinterpicClient({
baseUrl: 'https://your-worker.workers.dev'
});
// Single image
const image = await client.generate({
prompt: 'A futuristic city with flying cars',
model: '@cf/black-forest-labs/flux-1-schnell'
});
console.log(image);
// {
// id: 'img_abc123',
// r2_url: 'https://...',
// created_at: '2024-01-15T10:30:00.000Z'
// }
const prompts = [
'Mountain landscape at sunrise',
'Ocean waves during golden hour',
'Forest path in autumn'
];
const images = await Promise.all(
prompts.map(prompt => client.generate({ prompt }))
);
console.log(`Generated ${images.length} images`);
// Get first 50 images
const { images, pagination } = await client.listImages({
limit: 50,
offset: 0
});
console.log(`Found ${pagination.total} images`);
// Paginate through all images
async function getAllImages() {
const allImages = [];
let offset = 0;
const limit = 100;
while (true) {
const { images, pagination } = await client.listImages({ limit, offset });
allImages.push(...images);
if (!pagination.has_more) break;
offset += limit;
}
return allImages;
}
// Create a collection
const collection = await client.createCollection({
name: 'Marketing Campaign 2024',
description: 'Q1 social media assets'
});
// Add images to collection (note: requires additional endpoint implementation)
// This is a placeholder for future functionality
// await client.addImageToCollection(collection.id, imageId);
// List all collections
const collections = await client.listCollections();
// Get collection details
const details = await client.getCollection(collection.id);
// Delete a collection
await client.deleteCollection(collection.id);
// List all available models
const models = await client.listModels();
models.forEach(model => {
console.log(`${model.name}: $${model.cost_per_image}/image`);
});
// Get specific model details
const fluxModel = await client.getModel('@cf/black-forest-labs/flux-1-schnell');
console.log(fluxModel);
// Get usage statistics
const usage = await client.getUsageAnalytics();
console.log(`Total images generated: ${usage.total_images}`);
// Get cost analytics
const costs = await client.getCostAnalytics();
console.log(`Total cost: $${costs.total_cost}`);
console.log(`Average per image: $${costs.average_cost}`);
try {
const image = await client.generate({
prompt: 'A beautiful landscape',
model: '@cf/black-forest-labs/flux-1-schnell'
});
} catch (error) {
console.error('Generation failed:', error.message);
}
async function generateWithRetry(prompt, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await client.generate({ prompt });
} catch (error) {
if (i === maxRetries - 1) throw error;
console.log(`Retry ${i + 1}/${maxRetries}...`);
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
}
}
}
const image = await generateWithRetry('A beautiful landscape');

Full TypeScript definitions:

interface SplinterpicConfig {
baseUrl: string;
defaultModel?: string;
}
interface GenerateImageRequest {
prompt: string;
model?: string;
template_id?: string;
}
interface Image {
id: string;
prompt: string;
model: string;
r2_key: string;
r2_url: string;
width: number;
height: number;
created_at: string;
user_id: string;
cost: number;
is_deleted: boolean;
}
interface ListImagesResponse {
images: Image[];
pagination: {
limit: number;
offset: number;
total: number;
has_more: boolean;
};
}
interface Collection {
id: string;
name: string;
description: string;
created_at: string;
user_id: string;
}
interface Model {
id: string;
name: string;
description: string;
cost_per_image: number;
is_recommended: boolean;
}
declare class SplinterpicClient {
constructor(config: SplinterpicConfig);
generate(request: GenerateImageRequest): Promise<Image>;
listImages(options?: { limit?: number; offset?: number }): Promise<ListImagesResponse>;
getImage(imageId: string): Promise<Image>;
deleteImage(imageId: string): Promise<void>;
listCollections(): Promise<{ collections: Collection[] }>;
createCollection(data: { name: string; description: string }): Promise<Collection>;
getCollection(collectionId: string): Promise<Collection>;
getCollectionImages(collectionId: string): Promise<{ images: Image[] }>;
deleteCollection(collectionId: string): Promise<void>;
listModels(): Promise<{ models: Model[] }>;
getModel(modelId: string): Promise<Model>;
getUsageAnalytics(): Promise<any>;
getCostAnalytics(): Promise<any>;
}
export { SplinterpicClient };
export type {
SplinterpicConfig,
GenerateImageRequest,
Image,
ListImagesResponse,
Collection,
Model
};
import { useState, useCallback } from 'react';
import { SplinterpicClient } from './splinterpic-client';
const client = new SplinterpicClient({
baseUrl: process.env.REACT_APP_API_URL
});
function useSplinterpic() {
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const generate = useCallback(async (prompt) => {
setLoading(true);
setError(null);
try {
const image = await client.generate({ prompt });
return image;
} catch (err) {
setError(err.message);
throw err;
} finally {
setLoading(false);
}
}, []);
return { generate, loading, error };
}
// Usage in component
function ImageGenerator() {
const { generate, loading, error } = useSplinterpic();
const [image, setImage] = useState(null);
const handleGenerate = async () => {
const result = await generate('A beautiful mountain landscape');
setImage(result);
};
return (
<div>
<button onClick={handleGenerate} disabled={loading}>
{loading ? 'Generating...' : 'Generate Image'}
</button>
{error && <p>Error: {error}</p>}
{image && <img src={image.r2_url} alt={image.prompt} />}
</div>
);
}
pages/api/generate.js
import { SplinterpicClient } from '@/lib/splinterpic-client';
const client = new SplinterpicClient({
baseUrl: process.env.SPLINTERPIC_API_URL
});
export default async function handler(req, res) {
if (req.method !== 'POST') {
return res.status(405).json({ error: 'Method not allowed' });
}
try {
const { prompt } = req.body;
const image = await client.generate({ prompt });
res.status(200).json(image);
} catch (error) {
res.status(500).json({ error: error.message });
}
}
import express from 'express';
import { SplinterpicClient } from './splinterpic-client.js';
const app = express();
const client = new SplinterpicClient({
baseUrl: process.env.SPLINTERPIC_API_URL
});
app.use(express.json());
app.post('/generate', async (req, res) => {
try {
const { prompt } = req.body;
const image = await client.generate({ prompt });
res.json(image);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});