TypeScript SDK — Universal API Client
Official TypeScript SDK for TheFAQApp. Universal API client for Node.js, Deno, Bun, and the browser with full type safety and IntelliSense.
@faqapp/core
Universal TypeScript client for the TheFAQApp API. Works in Node.js, Deno, Bun, and the browser.
Install
npm install @faqapp/coreSetup
import { FAQClient } from '@faqapp/core';
const client = new FAQClient({
apiKey: process.env.FAQ_API_KEY!,
organizationSlug: 'your-org',
});You can also use the factory function:
import { createFAQClient } from '@faqapp/core';
const client = createFAQClient({
apiKey: process.env.FAQ_API_KEY!,
organizationSlug: 'your-org',
});Resources
The SDK uses a resource-based pattern. All resources are accessed as properties on the client instance.
Questions
client.questions.list(params?)
List questions with pagination and optional filters.
const page = await client.questions.list({
limit: 10,
category: 'billing',
sortBy: 'views',
status: 'published',
});
console.log(page.data); // Question[]
console.log(page.pagination); // { page, limit, total, pages }Parameters:
| Param | Type | Description |
|---|---|---|
page | number | Page number (1-indexed) |
limit | number | Items per page |
category | string | Filter by category slug |
search | string | Full-text search query |
status | "published" | "draft" | Filter by status |
featured | "true" | "false" | Filter by featured flag |
tags | string | Comma-separated tag filter |
sortBy | string | created, updated, views, alphabetical, order, helpful |
sortOrder | "asc" | "desc" | Sort direction |
Auto-pagination
Iterate over all items across pages automatically:
for await (const question of client.questions.list().iter()) {
console.log(question.question);
}
// Or iterate page by page
for await (const page of client.questions.list().iterPages()) {
console.log(`Page ${page.pagination.page}:`, page.data.length, 'items');
}client.questions.get(slug)
Get a single question by slug.
const { data: question } = await client.questions.get('how-to-cancel');
console.log(question.question, question.stats);client.questions.create(params)
Create a new question. Requires write scope.
const { data } = await client.questions.create({
question: 'What are your business hours?',
answer: '<p>Monday–Friday, 9am–5pm EST.</p>',
categorySlug: 'general',
published: true,
tags: ['hours', 'contact'],
});client.questions.update(slug, params)
Partial update — only provided fields are changed.
const { data } = await client.questions.update('business-hours', {
answer: '<p>Monday–Friday, 9am–6pm EST.</p>',
featured: true,
});client.questions.delete(slug)
Delete a question by slug.
const { data } = await client.questions.delete('old-question');
console.log(data.deleted); // trueclient.questions.bulk(params)
Bulk-create multiple questions in a single request.
const { data } = await client.questions.bulk({
questions: [
{ question: 'Q1?', answer: 'A1' },
{ question: 'Q2?', answer: 'A2', categorySlug: 'general' },
],
});
console.log(`Created: ${data.created}, Updated: ${data.updated}`);client.questions.export()
Export all questions (non-paginated).
const { data: allQuestions } = await client.questions.export();Categories
client.categories.list(params?)
const page = await client.categories.list({ limit: 50 });
console.log(page.data); // Category[]client.categories.get(slug)
const { data: category } = await client.categories.get('billing');client.categories.create(params)
const { data } = await client.categories.create({
name: 'Billing',
icon: '💳',
description: 'Payment and subscription questions',
});client.categories.update(slug, params)
const { data } = await client.categories.update('billing', {
description: 'Updated description',
});client.categories.delete(slug)
await client.categories.delete('old-category');Search
client.search.query(params)
Search questions by query string. Accepts a string or an options object.
// Simple string search
const { data } = await client.search.query('how do I reset');
// With options
const { data } = await client.search.query({
q: 'billing',
category: 'payments',
limit: 5,
});
console.log(data.results); // SearchResult[]
console.log(data.total); // numberFeedback
client.feedback.submit(questionSlug, params)
Submit feedback for a question.
await client.feedback.submit('how-to-cancel', {
helpful: true,
comment: 'This solved my issue!',
});client.feedback.stats(questionSlug)
Get aggregated feedback statistics.
const { data } = await client.feedback.stats('how-to-cancel');
console.log(data.helpfulPercentage); // e.g. 85Other Resources
The client also provides access to:
client.translations— Manage translations for questions and categoriesclient.webhooks— Manage webhook subscriptionsclient.domains— Manage custom domainsclient.apiKeys— Manage API keysclient.organization— Retrieve organization info
Configuration
new FAQClient({
apiKey: 'faq_...', // Required
organizationSlug: 'my-org', // Required
baseUrl: 'https://api.faq.money', // Default
timeout: 30000, // Default: 30s
maxRetries: 2, // Default: 2 (retries on 429 & 5xx)
});Error Handling
The SDK provides a typed error hierarchy for precise error handling:
import {
FAQAPIError,
FAQValidationError,
FAQNotFoundError,
FAQRateLimitError,
FAQNetworkError,
FAQTimeoutError,
} from '@faqapp/core';
try {
await client.questions.create({ question: '', answer: '' });
} catch (error) {
if (error instanceof FAQNotFoundError) {
console.error('Not found:', error.message);
}
if (error instanceof FAQValidationError) {
console.error('Validation errors:', error.errors);
// error.errors is ValidationIssue[] with field-level details
}
if (error instanceof FAQRateLimitError) {
console.error(`Rate limited. Retry after ${error.retryAfter}s`);
}
if (error instanceof FAQNetworkError) {
console.error('Network error:', error.message);
}
if (error instanceof FAQTimeoutError) {
console.error(`Timed out after ${error.timeoutMs}ms`);
}
if (error instanceof FAQAPIError) {
// Catch-all for any API error (4xx/5xx)
console.error(`${error.status}: ${error.message}`);
console.error('Request ID:', error.requestId);
}
}All errors extend FAQError and carry an optional requestId for traceability.
Pagination
List methods return a PagePromise that resolves to a Page object:
const page = await client.questions.list({ limit: 10 });
page.data; // Question[] — items on this page
page.pagination; // { page, limit, total, pages }
page.hasNextPage(); // boolean
page.getNextPage(); // Promise<Page<Question>>For automatic iteration across all pages:
// All items
for await (const q of client.questions.list().iter()) {
console.log(q.question);
}
// All pages
for await (const page of client.questions.list().iterPages()) {
console.log(page.data);
}Custom Domains API — Map Your Own Domain
Manage custom domains for your TheFAQApp FAQ portal. Add, verify, and configure domains with automatic SSL provisioning.
Next.js SDK — React Hooks & SSR Helpers
Next.js integration for TheFAQApp via @faqapp/nextjs. React hooks, components, SSR/SSG helpers, and SEO utilities for FAQ content.