Skip to content

Client API

Creates a new Promptly client instance.

import { createPromptlyClient } from '@promptlycms/prompts';
const promptly = createPromptlyClient({
apiKey: process.env.PROMPTLY_API_KEY,
});
OptionTypeRequiredDefaultDescription
apiKeystringNoprocess.env.PROMPTLY_API_KEYYour Promptly API key
baseUrlstringNohttps://api.promptlycms.comAPI base URL
model(modelId: string) => LanguageModelNoAuto-detectionCustom model resolver - overrides built-in auto-detection

Returns a PromptlyClient with four methods: getPrompt(), getPrompts(), getComposer(), and getComposers().

  • PromptlyError with code UNAUTHORIZED if no API key is provided and PROMPTLY_API_KEY is not set in the environment.

Fetches a single prompt by ID.

const result = await promptly.getPrompt('my-prompt');
ParameterTypeRequiredDescription
promptIdPromptIdYesThe prompt ID to fetch. Autocompletes known IDs if codegen types are present.
options.versionstringNoSpecific version to fetch (default: latest)
PropertyTypeDescription
promptIdstringThe prompt ID
promptNamestringHuman-readable prompt name
versionstringThe resolved version
systemMessagestringSystem message from the CMS
userMessagePromptMessage<V>Callable function for template interpolation
temperaturenumberTemperature setting
modelLanguageModelAuto-resolved AI SDK model
configPromptConfigFull config including schema fields
publishedVersionsPublishedVersion[]Available published versions (if present)

The userMessage property is both callable and stringifiable:

// Interpolate variables
const text = result.userMessage({ name: 'Alice' });
// Get raw template
const template = String(result.userMessage);
// => 'Hello ${name}!'
client.getPrompt<
T extends string, // Prompt ID
V extends PromptVersion<T> // Version (default: 'latest')
>(promptId: T, options?: GetOptions<V>)
=> Promise<PromptResult<VariablesFor<T, V>>>

When codegen types are present, T narrows to a known prompt ID and VariablesFor<T, V> resolves to the typed variable shape. For unknown IDs, it falls back to Record<string, string>.


Fetches multiple prompts in parallel.

const [first, second] = await promptly.getPrompts([
{ promptId: 'prompt-a' },
{ promptId: 'prompt-b', version: '2.0.0' },
]);
ParameterTypeRequiredDescription
entriesreadonly PromptRequest[]YesArray of prompt requests

Each PromptRequest:

PropertyTypeRequiredDescription
promptIdstringYesThe prompt ID
versionstringNoSpecific version (default: latest)

Returns GetPromptsResults<T> - a mapped tuple where each position is typed to the corresponding request’s prompt variables.

client.getPrompts<const T extends readonly PromptRequest[]>(entries: T)
=> Promise<GetPromptsResults<T>>

The const type parameter preserves literal string types from the input array.


Fetches a single composer by ID. Resolves all prompt segments into AI SDK-compatible objects and returns a formatComposer() function to reassemble the final output.

const composer = await promptly.getComposer('my-composer', {
input: { text: 'Hello world', targetLang: 'French' },
});
ParameterTypeRequiredDescription
composerIdComposerIdYesThe composer ID to fetch. Autocompletes known IDs if codegen types are present.
options.versionstringNoSpecific version to fetch (default: latest)
options.inputRecord<string, string>NoInput variables to interpolate into static segments and prompt user messages
PropertyTypeDescription
composerIdstringThe composer ID
composerNamestringHuman-readable composer name
versionstringThe resolved version
configComposerConfigFull config including schema fields
segmentsComposerSegment[]Raw segment data from the API
promptsComposerPrompt[]De-duplicated array of resolved prompts
formatComposerComposerFormatFn<Names>Function to reassemble the final output from prompt results
compose(generate: ComposerGenerateFn) => Promise<string>Convenience method — runs all prompts through your generate function in parallel and assembles the output
[promptName]ComposerPromptEach prompt is also available as a named property (camelCase of the prompt name)

Each prompt segment in the composer is exposed as a camelCase property on the result. For example, a prompt named “Intro Prompt” becomes introPrompt:

const { introPrompt, reviewPrompt, formatComposer } = await promptly.getComposer(
'my-composer',
{ input: { topic: 'TypeScript' } },
);
// Each named prompt is a ComposerPrompt - spread directly into generateText()
const introResult = await generateText(introPrompt);
const reviewResult = await generateText(reviewPrompt);
// Reassemble the final output
const output = formatComposer({
introPrompt: introResult,
reviewPrompt: reviewResult,
});

Each prompt object has properties that map directly to AI SDK function parameters:

type ComposerPrompt = {
model: LanguageModel;
system: string | undefined;
prompt: string;
temperature: number;
promptId: string;
promptName: string;
};

The simplest way to run a composer. Pass your AI SDK generate function and get back the assembled string:

// Simple — runs all prompts in parallel
const output = await composer.compose(generateText);
// With overrides per prompt
const output = await composer.compose((prompt) =>
generateText({ ...prompt, maxTokens: 500 })
);

compose() accepts any function matching (prompt: ComposerPrompt) => Promise<{ text: string } | string>.

The formatComposer() function accepts a record mapping prompt names to results. Each value can be either a string or an object with a text property (matching the generateText() return shape):

// Pass generateText() results directly
const output = formatComposer({
introPrompt: await generateText(introPrompt),
reviewPrompt: await generateText(reviewPrompt),
});
// Or pass plain strings
const output = formatComposer({
introPrompt: 'Hello, world!',
reviewPrompt: 'Looks good.',
});
client.getComposer<
T extends string, // Composer ID
V extends ComposerVersion<T> // Version (default: 'latest')
>(composerId: T, options?: GetComposerOptions<T, V>)
=> Promise<ComposerResult<ComposerPromptNamesFor<T>>>

When codegen types are present, T narrows to a known composer ID, ComposerInputFor<T, V> types the input option, and ComposerPromptNamesFor<T> types the named prompt keys on the result.


Fetches multiple composers in parallel.

const [first, second] = await promptly.getComposers([
{ composerId: 'composer-a', input: { text: 'Hello' } },
{ composerId: 'composer-b', version: '2.0.0' },
]);
ParameterTypeRequiredDescription
entriesreadonly ComposerRequest[]YesArray of composer requests

Each ComposerRequest:

PropertyTypeRequiredDescription
composerIdstringYesThe composer ID
inputRecord<string, string>NoInput variables for interpolation
versionstringNoSpecific version (default: latest)

Returns GetComposersResults<T> - a mapped tuple where each position is typed to the corresponding request’s composer prompt names.

client.getComposers<const T extends readonly ComposerRequest[]>(entries: T)
=> Promise<GetComposersResults<T>>

The const type parameter preserves literal string types from the input array.