Blogs
Fetch published blog posts from your Wrytze workspace.
The Blogs endpoints let you retrieve published blog posts from your Wrytze workspace. Use them to display blog content on your website, build a headless blog, or integrate with third-party platforms.
List blogs
GET /api/v1/blogsReturns a paginated list of published blogs for your organization. Results are ordered by publish date (newest first).
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
page | integer | No | 1 | Page number |
limit | integer | No | 20 | Results per page (max: 100) |
category | string | No | -- | Filter by category slug |
tag | string | No | -- | Filter by tag slug |
search | string | No | -- | Search by title (case-insensitive) |
website_id | string | No | -- | Filter to a specific website |
Response
Returns an array of blog objects wrapped in data, with a pagination object.
List responses do not include the contentHtml field. Use the Get blog by ID or Get blog by slug endpoints to retrieve the full HTML content.
Cache TTL: 5 minutes.
Examples
curl "https://app.wrytze.com/api/v1/blogs?page=1&limit=10&category=engineering" \
-H "X-API-Key: wrz_sk_abc123..."import { WrytzeClient } from "@wrytze/sdk";
const client = new WrytzeClient({ apiKey: "wrz_sk_abc123..." });
const { data, pagination } = await client.blogs.list({
page: 1,
limit: 10,
category: "engineering",
});
console.log(`Found ${pagination.total} blogs`);
for (const blog of data) {
console.log(blog.title);
}const response = await fetch(
"https://app.wrytze.com/api/v1/blogs?page=1&limit=10&category=engineering",
{
headers: {
"X-API-Key": "wrz_sk_abc123...",
},
}
);
const { data, pagination } = await response.json();
console.log(`Found ${pagination.total} blogs`);
for (const blog of data) {
console.log(blog.title);
}Response example
{
"data": [
{
"id": "cm5abc123def456",
"title": "Building a Modern Blog with Wrytze",
"slug": "building-a-modern-blog-with-wrytze",
"excerpt": "Learn how to set up a headless blog using the Wrytze API and Next.js.",
"metaTitle": "Building a Modern Blog with Wrytze | Acme Inc.",
"metaDescription": "Step-by-step guide to building a headless blog with Wrytze API.",
"featuredImageUrl": "https://cdn.wrytze.com/images/blog-hero.jpg",
"featuredImageAlt": "A developer working on a blog layout",
"wordCount": 1450,
"readingTimeMinutes": 6,
"publishedAt": "2026-02-15T10:30:00.000Z",
"websiteId": "ws_abc123",
"categories": [
{ "name": "Engineering", "slug": "engineering" }
],
"tags": [
{ "name": "Next.js", "slug": "nextjs" },
{ "name": "Tutorial", "slug": "tutorial" }
]
}
],
"pagination": {
"page": 1,
"limit": 10,
"total": 42,
"pages": 5
}
}Get blog by ID
GET /api/v1/blogs/:idReturns a single published blog by its unique ID, including the full HTML content.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | The blog's unique ID (path parameter) |
Response
Returns a single blog object wrapped in data, including the contentHtml field with the full blog content as HTML.
Cache TTL: 15 minutes.
Examples
curl "https://app.wrytze.com/api/v1/blogs/cm5abc123def456" \
-H "X-API-Key: wrz_sk_abc123..."import { WrytzeClient } from "@wrytze/sdk";
const client = new WrytzeClient({ apiKey: "wrz_sk_abc123..." });
const { data } = await client.blogs.get("cm5abc123def456");
console.log(data.title);
console.log(data.contentHtml); // Full HTML contentconst response = await fetch(
"https://app.wrytze.com/api/v1/blogs/cm5abc123def456",
{
headers: {
"X-API-Key": "wrz_sk_abc123...",
},
}
);
const { data } = await response.json();
console.log(data.title);
console.log(data.contentHtml); // Full HTML contentResponse example
{
"data": {
"id": "cm5abc123def456",
"title": "Building a Modern Blog with Wrytze",
"slug": "building-a-modern-blog-with-wrytze",
"excerpt": "Learn how to set up a headless blog using the Wrytze API and Next.js.",
"metaTitle": "Building a Modern Blog with Wrytze | Acme Inc.",
"metaDescription": "Step-by-step guide to building a headless blog with Wrytze API.",
"contentHtml": "<h2>Introduction</h2><p>In this guide, we will walk through...</p>",
"featuredImageUrl": "https://cdn.wrytze.com/images/blog-hero.jpg",
"featuredImageAlt": "A developer working on a blog layout",
"wordCount": 1450,
"readingTimeMinutes": 6,
"publishedAt": "2026-02-15T10:30:00.000Z",
"websiteId": "ws_abc123",
"categories": [
{ "id": "cat_abc123", "name": "Engineering", "slug": "engineering" }
],
"tags": [
{ "id": "tag_abc123", "name": "Next.js", "slug": "nextjs" },
{ "id": "tag_def456", "name": "Tutorial", "slug": "tutorial" }
]
}
}Get blog by slug
GET /api/v1/blogs/slug/:slugReturns a single published blog by its URL-friendly slug, including the full HTML content. Since slugs are unique per website (not globally), the website_id query parameter is required.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
slug | string | Yes | The blog's URL-friendly slug (path parameter) |
website_id | string | Yes | The website ID to look up the blog in (query parameter) |
The website_id query parameter is required for this endpoint. Slugs are unique within a website but may be duplicated across websites in the same organization.
Response
Returns a single blog object wrapped in data, including the contentHtml field.
Cache TTL: 15 minutes.
Examples
curl "https://app.wrytze.com/api/v1/blogs/slug/building-a-modern-blog-with-wrytze?website_id=ws_abc123" \
-H "X-API-Key: wrz_sk_abc123..."import { WrytzeClient } from "@wrytze/sdk";
const client = new WrytzeClient({ apiKey: "wrz_sk_abc123..." });
const { data } = await client.blogs.getBySlug(
"building-a-modern-blog-with-wrytze",
{ websiteId: "ws_abc123" }
);
console.log(data.title);
console.log(data.contentHtml);const response = await fetch(
"https://app.wrytze.com/api/v1/blogs/slug/building-a-modern-blog-with-wrytze?website_id=ws_abc123",
{
headers: {
"X-API-Key": "wrz_sk_abc123...",
},
}
);
const { data } = await response.json();
console.log(data.title);
console.log(data.contentHtml);Response example
{
"data": {
"id": "cm5abc123def456",
"title": "Building a Modern Blog with Wrytze",
"slug": "building-a-modern-blog-with-wrytze",
"excerpt": "Learn how to set up a headless blog using the Wrytze API and Next.js.",
"metaTitle": "Building a Modern Blog with Wrytze | Acme Inc.",
"metaDescription": "Step-by-step guide to building a headless blog with Wrytze API.",
"contentHtml": "<h2>Introduction</h2><p>In this guide, we will walk through...</p>",
"featuredImageUrl": "https://cdn.wrytze.com/images/blog-hero.jpg",
"featuredImageAlt": "A developer working on a blog layout",
"wordCount": 1450,
"readingTimeMinutes": 6,
"publishedAt": "2026-02-15T10:30:00.000Z",
"websiteId": "ws_abc123",
"categories": [
{ "id": "cat_abc123", "name": "Engineering", "slug": "engineering" }
],
"tags": [
{ "id": "tag_abc123", "name": "Next.js", "slug": "nextjs" },
{ "id": "tag_def456", "name": "Tutorial", "slug": "tutorial" }
]
}
}TypeScript Interfaces
Use these interfaces when working with Wrytze API responses in TypeScript:
// Returned in list responses (no contentHtml)
interface Blog {
id: string;
title: string;
slug: string;
excerpt: string | null;
metaTitle: string | null;
metaDescription: string | null;
featuredImageUrl: string | null;
featuredImageAlt: string | null;
wordCount: number;
readingTimeMinutes: number;
publishedAt: string;
websiteId: string;
categories: { name: string; slug: string }[];
tags: { name: string; slug: string }[];
}
// Returned in single-resource responses (includes contentHtml)
// Categories and tags also include the `id` field
interface BlogDetail extends Omit<Blog, "categories" | "tags"> {
contentHtml: string;
categories: { id: string; name: string; slug: string }[];
tags: { id: string; name: string; slug: string }[];
}
// List response envelope
interface BlogListResponse {
data: Blog[];
pagination: {
page: number;
limit: number;
total: number;
pages: number;
};
}
// Single resource response envelope
interface BlogDetailResponse {
data: BlogDetail;
}