@thankyouai/sdk
v0.3.0
Published
Official TypeScript SDK for the ThankYou unified creative generation API.
Maintainers
Readme
ThankYou TypeScript SDK
Official TypeScript SDK for the ThankYou unified creative generation API.
npm install @thankyouai/sdkThe package supports both ESM and CommonJS on Node.js 18 and newer.
Create a Client
ESM:
import { ThankYou } from "@thankyouai/sdk";
const thankyou = new ThankYou({
apiKey: process.env.THANKYOU_API_KEY!,
});CommonJS:
const { ThankYou } = require("@thankyouai/sdk");
const thankyou = new ThankYou({
apiKey: process.env.THANKYOU_API_KEY,
});The default base URL is https://api.thankyouai.com/open/v1.
Text to Image
const result = await thankyou.run({
model: "flux/v2/pro/text-to-image",
input: {
prompt: "A mountain landscape at golden hour",
aspect_ratio: "16:9",
},
});
console.log(result.output[0]?.url);Image to Video with an Uploaded File
const file = await thankyou.files.upload({
file: "./photo.jpg",
});
const generation = await thankyou.generations.create({
model: "wan/v2.6",
input: {
prompt: "Gentle camera movement with soft evening light",
reference_assets: [{ role: "primary", url: file.url }],
},
});
const result = await thankyou.generations.wait(generation.id, {
interval: 3000,
timeout: 10 * 60 * 1000,
});Quote Before Execute
Use a quote when you want to estimate the cost and check whether a request can run before starting the generation. A quote returns the resolved input, estimated cost, blocking reasons, and an expiration time.
const quote = await thankyou.generations.quote({
model: "wan/v2.6",
input: { prompt: "A koi fish swimming", duration: 5 },
});
if (quote.blocking_reasons.length > 0) {
throw new Error(quote.blocking_reasons.join(", "));
}
console.log(quote.estimated_cost, quote.currency, quote.expires_at);
const generation = await thankyou.generations.create({
quoteId: quote.quote_id,
});Models
const models = await thankyou.models.list();
const detail = await thankyou.models.detail("wan/v2.6");
console.log(models.models.length);
console.log(detail.input_schema);Model IDs can contain /, so models.detail() calls GET /models/detail?model_id=....
Usage
const usage = await thankyou.usage.get({ days: 30 });
console.log(usage.media.total_tasks);
console.log(usage.llm.total_tokens);LLM Requests
const requests = await thankyou.llmRequests.list({
page: 1,
pageSize: 20,
status: "succeeded",
modelPrefix: "gpt-",
});
console.log(requests.requests[0]?.request_id);Webhook Verification
const event = thankyou.webhooks.verify({
rawBody,
signature: request.headers["x-thankyou-signature"],
timestamp: request.headers["x-thankyou-timestamp"],
secret: process.env.THANKYOU_WEBHOOK_SECRET!,
});
if (event.event === "generation.completed") {
console.log(event.generation?.output[0]?.url);
}The signature is HMAC-SHA256 over ${timestamp}.${rawBody} and is formatted as sha256=<hex>.
Error Handling
import {
ThankYouAPIError,
ThankYouAuthenticationError,
ThankYouRateLimitError,
ThankYouValidationError,
} from "@thankyouai/sdk";
try {
await thankyou.generations.create({
model: "wan/v2.6",
input: { prompt: "test" },
});
} catch (error) {
if (error instanceof ThankYouRateLimitError) {
console.error("Rate limited", error.code, error.details);
} else if (error instanceof ThankYouValidationError) {
console.error("Invalid request", error.details);
} else if (error instanceof ThankYouAuthenticationError) {
console.error("Check your API key");
} else if (error instanceof ThankYouAPIError) {
console.error(error.status, error.code, error.retryable, error.details);
} else {
throw error;
}
}Type Strategy
The SDK generates built-in model input types from the live developer API model list and each model's models.detail().input_schema. Dynamic or custom model IDs still fall back to generic JSON input.
