Articles API (Knowledge Base)
The Articles API manages knowledge base articles including creation, publishing, versioning, search, and reader feedback.
Article Object
{
id: string; // UUID
organization_id: string; // UUID of the organization
title: string; // Article title
slug: string; // URL-friendly identifier
content: object; // Rich text content (TipTap JSON)
content_html?: string; // HTML version
excerpt?: string; // Short description
collection_id?: string; // UUID of parent collection
status: string; // draft, review, published, archived
current_version: number; // Version number
view_count: number; // Total views
search_text: string; // Searchable text content
created_at: string; // ISO timestamp
updated_at: string; // ISO timestamp
deleted_at?: string; // ISO timestamp (soft delete)
// Joined relations
collection?: {
name: string;
slug: string;
};
}
Status Values
| Status | Description |
|---|---|
draft | Work in progress, not visible to public |
review | Ready for review before publishing |
published | Live and visible to customers |
archived | No longer active but retained |
List Articles
List published articles, optionally filtered by collection or search query.
Procedure: articles.list
Authentication: None (public endpoint)
Input:
{
collectionId?: string; // Filter by collection UUID
search?: string; // Full-text search query
organizationId?: string; // Filter by organization
limit?: number; // 1-100, default: 20
}
Example:
curl -X GET "https://your-domain.com/api/trpc/articles.list?input=%7B%22collectionId%22:%22uuid%22,%22limit%22:10%7D"
Response:
{
"result": {
"data": {
"json": [
{
"id": "uuid",
"title": "Getting Started Guide",
"slug": "getting-started",
"excerpt": "Learn how to set up and configure your account",
"status": "published",
"view_count": 1250,
"collection": {
"name": "Onboarding",
"slug": "onboarding"
},
"created_at": "2024-01-01T00:00:00.000Z"
}
]
}
}
}
Notes:
- Only returns published articles
- Results sorted by position (custom ordering)
Get Article by ID
Retrieve a single article by its UUID. Used for dashboard editing.
Procedure: articles.getById
Authentication: Required
Input:
{
id: string; // Article UUID
}
Example:
curl -X GET "https://your-domain.com/api/trpc/articles.getById?input=%7B%22id%22:%22article-uuid%22%7D" \
-H "Cookie: your-session-cookie"
Response:
{
"result": {
"data": {
"json": {
"id": "uuid",
"title": "Getting Started Guide",
"slug": "getting-started",
"content": {
"type": "doc",
"content": [...]
},
"content_html": "<p>...</p>",
"excerpt": "Learn how to set up...",
"status": "draft",
"current_version": 3,
"collection": {
"name": "Onboarding",
"slug": "onboarding"
},
"created_at": "2024-01-01T00:00:00.000Z"
}
}
}
}
Notes:
- Returns articles in any status (draft, review, published, archived)
- Used for editing in the dashboard
Get Article by Slug
Retrieve a published article by its URL slug. Optimized for public access with caching.
Procedure: articles.getBySlug
Authentication: None (public endpoint)
Input:
{
slug: string; // URL-friendly slug
organizationId?: string; // Optional organization filter
}
Example:
curl -X GET "https://your-domain.com/api/trpc/articles.getBySlug?input=%7B%22slug%22:%22getting-started%22%7D"
Response:
{
"result": {
"data": {
"json": {
"id": "uuid",
"title": "Getting Started Guide",
"slug": "getting-started",
"content": {
"type": "doc",
"content": [...]
},
"content_html": "<p>Welcome to our platform...</p>",
"excerpt": "Learn how to set up...",
"status": "published",
"view_count": 1251,
"collection": {
"name": "Onboarding",
"slug": "onboarding"
}
}
}
}
}
Side Effects:
- Increments view count asynchronously
Notes:
- Only returns published articles
- Results are cached for 30 minutes
- View counts are tracked automatically
Create Article
Create a new knowledge base article.
Procedure: articles.create
Authentication: Required
Input:
{
title: string; // 1-500 characters
slug: string; // 1-200 characters, URL-safe
content: object; // TipTap JSON document
excerpt?: string; // Short description
collectionId?: string; // Parent collection UUID
status?: 'draft' | 'review' | 'published' | 'archived'; // default: 'draft'
}
Example:
curl -X POST "https://your-domain.com/api/trpc/articles.create" \
-H "Content-Type: application/json" \
-H "Cookie: your-session-cookie" \
-d '{
"json": {
"title": "How to Reset Your Password",
"slug": "reset-password",
"content": {
"type": "doc",
"content": [
{
"type": "paragraph",
"content": [
{"type": "text", "text": "Follow these steps to reset your password..."}
]
}
]
},
"excerpt": "Step-by-step guide for resetting your account password",
"collectionId": "collection-uuid",
"status": "draft"
}
}'
Response:
{
"result": {
"data": {
"json": {
"id": "uuid",
"title": "How to Reset Your Password",
"slug": "reset-password",
"status": "draft",
"current_version": 1,
"created_at": "2024-01-15T10:30:00.000Z"
}
}
}
}
Side Effects:
- Creates initial version record in
article_versions - Content is sanitized to prevent XSS
Notes:
- Rate limited to prevent abuse
- Slug must be unique within the organization
- HTML is automatically generated from TipTap content
Update Article
Update an existing article. Creates a new version when content changes.
Procedure: articles.update
Authentication: Required
Input:
{
id: string; // Required, article UUID
title?: string; // 1-500 characters
slug?: string; // 1-200 characters
content?: object; // TipTap JSON document
excerpt?: string; // Short description
status?: 'draft' | 'review' | 'published' | 'archived';
changeSummary?: string; // Description of changes
}
Example:
curl -X POST "https://your-domain.com/api/trpc/articles.update" \
-H "Content-Type: application/json" \
-H "Cookie: your-session-cookie" \
-d '{
"json": {
"id": "article-uuid",
"content": {...},
"status": "published",
"changeSummary": "Added section on two-factor authentication"
}
}'
Response:
{
"result": {
"data": {
"json": {
"id": "uuid",
"title": "How to Reset Your Password",
"current_version": 2,
"status": "published",
"updated_at": "2024-01-15T11:00:00.000Z"
}
}
}
}
Side Effects:
- Increments version number
- Creates version record if content changed
- Invalidates article cache
Notes:
- Content changes create a new version for history tracking
- Cache is automatically invalidated on update
Delete Article
Soft delete an article.
Procedure: articles.delete
Authentication: Required
Input:
{
id: string; // Article UUID
}
Example:
curl -X POST "https://your-domain.com/api/trpc/articles.delete" \
-H "Content-Type: application/json" \
-H "Cookie: your-session-cookie" \
-d '{"json":{"id":"article-uuid"}}'
Response:
{
"result": {
"data": {
"json": {
"success": true
}
}
}
}
Search Articles
Search articles with typo tolerance using trigram similarity matching.
Procedure: articles.search
Authentication: None (public endpoint)
Input:
{
query: string; // Search query
organizationId?: string; // Filter by organization
limit?: number; // 1-50, default: 10
similarityThreshold?: number; // 0-1, default: 0.3
}
Example:
curl -X GET "https://your-domain.com/api/trpc/articles.search?input=%7B%22query%22:%22passowrd%20reset%22,%22limit%22:5%7D"
Response:
{
"result": {
"data": {
"json": [
{
"id": "uuid",
"title": "How to Reset Your Password",
"slug": "reset-password",
"excerpt": "Step-by-step guide for resetting your account password",
"similarity": 0.85,
"collection": {
"name": "Account Management",
"slug": "account"
}
},
{
"id": "uuid-2",
"title": "Password Security Best Practices",
"slug": "password-security",
"excerpt": "Keep your account safe with strong passwords",
"similarity": 0.65,
"collection": {
"name": "Security",
"slug": "security"
}
}
]
}
}
}
Notes:
- Uses trigram similarity for typo-tolerant matching (e.g., "passowrd" matches "password")
- Falls back to full-text search if trigram search fails
- Only searches published articles
- Results sorted by similarity score
Generate Article Draft
Generate an AI-assisted article draft based on a prompt or ticket context.
Procedure: articles.generateDraft
Authentication: Required
Input:
{
prompt: string; // Minimum 10 characters, describes desired article
ticketId?: string; // Optional ticket UUID for context
}
Example:
curl -X POST "https://your-domain.com/api/trpc/articles.generateDraft" \
-H "Content-Type: application/json" \
-H "Cookie: your-session-cookie" \
-d '{
"json": {
"prompt": "Write a help article explaining how to integrate our API with Zapier",
"ticketId": "ticket-uuid"
}
}'
Response:
{
"result": {
"data": {
"json": {
"title": "Integrating with Zapier",
"content": {
"type": "doc",
"content": [
{
"type": "heading",
"attrs": {"level": 1},
"content": [{"type": "text", "text": "Integrating with Zapier"}]
},
{
"type": "paragraph",
"content": [{"type": "text", "text": "This guide walks you through..."}]
}
]
},
"excerpt": "Learn how to connect your account to Zapier for automated workflows"
}
}
}
}
Notes:
- If
ticketIdis provided, uses ticket subject, description, and AI summary for context - Generated content is a draft - review and edit before publishing
- Subject to AI usage limits
Submit Feedback
Submit reader feedback on an article (helpful/not helpful).
Procedure: articles.submitFeedback
Authentication: None (public endpoint, but records user if authenticated)
Input:
{
articleId: string; // Article UUID
helpful: boolean; // Was the article helpful?
comment?: string; // Optional feedback comment
}
Example:
curl -X POST "https://your-domain.com/api/trpc/articles.submitFeedback" \
-H "Content-Type: application/json" \
-d '{
"json": {
"articleId": "article-uuid",
"helpful": true,
"comment": "This solved my issue, thanks!"
}
}'
Response:
{
"result": {
"data": {
"json": {
"id": "feedback-uuid",
"article_id": "article-uuid",
"helpful": true,
"comment": "This solved my issue, thanks!",
"created_at": "2024-01-15T10:30:00.000Z"
}
}
}
}
Notes:
- Can be submitted anonymously or by authenticated users
- Feedback is linked to user ID if authenticated
Article Versioning
Articles support versioning to track changes over time:
- Each article has a
current_versionnumber - When content is updated, a new version is created in
article_versions - Version history includes:
- Version number
- Title and content at that version
- Change summary
- Author who made the change
- Timestamp
Rate Limits
| Operation | Limit |
|---|---|
| Create article | Rate limited per user |
| Search | 100 per minute |
| Submit feedback | 10 per minute per IP |
Caching
The getBySlug endpoint implements caching for performance:
- Cache duration: 30 minutes
- Cache is automatically invalidated when article is updated
- View counts are tracked separately from cached content
Content Format
Articles use TipTap JSON format for rich text content. Example structure:
{
"type": "doc",
"content": [
{
"type": "heading",
"attrs": {"level": 1},
"content": [{"type": "text", "text": "Article Title"}]
},
{
"type": "paragraph",
"content": [
{"type": "text", "text": "Regular text "},
{"type": "text", "marks": [{"type": "bold"}], "text": "bold text"},
{"type": "text", "text": " and more."}
]
},
{
"type": "bulletList",
"content": [
{
"type": "listItem",
"content": [
{"type": "paragraph", "content": [{"type": "text", "text": "List item 1"}]}
]
}
]
}
]
}
All content is automatically sanitized to prevent XSS attacks.