Articles
Search and create knowledge base articles programmatically. Articles can also be managed through the dashboard and are published to your public knowledge base portal.
Which project?
Every article belongs to one project. A key limited to one project implies it — send nothing extra. A key that reaches several projects (the kind you give a coding agent) names the project on each request with the Helmdesk-Project header (slug or id) or ?project=; without it the API answers 400 project.required with the projects it could have meant. Every object in a response carries projectId and projectSlug, so you can always tell what you are looking at.
curl https://helmdesk.dev/api/v1/articles/search?q=export \
-H "Authorization: Bearer sk_live_..." \
-H "Helmdesk-Project: ledgerly"// Pin the project once — or set HELMDESK_PROJECT and omit it.
const helmdesk = new HelmdeskClient({ apiKey, project: 'ledgerly' })
await helmdesk.articles.search('export')See Authentication for how keys and projects fit together.
/api/v1/articles/searchSearch published knowledge base articles by keyword and optionally filter by category.
Request
const results = await helmdesk.articles.search({
q: 'reset password',
category: 'getting-started',
})/api/v1/articlesCreate a knowledge-base article. The slug is auto-generated from the title when omitted. Defaults to a draft; pass status 'published' to make it live (published articles are indexed for search). Requires the articles:write scope.
Request
const article = await helmdesk.articles.create({
title: 'How to reset your password',
body: '1. Open Settings...\n2. Click "Reset password"...',
status: 'published',
})/api/v1/articles/:idGet a single article by id, including its full markdown body. Requires the articles:read scope.
Request
const article = await helmdesk.articles.get('article-uuid')
// article.body -> full markdown/api/v1/articles/:idUpdate an article's content, category, or status. Publishing for the first time stamps publishedAt and indexes the article for search. Changing the slug to one that already exists returns a 409 conflict. Requires the articles:write scope.
Request
await helmdesk.articles.update('article-uuid', {
body: 'Revised steps...',
status: 'published',
})/api/v1/article-categoriesList the project's article categories — the valid categoryId values for create and update. Requires the articles:read scope.
Request
const { categories } = await helmdesk.articles.categories()Managing the knowledge base
Search only sees what is published. The management endpoints see everything in the request's environment — drafts included — and let you organise and remove articles through the same code path the dashboard uses.
/api/v1/articlesarticles:readList the project's articles, newest-updated first, drafts included. Filter by status (draft | published), categoryId, or a title/slug substring; page and limit (max 100). Rows carry no body — GET /articles/:id has it.
Request
// SDK
const { articles, total } = await helmdesk.articles.list({ status: 'draft', limit: 50 })
// curl
curl "https://helmdesk.dev/api/v1/articles?status=draft&limit=50" \
-H "Authorization: Bearer sk_live_..." \
-H "Helmdesk-Project: abc-salon"Response
{
"articles": [
{
"id": "9c1f2e3d-4a5b-4c6d-8e7f-0a1b2c3d4e5f",
"projectId": "7f3a9c2e-4b1d-4e8f-a6c5-2d9b8e7f1a30",
"projectSlug": "abc-salon",
"title": "How to reset your password",
"slug": "how-to-reset-your-password",
"status": "draft",
"excerpt": null,
"categoryId": null,
"helpfulYes": 0,
"helpfulNo": 0,
"publishedAt": null,
"createdAt": "2026-09-09T10:00:00.000Z",
"updatedAt": "2026-09-09T10:00:00.000Z"
}
],
"total": 1,
"page": 1,
"limit": 50
}/api/v1/article-categoriesarticles:writeCreate a category. The slug is derived from the name when omitted; a slug already used in the project + environment is a 409.
Request
// SDK
const category = await helmdesk.articles.createCategory({
name: 'Getting started',
description: 'First steps in the app',
})
// curl
curl -X POST https://helmdesk.dev/api/v1/article-categories \
-H "Authorization: Bearer sk_live_..." \
-H "Helmdesk-Project: abc-salon" \
-H "Content-Type: application/json" \
-d '{"name":"Getting started","description":"First steps in the app"}'Response
{
"id": "5d6e7f80-9a1b-4c2d-8e3f-4a5b6c7d8e9f",
"name": "Getting started",
"slug": "getting-started",
"description": "First steps in the app",
"sortOrder": 0,
"projectId": "7f3a9c2e-4b1d-4e8f-a6c5-2d9b8e7f1a30",
"projectSlug": "abc-salon"
}/api/v1/articles/:idarticles:writePermanently delete an article. It disappears from the public help centre and from search at once; images it referenced from the article-images bucket are removed and their bytes released. To unpublish without losing it, PATCH status to draft instead.
Request
// SDK
await helmdesk.articles.delete('article-uuid')
// curl
curl -X DELETE https://helmdesk.dev/api/v1/articles/article-uuid \
-H "Authorization: Bearer sk_live_..." \
-H "Helmdesk-Project: abc-salon"Response
{
"deleted": true,
"id": "9c1f2e3d-4a5b-4c6d-8e7f-0a1b2c3d4e5f",
"imagesRemoved": 0,
"projectId": "7f3a9c2e-4b1d-4e8f-a6c5-2d9b8e7f1a30",
"projectSlug": "abc-salon"
}Public knowledge base
Published articles are automatically available at your project's public portal: helmdesk.dev/p/your-slug/articles. No API key is required to view published articles through the portal.