@wrytze/sdk
v0.2.0
Published
TypeScript SDK for the Wrytze Blog API
Maintainers
Readme
@wrytze/sdk
TypeScript SDK for the Wrytze Blog API.
Features
- Zero dependencies -- uses native
fetch, no extra packages required - TypeScript-first -- full type definitions for all API responses and parameters
- ESM + CJS -- works in any JavaScript environment
- Pagination support -- built-in pagination for blog listing endpoints
- Error handling -- typed error classes for API errors and rate limits
- Rate limit handling -- automatic detection with
retryAfterinformation
Installation
npm install @wrytze/sdkpnpm add @wrytze/sdkyarn add @wrytze/sdkQuick Start
import { WrytzeClient, WrytzeError, RateLimitError } from '@wrytze/sdk'
const client = new WrytzeClient({
apiKey: 'wrz_sk_...',
websiteId: 'your-website-id', // optional default for all queries
})
// List published blogs
const { data: blogs, pagination } = await client.blogs.list({
page: 1,
limit: 10,
})
console.log(`Found ${pagination.total} blogs`)
for (const blog of blogs) {
console.log(`${blog.title} (${blog.readingTimeMinutes} min read)`)
}
// Get a single blog by slug
try {
const { data: blog } = await client.blogs.getBySlug('my-first-post')
console.log(blog.contentHtml)
} catch (error) {
if (error instanceof RateLimitError) {
console.log(`Rate limited. Retry after ${error.retryAfter} seconds.`)
} else if (error instanceof WrytzeError) {
console.log(`API error: ${error.message} (${error.status})`)
}
}API Reference
Blogs
client.blogs.list(params?)
Returns a paginated list of published blogs.
| Parameter | Type | Required | Description |
| ------------ | -------- | -------- | ------------------------------------ |
| page | number | No | Page number (default: 1) |
| limit | number | No | Results per page (default: 10) |
| category | string | No | Filter by category slug |
| tag | string | No | Filter by tag slug |
| search | string | No | Search blog titles and content |
| websiteId | string | No | Override the default website ID |
Returns: ListResponse<Blog> -- { data: Blog[], pagination: Pagination }
const { data, pagination } = await client.blogs.list({
category: 'engineering',
limit: 20,
})client.blogs.get(id)
Returns a single blog by its UUID, including full HTML content.
| Parameter | Type | Required | Description |
| --------- | -------- | -------- | ---------------- |
| id | string | Yes | Blog UUID |
Returns: SingleResponse<BlogDetail> -- { data: BlogDetail }
const { data: blog } = await client.blogs.get('550e8400-e29b-41d4-a716-446655440000')
console.log(blog.contentHtml)
console.log(blog.tableOfContents) // TocItem[]
console.log(blog.relatedBlogs) // RelatedBlog[]client.blogs.getBySlug(slug, params?)
Returns a single blog by its slug. Requires a websiteId -- either set on the client or passed in params.
| Parameter | Type | Required | Description |
| ------------ | -------- | -------- | ------------------------------------ |
| slug | string | Yes | Blog slug |
| websiteId | string | No | Override the default website ID |
Returns: SingleResponse<BlogDetail> -- { data: BlogDetail }
If no
websiteIdis available (neither in params nor client config), aWrytzeErroris thrown with status400.
const { data: blog } = await client.blogs.getBySlug('getting-started-with-wrytze')Categories
client.categories.list(params?)
Returns all categories for a website.
| Parameter | Type | Required | Description |
| ------------ | -------- | -------- | ------------------------------------ |
| websiteId | string | No | Override the default website ID |
Returns: DataResponse<Category> -- { data: Category[] }
const { data: categories } = await client.categories.list()Tags
client.tags.list(params?)
Returns all tags for a website.
| Parameter | Type | Required | Description |
| ------------ | -------- | -------- | ------------------------------------ |
| websiteId | string | No | Override the default website ID |
Returns: DataResponse<Tag> -- { data: Tag[] }
const { data: tags } = await client.tags.list()Error Handling
All API errors are thrown as typed error classes that you can catch and inspect.
import { WrytzeClient, WrytzeError, RateLimitError } from '@wrytze/sdk'
const client = new WrytzeClient({ apiKey: 'wrz_sk_...' })
try {
const { data: blog } = await client.blogs.get('non-existent-id')
} catch (error) {
if (error instanceof RateLimitError) {
// 429 Too Many Requests
console.log(`Rate limited. Retry after ${error.retryAfter} seconds.`)
} else if (error instanceof WrytzeError) {
// Other API errors (400, 401, 403, 404, 500, etc.)
console.log(`Error: ${error.message}`)
console.log(`Status: ${error.status}`)
}
}| Error Class | Status | Properties | Description |
| ---------------- | ------ | --------------------------------- | ------------------------------------ |
| WrytzeError | Any | message, status | Base error for all API errors |
| RateLimitError | 429 | message, status, retryAfter | Rate limit exceeded (100 req/min) |
Configuration
The WrytzeClient constructor accepts a configuration object:
| Option | Type | Required | Default | Description |
| ------------ | -------- | -------- | ----------------------------- | ------------------------------------------------ |
| apiKey | string | Yes | -- | Your Wrytze API key (prefix: wrz_sk_) |
| baseUrl | string | No | https://app.wrytze.com | API base URL |
| websiteId | string | No | -- | Default website ID for all queries |
Setting websiteId on the client avoids passing it to every method call. Per-method websiteId params override the client default.
const client = new WrytzeClient({
apiKey: 'wrz_sk_...',
websiteId: 'ws_abc123', // used by all methods unless overridden
})
// Uses the default websiteId
const { data: blogs } = await client.blogs.list()
// Overrides for this call only
const { data: otherBlogs } = await client.blogs.list({
websiteId: 'ws_other456',
})Documentation
Full API documentation, integration guides, and code templates are available at docs.wrytze.com.
License
MIT
