Getting started
Install the package, generate an API key, and make your first call.
Install
The package is published to npm under the
@prompty-tools scope. It targets Node.js 20+ and ships
both ESM and CJS builds with TypeScript declarations.
npm install @prompty-tools/core
# or
pnpm add @prompty-tools/core
# or
yarn add @prompty-tools/core
Authenticate
Every request needs a Bearer API key starting with pk_.
Generate one in your prompty.tools dashboard, then pass it to the
client at construction time:
import { createPromptyClient } from "@prompty-tools/core";
const client = createPromptyClient({
apiKey: process.env.PROMPTY_API_KEY,
});
localStorage on this domain and never sent anywhere except
www.prompty.tools/api/v1 when you click Run.
The client validates the key shape at construction time and throws
PromptyConfigError
synchronously if it's missing or doesn't start with pk_:
// `createPromptyClient` and the error classes are pre-bound for these examples.
try {
createPromptyClient({ apiKey: "definitely-not-a-key" });
} catch (err) {
if (err instanceof PromptyConfigError) {
console.log("config rejected:", err.message);
return { rejected: true, message: err.message };
}
throw err;
}
First call
With a key set, you can hit the API. The example below lists the public feed, six prompts at a time, sorted by upvotes.
const page = await client.prompts.list({
scope: "public",
sort: "most-upvoted",
pageSize: 6,
});
console.log(`Page ${page.page} of ${Math.ceil(page.total / page.pageSize)}`);
return page.items.map((p) => ({
title: p.title,
upvotes: p.upvotes,
tags: p.tags,
}));
Client configuration
createPromptyClient accepts the following options:
| Option | Type | Default | Description |
|---|---|---|---|
apiKey required |
string |
- | Bearer API key (must start with pk_). |
baseUrl |
string |
https://prompty.tools/api/v1 |
Useful for self-hosted or staging environments. |
fetch |
typeof fetch |
globalThis.fetch |
Inject a custom fetch - see bring your own fetch. |
userAgent |
string |
@prompty-tools/core/<version> |
Sent on Node-like runtimes; browsers ignore. |
timeoutMs |
number |
30000 |
Per-request abort. Use 0 to disable. |
maxRetries |
number |
0 |
GET-only retry on 429/5xx with exponential backoff. See retries. |
defaultHeaders |
Record<string, string> |
{} |
Merged into every request. |
onRequest |
(ctx) => void | Promise<void> |
- | Called before every fetch - useful for tracing/logging. |
onResponse |
(ctx) => void | Promise<void> |
- | Called after every fetch (success or error) - receives status, duration, and any thrown error. |
TypeScript
Types are first-class. Every method, every DTO, every error is fully annotated. Inputs and outputs are typed against the actual server contract:
import {
createPromptyClient,
type Prompt,
type PromptCreateInput,
type Page,
type PromptSummary,
} from "@prompty-tools/core";
const client = createPromptyClient({ apiKey: process.env.PROMPTY_API_KEY! });
const page: Page<PromptSummary> = await client.prompts.list({ scope: "public" });
const detail: Prompt = await client.prompts.get(page.items[0]!.id);
const input: PromptCreateInput = {
title: "Write a haiku",
task: "Write a haiku about TypeScript",
compiledPrompt: "Write a haiku about TypeScript. Three lines, 5/7/5 syllables.",
isPublic: false,
};
await client.prompts.create(input);
DTO arrays are typed as readonly T[]; date fields are ISO
8601 strings ("2026-04-13T10:42:00.000Z") - call
new Date(prompt.createdAt) when you want a
Date.
Supported runtimes
- Node.js 20+ (uses native
fetchandAbortSignal.any) - Modern browsers
- Deno
- Bun
- Cloudflare Workers, Vercel Edge, and other edge runtimes
For non-standard environments where globalThis.fetch
isn't ideal, see
bring your own fetch.