Creating and publishing articles is a common task in Document360. Using the v3 API you can automate this end to end: create a draft article, then publish a specific version.
Before you begin
You need an API key and four IDs before you start.
| Value | How to retrieve it |
|---|---|
| API key | Create one in Settings › Knowledge base portal › API keys, then send it as the X-API-Key header on every request. See Generating an API key. |
project_id |
GET /v3/projects — copy the id of the project you want to use. |
workspace_id |
GET /v3/projects/{project_id}/workspaces — copy the id of the workspace. |
category_id |
GET /v3/projects/{project_id}/workspaces/{workspace_id}/categories — copy the id of the target category. |
user_id |
GET /v3/projects/{project_id}/users — copy the id of the user the content is created as. Required when authenticating with an API key. |
These examples use https://apihub.document360.io, the default API host. If your project is on a regional or privately hosted deployment, replace it with your own host.
Step 1 - Create the article
Send a POST request to the articles endpoint. The article is created in draft status. This requires the Update articles permission.
POST /v3/projects/{project_id}/articles
curl --request POST "https://apihub.document360.io/v3/projects/{project_id}/articles" \
--header "X-API-Key: YOUR_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"title": "Getting Started with Single Sign-On",
"content": "# Introduction\nThis guide walks you through configuring SSO.",
"category_id": "f4a5b6c7-d8e9-0a1b-2c3d-4e5f6a7b8c9d",
"workspace_id": "1c2d3e4f-5a6b-7c8d-9e0f-a1b2c3d4e5f6",
"user_id": "a1b2c3d4-e5f6-7a8b-9c0d-1e2f3a4b5c6d",
"content_type": "markdown",
"slug": "getting-started-with-single-sign-on"
}'
| Field | Required | Description |
|---|---|---|
title |
Yes | The article title. |
category_id |
Yes | The category the article belongs to. |
workspace_id |
Yes | The workspace the article belongs to. |
user_id |
Yes, with an API key | The user the article is created as. Required when authenticating with X-API-Key, which identifies a token rather than a person. Ignored when using a user access token (OAuth) — the identity comes from the token. |
content |
No | The article body. Markdown when content_type is markdown or omitted; HTML when content_type is block or wysiwyg. |
content_type |
No | The editor format for content: markdown (default), block, or wysiwyg. |
order |
No | Position of the article within the category. Omit, or send 0, to add it at the end of the category. Send 1 or higher to place it at a specific position. The response returns the position actually assigned. |
slug |
No | URL slug. Generated from the title if omitted. |
A successful request returns 201 Created, with a Location header pointing at the new article. Copy data.id and data.version_number — you need them to publish.
{
"success": true,
"request_id": "req_abc123def456",
"data": {
"id": "9a3b4c5d-6e7f-8a9b-0c1d-2e3f4a5b6c7d",
"title": "Getting Started with Single Sign-On",
"category_id": "f4a5b6c7-d8e9-0a1b-2c3d-4e5f6a7b8c9d",
"workspace_id": "1c2d3e4f-5a6b-7c8d-9e0f-a1b2c3d4e5f6",
"version_number": 1,
"public_version": null,
"latest_version": 1,
"status": "draft",
"order": 7,
"slug": "getting-started-with-single-sign-on",
"content_type": "markdown",
"created_at": "2025-08-15T14:30:00Z"
}
}
When content_type is block, content must not be empty — an empty body returns 422.
You must have content access to the target location. If your content role does not grant access to the specified workspace and parent category, the request returns 403 with the error code FORBIDDEN.
If the request fails
| Status | Likely cause |
|---|---|
403 |
Your content role does not grant access to the target workspace and category, or your role lacks the Update articles permission. |
422 |
A required field is missing or invalid. Most common: user_id omitted while using an API key, or content empty while content_type is block. |
429 |
Rate limit exceeded. Retry after the interval given in the Retry-After response header. See Understanding rate limiting. |
Step 2 - Publish the article
Publish a specific version of the article, making it visible to readers. This requires the Publish articles permission.
POST /v3/projects/{project_id}/articles/{article_id}/publish
curl --request POST "https://apihub.document360.io/v3/projects/{project_id}/articles/{article_id}/publish" \
--header "X-API-Key: YOUR_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"workspace_id": "1c2d3e4f-5a6b-7c8d-9e0f-a1b2c3d4e5f6",
"user_id": "a1b2c3d4-e5f6-7a8b-9c0d-1e2f3a4b5c6d",
"version_number": 1,
"message": "Publishing SSO guide after technical review"
}'
| Field | Required | Description |
|---|---|---|
workspace_id |
Yes | The workspace containing the article. |
version_number |
Yes | The version to publish. Must reference an existing draft version of the article. Publishing it supersedes whichever version is currently published. |
user_id |
Yes, with an API key | The user performing the publish. Required when authenticating with X-API-Key. Ignored when using a user access token (OAuth). |
message |
Conditional | A short note describing the publish action. Required when the project's published workflow status is configured to require a comment; optional otherwise. |
A successful publish returns 200 OK:
{
"success": true,
"request_id": "req_abc123def456"
}
If the request fails
| Status | Likely cause |
|---|---|
403 |
Your role lacks the Publish articles permission, or your content role does not grant access to the article. |
404 |
No article with that article_id exists in the project. |
422 |
version_number does not reference an existing draft version, user_id is missing while using an API key, or message is empty in a project that requires a publish comment. |
429 |
Rate limit exceeded. Retry after the interval given in the Retry-After response header. |
To publish many articles at once, see Create and publish multiple articles.
Step 3 - Confirm the article is live
The publish response confirms only that the call was accepted — it returns no article state. Fetch the article to confirm the result.
GET /v3/projects/{project_id}/articles/{article_id}
In the response, check that:
public_versionis no longernulland matches theversion_numberyou published.statusis no longerdraft.
The article is now visible to readers at its slug in the published workspace.