@prompty-tools/core
v0.5.0
Published
Typed TypeScript client for the prompty.tools public HTTP API.
Readme
@prompty-tools/core
Typed TypeScript client for the prompty.tools public HTTP API.
- Zero runtime dependencies
- Full TypeScript types for every endpoint
- Works in Node 20+, modern browsers, Deno, Bun, and edge runtimes (Cloudflare Workers, Vercel Edge)
- Dual ESM + CJS publish
Installation
npm install @prompty-tools/coreQuickstart
import { createPromptyClient } from "@prompty-tools/core";
const client = createPromptyClient({ apiKey: process.env.PROMPTY_API_KEY! });
const page = await client.prompts.list({ scope: "public", pageSize: 12 });
console.log(page.items.length, "of", page.total);
const prompt = await client.prompts.get(page.items[0].id);
console.log(prompt.title, prompt.compiledPrompt);Authentication
Generate an API key in your Prompty dashboard. Keys start with pk_ and are passed to the client at construction time:
const client = createPromptyClient({
apiKey: process.env.PROMPTY_API_KEY!,
});The key is required and validated synchronously - a missing or malformed key throws PromptyConfigError immediately.
Namespaces
The client exposes one namespace per resource:
| Namespace | Covers |
| ---------------------------------- | ----------------------------------------------------------------- |
| client.prompts | Prompts (versioned) - list, get, create, update, versions |
| client.personas | Personas (versioned) |
| client.tones | Tones |
| client.tones.collections | Tone collections (groups of tones) |
| client.outputs | Outputs |
| client.constraints | Constraints |
| client.constraints.collections | Constraint collections (groups of constraints) |
| client.libraries | Libraries (groups of prompts) |
| client.queues | Queues (ordered lists of prompts for headless agent processing) |
All resources support .list(), .get(id), .create(input), .update(id, input), .delete(id), .vote(id, 1 | -1), .unvote(id), .toggleFavorite(id). Prompts and personas additionally support .setVisibility(id, isPublic), .listVersions(id), and .getVersion(id, versionId). Collections additionally support .listItems(id) and .setItems(id, itemIds) to manage their members. Libraries additionally support .listPrompts(id), .listAllPrompts(id), .addPrompt(id, promptId), and .removePrompt(id, promptId) to manage their members. Queues support .listItems(id), .listAllItems(id), .addItem(id, promptId), .dequeue(id), .markItem(id, itemId, input), and .removeItem(id, itemId).
Creating and updating prompts
The server compiles the full prompt text from the task field and the referenced building blocks. Free-text content fields (compiledPrompt, persona, output, tones, constraints) are not accepted — use the corresponding ID fields instead.
// Minimal prompt — just a task
const created = await client.prompts.create({
title: "Summariser",
task: "Summarise the following text in three bullet points.",
});
// With building block references — the server compiles them into the prompt
const created = await client.prompts.create({
title: "Formal JSON summariser",
task: "Summarise the following text in three bullet points.",
personaVersionId: "pv_abc123",
outputId: "out_xyz789",
toneIds: ["tone_formal", "tone_concise"],
constraintIds: ["con_max100words"],
});
// Read back the server-compiled prompt text
const prompt = await client.prompts.get(created.id);
console.log(prompt.compiledPrompt);
// Update creates a new version — changelog is required
await client.prompts.update(created.id, {
title: "Formal JSON summariser v2",
task: "Summarise the following text in two bullet points.",
outputId: "out_xyz789",
changelog: "Reduced bullet count to two",
});const myToneCollections = await client.tones.collections.list({ scope: "mine" });
const collection = await client.tones.collections.create({
name: "Friendly voices",
itemIds: ["tone_id_1", "tone_id_2"],
});
await client.tones.collections.setItems(collection.id, ["tone_id_3"]);
const library = await client.libraries.create({
name: "Onboarding prompts",
description: "Curated prompts for new hires",
});
await client.libraries.addPrompt(library.id, "prompt_id_1");
const memberPage = await client.libraries.listPrompts(library.id, { pageSize: 24 });
console.log(memberPage.items.map((p) => p.title));Error handling
Every non-2xx response throws a typed error:
import {
PromptyRateLimitError,
PromptyNotFoundError,
PromptyAuthError,
PromptyForbiddenError,
} from "@prompty-tools/core";
try {
await client.prompts.get("prompt_missing");
} catch (err) {
if (err instanceof PromptyNotFoundError) {
console.log("not found");
} else if (err instanceof PromptyRateLimitError) {
console.log("rate limited");
} else if (err instanceof PromptyAuthError) {
console.log("bad API key");
} else if (err instanceof PromptyForbiddenError) {
console.log("action not permitted:", err.message);
} else {
throw err;
}
}Pagination
list() returns a Page<T> with navigation helpers:
let page = await client.prompts.list({ scope: "public", pageSize: 24 });
while (page.hasNext) {
page = await page.next();
console.log(page.items.map((p) => p.title));
}Or use the async iterator to walk every page:
for await (const prompt of client.prompts.listAll({ scope: "mine" })) {
console.log(prompt.title);
}Bring your own fetch
Inject a custom fetch for Cloudflare Workers, Deno, Bun, or tracing:
const client = createPromptyClient({
apiKey: process.env.PROMPTY_API_KEY!,
fetch: (input, init) => tracedFetch(input, init),
});Runtime support
- Node.js 20+
- Modern browsers (any that implement
fetch) - Deno
- Bun
- Cloudflare Workers, Vercel Edge, and other edge runtimes
License
MIT - prompty.tools
