> ## Documentation Index > Fetch the complete documentation index at: https://apidocs.document360.com/llms.txt > Use this file to discover all available pages before exploring further. # Get an article version > Retrieves the content for a specific historical version of the article. Use `GET /v3/projects/{projectId}/articles/{articleId}/versions` to list available version numbers. For private or mixed-visibility projects, SAS tokens are appended to media URLs in the content by default. Returns `404` if the article or version number does not exist. ## OpenAPI ````json GET /v3/projects/{project_id}/articles/{article_id}/versions/{version_number} { "openapi": "3.0.1", "info": { "title": "Document360 Customer API", "description": "> **⚠️ Beta:** Version 3 of the Document360 Customer API is currently in **Beta**. The contract (routes, request/response field names, status codes) may change without notice prior to GA. Pin to a specific revision and review release notes before upgrading.\n\nDocument360 RESTful APIs let you integrate your documentation with your software — onboard readers, manage articles, automate publishing, and more.\n\nFull reference: [API Documentation](https://apidocs.document360.io/docs).\n\n## Authentication\nV3 authenticates with an **API key** — not the `api_token` used by V1/V2. Create one in the Document360 portal under **Settings → Knowledge base portal → API keys**, then click **Create API key**. (Projects that still have the older screen show two tabs; choose **Enhanced keys (v3)**, or pick **API v3** from the Create menu.)\n\nSend it in the `X-API-Key` header:\n\n```\nX-API-Key: d360_sk_...\n```\n\nThe plaintext key is shown **once**, at creation — only its hash is stored, so a lost key must be replaced rather than recovered. Each key carries a fixed portal role, content role and content-access scope, supports an optional expiry, and can be disabled or deleted at any time from the same screen. Treat it as an opaque string: it is a pre-shared secret, not an OAuth 2.0 access token, and must not be parsed.\n\nFor flows that act on behalf of a specific person, V3 also accepts an OAuth 2.0 bearer token carrying the `customerApi` scope.\n\nAPI access is part of your subscription plan. If your plan does not include it, every endpoint returns `403` with the error code `FEATURE_NOT_IN_LICENSE` — including for keys created while an earlier plan was active. Contact your Customer Success Manager or `support@document360.com` to enable it.\n\n> **Note on terminology:** V1/V2 call these *API tokens* and manage them under **Settings → Knowledge base portal → API tokens**. V3 keys are a separate credential with their own screen, roles and scope — a V1/V2 token will not authenticate a V3 request.\n\n## Rate Limits\nAll endpoints are rate-limited per API key per project. Default limits vary by plan. When rate-limited, responses include `Retry-After`, `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Reset` headers. Use exponential backoff with jitter for optimal retry behavior.", "termsOfService": "https://document360.com/terms", "contact": { "name": "Document360 Support", "url": "https://document360.io/contact-us/", "email": "support@document360.com" }, "license": { "name": "Document360 API Terms of Use", "url": "https://document360.com/terms" }, "version": "3.0.0" }, "servers": [ { "url": "https://apihub.document360.io", "description": "Document 360 API Hub" }, { "url": "https://apihub.us.document360.io", "description": "Document360 API Hub - US data center" }, { "url": "https://apihub.{private_hosting}.document360.io", "description": "Private hosting - Please provide the subdomain name.", "variables": { "private_hosting": { "default": "domain", "description": "Sub domain for private hosting" } } } ], "security": [ { "ApiKey": [] }, { "Bearer": [ "customerApi" ] } ], "tags": [ { "name": "Projects", "description": "List and manage knowledge base projects. Export and import project documentation, and manage project-level site customization such as custom CSS and JavaScript." }, { "name": "Projects > Import & export", "description": "Start a project export or import and poll the resulting background operation for completion." }, { "name": "Workspaces", "description": "Manage workspaces and access workspace-scoped categories and articles." }, { "name": "Workspaces > AI", "description": "Query the workspace with Eddy AI and submit feedback on AI answers." }, { "name": "Articles", "description": "Create, read, update, and delete knowledge base articles and their settings, including bulk operations." }, { "name": "Articles > Publishing & workflow", "description": "Publish and unpublish articles (single and bulk) and update the article workflow status." }, { "name": "Articles > Versions", "description": "List, fork, and delete article versions." }, { "name": "Articles > Attachments", "description": "Manage the files attached to an article — list, upload, and delete article attachments." }, { "name": "Articles > Content drafts", "description": "(Internal) Stage AI-generated article content with an Accept/Reject review lifecycle — used by Eddy Copilot to preview content before committing to the live article body." }, { "name": "Articles > Labels", "description": "Read and set the labels associated with an article." }, { "name": "Categories", "description": "Manage the category hierarchy that organizes articles. Create, update, and delete categories and their settings, including bulk operations." }, { "name": "Categories > Page category", "description": "Read and update the content body of page-type categories, including bulk content updates." }, { "name": "Categories > Publishing & workflow", "description": "Publish and unpublish categories (single and bulk) and update the category workflow status." }, { "name": "Categories > Versions", "description": "List, fork, and delete category versions." }, { "name": "Categories > Labels", "description": "Read and set the labels associated with a category." }, { "name": "ArticleTemplates", "description": "Manage reusable article templates — per-language article skeletons that authors and AI tools (such as Eddy Copilot) can apply when starting a new article.", "x-displayName": "Article templates" }, { "name": "Content reuse > Glossaries", "description": "Manage glossary entries — terminology definitions referenced inside articles via merge codes (`{{glossary.name}}`) and rendered as tooltips on the public KB." }, { "name": "Content reuse > Snippets", "description": "Manage reusable snippets — markdown or WYSIWYG content fragments referenced across articles via merge codes (`{{snippet.name}}`)." }, { "name": "Content reuse > Variables", "description": "Manage reusable variables — short text values referenced across articles via merge codes (`{{variable.name}}`)." }, { "name": "AiWriterStyleGuides", "description": "Retrieve AI writer style guides configured for the project — voice / tone instructions Eddy Copilot follows when generating article content. Used to let users pick a style before kicking off generation.", "x-displayName": "AI writer style guides" }, { "name": "RedirectRules", "description": "Manage article-redirection rules — 301/302 redirects from old article URLs to new locations after renames or restructures.", "x-displayName": "Redirect rules" }, { "name": "Tags", "description": "Manage tags — labels used to classify articles, categories, and files for filtering and discovery." }, { "name": "Labels", "description": "Manage labels shown on the article list and category tree. (Associating labels with a specific article or category lives under Articles and Categories.)" }, { "name": "CustomFields", "description": "Retrieve the custom field definitions configured for the project. Custom field values are read and written through the article and category settings endpoints.", "x-displayName": "Custom fields" }, { "name": "ApiReferences", "description": "Import, resync, and publish OpenAPI/Swagger specifications for API reference documentation.", "x-displayName": "API references" }, { "name": "ApiReferences > Logs", "description": "Monitor API reference import logs and inspect individual log entries." }, { "name": "Drive", "description": "Search Drive and retrieve files associated with an article, and track Drive background tasks." }, { "name": "Drive > Folders", "description": "Create, read, update, and delete Drive folders." }, { "name": "Drive > Files", "description": "Upload, copy, move, delete, and tag Drive files." }, { "name": "Drive > Image drafts", "description": "(Internal) Stage uploaded or AI-generated images (committed to Drive and associated with a staged article draft) — used by Eddy Copilot." }, { "name": "Readers", "description": "Manage reader accounts, invitations, and access scopes for private documentation." }, { "name": "Readers > Groups", "description": "Create, read, update, and delete reader groups." }, { "name": "Users", "description": "Manage users, their portal and content roles, and consolidated (effective) permissions within a project." }, { "name": "Users > Groups", "description": "Manage user groups, their portal role, and consolidated (effective) group permissions." }, { "name": "Roles", "description": "Create, read, update, and delete portal and content roles, list the users assigned to a role, and retrieve the permission dependency matrix." }, { "name": "ContentAccess", "description": "Manage per-node content-access permissions — grant, allow, deny, and inheritance overrides for users and groups against specific versions, languages, categories, or articles, plus version/language site protection.", "x-displayName": "Content access" }, { "name": "ContentAccess > Eligibility", "description": "List the readers and groups eligible to be granted content access." }, { "name": "Languages", "description": "Retrieve configured languages for a workspace." }, { "name": "Translations", "description": "Query translation status of articles across languages." }, { "name": "Operations", "description": "Track asynchronous operations — long-running tasks (bulk updates, merges, exports) accepted with `202 Accepted` and an `Operation-Location` header. Poll until the operation reaches a terminal status, honouring the `Retry-After` header." }, { "name": "Analytics > Articles", "description": "View article performance metrics including views, top articles, reader locations, and category breakdowns." }, { "name": "Analytics > Search", "description": "View search usage metrics including top keywords, no-result queries, and bounced searches." }, { "name": "Analytics > AI search", "description": "View AI-powered search metrics including usage trends, most-referenced articles, and trending topics." }, { "name": "Analytics > Feedback", "description": "View reader feedback trends across articles, including top-performing articles and feedback keywords." } ], "externalDocs": { "description": "Document360 API Documentation", "url": "https://apidocs.document360.io/docs" }, "x-tagGroups": [ { "name": "Workspace", "tags": [ "Projects", "Projects > Import & export", "Workspaces", "Workspaces > AI" ] }, { "name": "Content", "tags": [ "Articles", "Articles > Publishing & workflow", "Articles > Versions", "Articles > Attachments", "Articles > Content drafts", "Articles > Labels", "Categories", "Categories > Page category", "Categories > Publishing & workflow", "Categories > Versions", "Categories > Labels", "ArticleTemplates", "AiWriterStyleGuides", "RedirectRules", "Tags", "Labels", "ApiReferences", "ApiReferences > Logs" ] }, { "name": "Content reuse", "tags": [ "Content reuse > Glossaries", "Content reuse > Snippets", "Content reuse > Variables" ] }, { "name": "Media", "tags": [ "Drive", "Drive > Folders", "Drive > Files", "Drive > Image drafts" ] }, { "name": "Access", "tags": [ "Readers", "Readers > Groups", "Users", "Users > Groups", "Roles", "ContentAccess", "ContentAccess > Eligibility" ] }, { "name": "Localization", "tags": [ "Languages", "Translations" ] }, { "name": "Operations", "tags": [ "Operations" ] }, { "name": "Analytics", "tags": [ "Analytics > Articles", "Analytics > Search", "Analytics > AI search", "Analytics > Feedback" ] } ], "paths": { "/v3/projects/{project_id}/articles/{article_id}/versions/{version_number}": { "get": { "tags": [ "Articles > Versions" ], "summary": "Get an article version.", "description": "Retrieves the content for a specific historical version of the article. Use `GET /v3/projects/{projectId}/articles/{articleId}/versions`\r\nto list available version numbers. For private or mixed-visibility projects, SAS tokens are appended to media URLs in the content by default.\r\nReturns `404` if the article or version number does not exist.", "operationId": "getArticleVersion", "parameters": [ { "$ref": "#/components/parameters/ProjectId" }, { "$ref": "#/components/parameters/ArticleId" }, { "$ref": "#/components/parameters/VersionNumber" }, { "$ref": "#/components/parameters/LangCode" }, { "name": "content_mode", "in": "query", "description": "Controls how content is processed in the response. Defaults to `raw`.\n\n**raw** — Returns content as stored in the knowledge base. Snippets, Variables, and Glossary terms remain as their placeholder tokens (e.g., `{{snippet:intro}}`, `{{variable:productName}}`). SAS tokens are appended to media URLs for private/mixed-visibility projects. Internal notes are preserved.\n*Use when:* building an authoring UI, running a GET-then-PUT round trip to edit an article, migrating content between projects, diffing two versions, or syncing source-of-truth content to an external system.\n\n**display** — Returns fully rendered content ready for end-user consumption. Snippets, Variables, and Glossary terms are resolved inline into HTML, SAS tokens are appended to media URLs, and internal notes are removed.\n*Use when:* rendering articles on a public site, in-app reader, chatbot answer, email digest, or any read-only surface where the reader should never see unresolved placeholders or internal notes.\n\n**Warning:** never feed `display` output back into a create/update call. Snippet, Variable, and Glossary references are expanded into literal inline HTML, so saving the response as new content destroys the links to those reusable components in your source article.", "schema": { "enum": [ "raw", "display" ], "type": "string", "allOf": [ { "$ref": "#/components/schemas/ContentMode" } ], "description": "Controls how article/category content is processed in the response.", "default": "raw", "example": "display", "x-enumNames": [ "Raw", "Display" ], "x-enum-varnames": [ "Raw", "Display" ], "x-ms-enum": { "name": "ContentMode", "modelAsString": true } }, "example": "display" } ], "responses": { "200": { "description": "Article version retrieved successfully.", "headers": { "X-RateLimit-Limit": { "description": "The maximum number of requests allowed in the current time window for this request's bucket. Read requests (GET/HEAD) and write requests (POST/PUT/PATCH/DELETE) have independent limits, applied per caller (API key or user) per project.", "schema": { "type": "integer", "format": "int32" } }, "X-RateLimit-Remaining": { "description": "The number of requests remaining in the current time window. When this reaches 0, subsequent requests receive a 429 response.", "schema": { "type": "integer", "format": "int32" } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ArticleDetailResponseApiResponse" }, "examples": { "Article retrieved successfully": { "summary": "Returns the latest version of the article with full content, authors, and available languages.", "value": { "data": { "id": "9a3b4c5d-6e7f-8a9b-0c1d-2e3f4a5b6c7d", "title": "Getting Started with Single Sign-On", "content": "# Introduction\nThis guide walks you through configuring SSO for your organization.\n\n## Prerequisites\n- An active Document360 project\n- Admin access to your identity provider", "html_content": "

Introduction

This guide walks you through configuring SSO for your organization.

Prerequisites

", "category_id": "f4a5b6c7-d8e9-0a1b-2c3d-4e5f6a7b8c9d", "workspace_id": "1c2d3e4f-5a6b-7c8d-9e0f-a1b2c3d4e5f6", "version_number": 3, "public_version": 2, "latest_version": 3, "enable_rtl": false, "hidden": false, "status": "draft", "version_type": null, "order": 0, "created_by": "a1b2c3d4-e5f6-7a8b-9c0d-1e2f3a4b5c6d", "authors": [ { "id": "a1b2c3d4-e5f6-7a8b-9c0d-1e2f3a4b5c6d", "first_name": "Jane", "last_name": "Doe", "email": "jane.doe@example.com", "profile_logo_url": "https://cdn.example.com/avatars/jane-doe.png" } ], "created_at": "2025-06-01T09:00:00Z", "modified_at": "2025-08-15T14:30:00Z", "modified_by": "a1b2c3d4-e5f6-7a8b-9c0d-1e2f3a4b5c6d", "slug": "getting-started-with-single-sign-on", "is_fallback_content": false, "description": "Learn how to configure single sign-on authentication for your knowledge base.", "category_type": "folder", "content_type": "markdown", "is_shared_article": false, "translation_option": "none", "url": "https://docs.example.com/en/articles/getting-started-with-single-sign-on", "preview_url": null, "current_workflow_status_id": "b7e2a1d4-3f56-4c89-9d0e-1a2b3c4d5e6f", "lang_code": "en", "available_languages": [ { "lang_code": "fr", "url": "https://docs.example.com/fr/articles/getting-started-with-single-sign-on", "translation_status": "translated" } ], "settings": { "seo_title": "SSO Setup Guide - Product Documentation", "description": "Step-by-step instructions for configuring single sign-on with SAML or OIDC providers.", "exclude_from_external_search": false }, "stale_status": { "article_stale_status": "stale", "stale_reason": "Scheduled review reminder reached", "expired_at": "2026-01-31T05:10:26Z", "is_from_document_settings": false, "expire_days": 0 }, "content_hash": "sha256:9f2c5a1d8e3b4c6f7a0918273645dacb5e1f2a3b4c5d6e7f8091a2b3c4d5e6f7", "custom_fields_data": { "Reviewer": "Jane Doe", "Audience": "Internal, Beta customers", "Review due": null } }, "success": true, "request_id": "req_abc123def456", "errors": null, "warnings": null } } } } } }, "401": { "description": "Authentication token is missing or invalid.", "headers": { "WWW-Authenticate": { "description": "Indicates the authentication scheme required. Returns `Bearer` with optional `error` and `error_description` parameters per RFC 6750.", "schema": { "type": "string" } } }, "content": { "application/problem+json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/V3ProblemDetails" }, { "type": "object", "properties": { "type": { "enum": [ "https://apidocs.document360.io/apidocs/errors/unauthorized" ], "type": "string", "description": "RFC 7807 error type URI. Always `https://apidocs.document360.io/apidocs/errors/unauthorized` for 401 responses." }, "status": { "enum": [ 401 ], "type": "integer", "description": "HTTP status code. Always `401` for this response.", "format": "int32" } } } ] }, "examples": { "Missing or invalid token": { "summary": "Authentication token is missing or invalid.", "value": { "type": "https://apidocs.document360.io/apidocs/errors/unauthorized", "title": "Unauthorized.", "status": 401, "detail": "The authentication token is missing or has expired.", "instance": null, "trace_id": "req_abc123def456", "errors": [ { "code": "UNAUTHORIZED", "message": "Bearer token is missing or invalid.", "field": null, "details": null } ], "warnings": null } } } } } }, "404": { "description": "Article or version not found.", "content": { "application/problem+json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/V3ProblemDetails" }, { "type": "object", "properties": { "type": { "enum": [ "https://apidocs.document360.io/apidocs/errors/resource-not-found" ], "type": "string", "description": "RFC 7807 error type URI. Always `https://apidocs.document360.io/apidocs/errors/resource-not-found` for 404 responses." }, "status": { "enum": [ 404 ], "type": "integer", "description": "HTTP status code. Always `404` for this response.", "format": "int32" } } } ] }, "examples": { "Resource not found": { "summary": "The requested resource was not found.", "value": { "type": "https://apidocs.document360.io/apidocs/errors/resource-not-found", "title": "Not Found.", "status": 404, "detail": "The requested resource does not exist or has been deleted.", "instance": null, "trace_id": "req_abc123def456", "errors": [ { "code": "RESOURCE_NOT_FOUND", "message": "The requested resource was not found.", "field": null, "details": null } ], "warnings": null } } } } } }, "429": { "description": "Rate limit exceeded. Retry after the duration specified in the Retry-After header.", "headers": { "Retry-After": { "description": "Number of seconds to wait before retrying the request. Use exponential backoff with jitter for optimal retry behavior.", "schema": { "type": "integer", "format": "int32" } }, "X-RateLimit-Limit": { "description": "The maximum number of requests allowed in the current time window for this request's bucket. Read requests (GET/HEAD) and write requests (POST/PUT/PATCH/DELETE) have independent limits, applied per caller (API key or user) per project. Read limits are typically higher than write limits.", "schema": { "type": "integer", "format": "int32" } }, "X-RateLimit-Remaining": { "description": "The number of requests remaining in the current time window. When this reaches 0, subsequent requests will receive a 429 response.", "schema": { "type": "integer", "format": "int32" } }, "X-RateLimit-Reset": { "description": "The UTC epoch timestamp (in seconds) when the current rate limit window resets.", "schema": { "type": "integer", "format": "int64" } } }, "content": { "application/problem+json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/V3ProblemDetails" }, { "type": "object", "properties": { "type": { "enum": [ "https://apidocs.document360.io/apidocs/errors/too-many-requests" ], "type": "string", "description": "RFC 7807 error type URI. Always `https://apidocs.document360.io/apidocs/errors/too-many-requests` for 429 responses." }, "status": { "enum": [ 429 ], "type": "integer", "description": "HTTP status code. Always `429` for this response.", "format": "int32" } } } ] }, "examples": { "Rate limit exceeded": { "summary": "Rate limit exceeded.", "value": { "type": "https://apidocs.document360.io/apidocs/errors/too-many-requests", "title": "Too Many Requests.", "status": 429, "detail": "Rate limit exceeded. Retry after the duration specified in the Retry-After header.", "instance": null, "trace_id": "req_abc123def456", "errors": [ { "code": "TOO_MANY_REQUESTS", "message": "Rate limit exceeded. Retry after the duration specified in the Retry-After header.", "field": null, "details": null } ], "warnings": null } } } } } }, "500": { "description": "An unexpected server error occurred.", "content": { "application/problem+json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/V3ProblemDetails" }, { "type": "object", "properties": { "type": { "enum": [ "https://apidocs.document360.io/apidocs/errors/internal-server-error" ], "type": "string", "description": "RFC 7807 error type URI. Always `https://apidocs.document360.io/apidocs/errors/internal-server-error` for 500 responses." }, "status": { "enum": [ 500 ], "type": "integer", "description": "HTTP status code. Always `500` for this response.", "format": "int32" } } } ] }, "examples": { "Unexpected server error": { "summary": "Unexpected server error.", "value": { "type": "https://apidocs.document360.io/apidocs/errors/internal-server-error", "title": "Internal Server Error.", "status": 500, "detail": "An unexpected error occurred. Please try again or contact support.", "instance": null, "trace_id": "req_abc123def456", "errors": [ { "code": "INTERNAL_SERVER_ERROR", "message": "An unexpected error occurred.", "field": null, "details": null } ], "warnings": null } } } } } } }, "security": [ { "ApiKey": [] }, { "Bearer": [ "customerApi" ] } ] } } }, "components": { "parameters": { "ProjectId": { "name": "project_id", "in": "path", "description": "The unique identifier of the project. Retrieve project IDs from `GET /v3/projects`.", "required": true, "schema": { "type": "string", "format": "uuid", "example": "9a3b4c5d-6e7f-8a9b-0c1d-2e3f4a5b6c7d" } }, "ArticleId": { "name": "article_id", "in": "path", "description": "The unique identifier of the article. Retrieve article IDs from `GET /v3/projects/{projectId}/articles`.", "required": true, "schema": { "type": "string", "format": "uuid", "example": "9a3b4c5d-6e7f-8a9b-0c1d-2e3f4a5b6c7d" } }, "VersionNumber": { "name": "version_number", "in": "path", "description": "The version number of the article or category. Version numbers start at 1.", "required": true, "schema": { "minimum": 1, "type": "integer", "format": "int32", "example": 1 } }, "LangCode": { "name": "lang_code", "in": "query", "description": "ISO 639-1 language code (e.g., `en`, `fr`). Defaults to the project's primary language if omitted.", "schema": { "pattern": "^[a-z]{2}(-[A-Z]{2})?$", "type": "string", "format": "language-tag", "example": "en" } } }, "schemas": { "ContentMode": { "enum": [ "raw", "display" ], "type": "string", "description": "Controls how article/category content is processed in the response.", "x-enumNames": [ "Raw", "Display" ], "x-enum-varnames": [ "Raw", "Display" ], "x-ms-enum": { "name": "ContentMode", "modelAsString": true } }, "ArticleDetailResponseApiResponse": { "required": [ "data", "request_id", "success" ], "type": "object", "properties": { "data": { "allOf": [ { "$ref": "#/components/schemas/ArticleDetailResponse" } ], "description": "Response data payload." }, "success": { "type": "boolean", "description": "Whether the API request was successful.", "readOnly": true }, "request_id": { "minLength": 1, "type": "string", "description": "Unique identifier for request tracing and correlation.", "readOnly": true }, "errors": { "type": "array", "items": { "$ref": "#/components/schemas/ApiError" }, "description": "List of errors if the request failed.", "nullable": true }, "warnings": { "type": "array", "items": { "$ref": "#/components/schemas/ApiWarning" }, "description": "List of non-fatal warnings from the request.", "nullable": true } }, "additionalProperties": false, "description": "Generic API response wrapper containing typed data." }, "V3ProblemDetails": { "required": [ "status", "title", "type" ], "type": "object", "properties": { "type": { "minLength": 1, "enum": [ "https://apidocs.document360.io/apidocs/errors/bad-request", "https://apidocs.document360.io/apidocs/errors/unauthorized", "https://apidocs.document360.io/apidocs/errors/forbidden", "https://apidocs.document360.io/apidocs/errors/resource-not-found", "https://apidocs.document360.io/apidocs/errors/conflict", "https://apidocs.document360.io/apidocs/errors/validation-error", "https://apidocs.document360.io/apidocs/errors/too-many-requests", "https://apidocs.document360.io/apidocs/errors/internal-server-error" ], "type": "string", "description": "URI reference identifying the error type (links to documentation)." }, "title": { "minLength": 1, "type": "string", "description": "Short human-readable summary of the error type." }, "status": { "enum": [ 400, 401, 403, 404, 409, 422, 429, 500 ], "type": "integer", "description": "HTTP status code.", "format": "int32" }, "detail": { "type": "string", "description": "Human-readable explanation specific to this occurrence.", "nullable": true }, "instance": { "type": "string", "description": "URI of the request that generated the error.", "nullable": true }, "trace_id": { "type": "string", "description": "Request trace identifier for correlation.", "nullable": true }, "errors": { "type": "array", "items": { "$ref": "#/components/schemas/ApiError" }, "description": "Structured list of specific errors (extension field).", "nullable": true }, "warnings": { "type": "array", "items": { "$ref": "#/components/schemas/ApiWarning" }, "description": "Non-fatal warnings (extension field).", "nullable": true } }, "additionalProperties": false, "description": "RFC 7807 Problem Details response for V3 API errors.\r\nContent-Type: application/problem+json" }, "ArticleDetailResponse": { "required": [ "created_at", "enable_rtl", "hidden", "id", "is_fallback_content", "is_shared_article", "latest_version", "modified_at", "order", "status", "title", "version_number" ], "type": "object", "properties": { "id": { "type": "string", "description": "The unique identifier of the article.", "format": "uuid", "nullable": true, "readOnly": true, "example": "9a3b4c5d-6e7f-8a9b-0c1d-2e3f4a5b6c7d" }, "title": { "type": "string", "description": "The title of the article.", "nullable": true, "example": "Getting Started with Single Sign-On" }, "content": { "type": "string", "description": "The raw content of the article in its source format.", "nullable": true, "example": "# Introduction\\nThis guide walks you through configuring SSO for your organization." }, "html_content": { "type": "string", "description": "The rendered HTML content of the article.", "nullable": true, "example": "

Introduction

This guide walks you through configuring SSO.

" }, "category_id": { "type": "string", "description": "The identifier of the category this article belongs to. Use this value with `GET /v3/projects/{projectId}/categories/{categoryId}` to retrieve category details.", "nullable": true, "example": "f4a5b6c7-d8e9-0a1b-2c3d-4e5f6a7b8c9d" }, "workspace_id": { "type": "string", "description": "The workspace this article belongs to. Corresponds to a workspace from `GET /v3/projects/{projectId}/workspaces`.", "nullable": true, "example": "1c2d3e4f-5a6b-7c8d-9e0f-a1b2c3d4e5f6" }, "version_number": { "type": "integer", "description": "The current version number of the article.", "format": "int32", "example": 3 }, "public_version": { "type": "integer", "description": "The latest published version number, or null if the article has never been published.", "format": "int32", "nullable": true, "readOnly": true, "example": 2 }, "latest_version": { "type": "integer", "description": "The latest version number including drafts.", "format": "int32", "readOnly": true, "example": 3 }, "enable_rtl": { "type": "boolean", "description": "Whether right-to-left text direction is enabled.", "example": false }, "hidden": { "type": "boolean", "description": "Whether the article is hidden from readers.", "example": false }, "status": { "enum": [ "draft", "published", "unpublished" ], "type": "string", "allOf": [ { "$ref": "#/components/schemas/ArticleStatus" } ], "description": "The publication status of the article.", "x-enumNames": [ "Draft", "Published", "Unpublished" ], "x-enum-varnames": [ "Draft", "Published", "Unpublished" ], "x-ms-enum": { "name": "ArticleStatus", "modelAsString": true } }, "version_type": { "type": "string", "description": "Derived version discriminator (version-less collab): `draft`, `published`, or `system_backup`. Null when collaborative editing is not enabled for the project. Display/system-backup ordinals are exposed only by the versions-list endpoint (they are relative to the full version set).", "nullable": true, "readOnly": true, "example": "draft" }, "order": { "type": "integer", "description": "The display order of the article within its category.", "format": "int32", "example": 5 }, "created_by": { "type": "string", "description": "The user ID of the original article creator. For full author details including name and avatar, see the `authors` array. Corresponds to a user from `GET /v3/projects/{projectId}/users`.", "nullable": true, "example": "a1b2c3d4-e5f6-7a8b-9c0d-1e2f3a4b5c6d" }, "authors": { "type": "array", "items": { "$ref": "#/components/schemas/AuthorResponse" }, "description": "The list of contributors to this article, including the original creator and any subsequent editors.", "nullable": true }, "created_at": { "type": "string", "description": "The date and time the article was created.", "format": "date-time", "readOnly": true, "example": "2025-06-01T09:00:00Z" }, "modified_at": { "type": "string", "description": "The date and time the article was last modified.", "format": "date-time", "readOnly": true, "example": "2025-08-15T14:30:00Z" }, "modified_by": { "type": "string", "description": "The user ID of who last modified this article. Corresponds to a user from `GET /v3/projects/{projectId}/users`.", "nullable": true, "readOnly": true, "example": "b2c3d4e5-f6a7-8b9c-0d1e-2f3a4b5c6d7e" }, "slug": { "type": "string", "description": "The URL slug for the article.", "nullable": true, "readOnly": true, "example": "getting-started-with-single-sign-on" }, "is_fallback_content": { "type": "boolean", "description": "Whether the content is a fallback from the default language.", "example": false }, "description": { "type": "string", "description": "A brief description of the article.", "nullable": true, "example": "Learn how to configure single sign-on authentication for your knowledge base." }, "category_type": { "allOf": [ { "$ref": "#/components/schemas/CategoryType" } ], "description": "The type of category this article belongs to.", "nullable": true }, "content_type": { "allOf": [ { "$ref": "#/components/schemas/ContentType" } ], "description": "The editor content type of the article.", "nullable": true }, "is_shared_article": { "type": "boolean", "description": "Whether the article is shared across multiple projects.", "example": false }, "translation_option": { "enum": [ "none", "needTranslation", "translated", "inProgress" ], "type": "string", "allOf": [ { "$ref": "#/components/schemas/TranslationOption" } ], "description": "The translation status of the article.", "x-enumNames": [ "None", "NeedTranslation", "Translated", "InProgress" ], "x-enum-varnames": [ "None", "NeedTranslation", "Translated", "InProgress" ], "x-ms-enum": { "name": "TranslationOption", "modelAsString": true } }, "url": { "type": "string", "description": "Canonical public URL of the article on the knowledge base site. Deterministic from the slug\r\nand always returned, but only resolves to live content once the article is published; a\r\ndraft-only article returns 404 (or redirects to login) at this URL until first publish.\r\nUse `preview_url` to view unpublished content.", "format": "uri", "nullable": true, "example": "https://docs.example.com/v1/docs/en/getting-started-with-single-sign-on" }, "preview_url": { "type": "string", "description": "Preview URL for the current version of the article on the knowledge base site. Works before\r\npublishing; anonymous readers are redirected to login. For an already-published article it\r\nrenders the requested version's content. Empty for legacy KB v1 projects.", "nullable": true, "example": "https://docs.example.com/v1/docs/en/9a3b4c5d-6e7f-8a9b-0c1d-2e3f4a5b6c7d?isPreview=true&versionNumber=3" }, "current_workflow_status_id": { "type": "string", "description": "The current workflow status identifier. Retrieve available statuses from `GET /v3/projects/{projectId}/workflow-statuses`.", "nullable": true, "example": "b7e2a1d4-3f56-4c89-9d0e-1a2b3c4d5e6f" }, "lang_code": { "type": "string", "description": "The language code of this article version.", "nullable": true, "example": "en" }, "available_languages": { "type": "array", "items": { "$ref": "#/components/schemas/AvailableLanguage" }, "description": "The list of languages this article is available in.", "nullable": true }, "settings": { "allOf": [ { "$ref": "#/components/schemas/ArticleDocumentSettings" } ], "description": "A subset of article settings (SEO title, description, external search exclusion). For full settings including tags, related articles, and display options, use `GET /v3/projects/{projectId}/articles/{articleId}/settings`.", "nullable": true }, "stale_status": { "allOf": [ { "$ref": "#/components/schemas/StaleStatusResponse" } ], "description": "The content freshness status of the article: whether it is up to date or due for review, along with the review schedule. Mirrors the `stale_status` exposed by the category endpoints.", "nullable": true }, "content_hash": { "type": "string", "description": "SHA-256 hash of this version's stored content, prefixed with the algorithm\r\n(`sha256:`). Changes only when the content itself changes — record it at write\r\ntime and compare against listing or detail reads to detect drift without downloading\r\ncontent. `null` for versions saved before hash tracking was introduced.", "nullable": true, "readOnly": true, "example": "sha256:9f2c5a1d8e3b4c6f7a0918273645dacb5e1f2a3b4c5d6e7f8091a2b3c4d5e6f7" }, "custom_fields_data": { "type": "object", "additionalProperties": { "nullable": true }, "description": "Read-only map of custom field name → display value for this article (dropdown /\r\nmulti-select values are resolved to option labels; unset fields are `null`).\r\nPopulated on the single-article and article-version GET endpoints only. Named to match the\r\nV1/V2 `customFieldsData` map, and kept distinct from the `custom_fields` array on\r\nthe settings endpoints, which is where raw values are read and written.\r\nAbsent from the response entirely for article types that have no custom-field surface (for\r\nexample custom pages); an empty map means custom fields apply but none are configured.", "nullable": true, "readOnly": true } }, "additionalProperties": false, "description": "Full article detail with content." }, "ApiError": { "required": [ "code", "message" ], "type": "object", "properties": { "code": { "minLength": 1, "enum": [ "BAD_REQUEST", "CONFLICT", "FEATURE_NOT_IN_LICENSE", "FORBIDDEN", "INTERNAL_SERVER_ERROR", "LICENSE_LIMIT_EXCEEDED", "OPERATION_FAILED", "PREMIUM_FEATURE_NOT_IN_LICENSE", "RESOURCE_NOT_FOUND", "TOO_MANY_REQUESTS", "UNAUTHORIZED", "UNRECOGNIZED_FIELD", "UNRECOGNIZED_FIELDS", "VALIDATION_ERROR" ], "type": "string", "description": "Machine-readable error code (e.g. VALIDATION_ERROR, RESOURCE_NOT_FOUND)." }, "message": { "minLength": 1, "type": "string", "description": "Human-readable error message." }, "field": { "type": "string", "description": "The request field that caused the error, if applicable.", "nullable": true }, "details": { "type": "string", "description": "Additional context about the error.", "nullable": true } }, "additionalProperties": false, "description": "Represents an error returned by the API." }, "ApiWarning": { "required": [ "code", "message" ], "type": "object", "properties": { "code": { "minLength": 1, "type": "string", "description": "Machine-readable warning code." }, "message": { "minLength": 1, "type": "string", "description": "Human-readable warning message." } }, "additionalProperties": false, "description": "Represents a non-fatal warning from the API." }, "ArticleStatus": { "enum": [ "draft", "published", "unpublished" ], "type": "string", "description": "The publication status of an article.", "x-enumNames": [ "Draft", "Published", "Unpublished" ], "x-enum-varnames": [ "Draft", "Published", "Unpublished" ], "x-ms-enum": { "name": "ArticleStatus", "modelAsString": true } }, "AuthorResponse": { "required": [ "email", "id" ], "type": "object", "properties": { "id": { "type": "string", "description": "The unique identifier of the author.", "format": "uuid", "nullable": true, "readOnly": true, "example": "a1b2c3d4-e5f6-7a8b-9c0d-1e2f3a4b5c6d" }, "first_name": { "type": "string", "description": "The first name of the author.", "nullable": true, "example": "Jane" }, "last_name": { "type": "string", "description": "The last name of the author.", "nullable": true, "example": "Doe" }, "email": { "type": "string", "description": "The email address of the author.", "format": "email", "nullable": true, "example": "jane.doe@example.com" }, "profile_logo_url": { "type": "string", "description": "The URL of the author's profile image.", "nullable": true, "example": "https://cdn.example.com/avatars/jane-doe.png" } }, "additionalProperties": false, "description": "Author information for an article." }, "CategoryType": { "enum": [ "folder", "page", "index" ], "type": "string", "description": "The type of category an article belongs to.", "x-enumNames": [ "Folder", "Page", "Index" ], "x-enum-varnames": [ "Folder", "Page", "Index" ], "x-ms-enum": { "name": "CategoryType", "modelAsString": true } }, "ContentType": { "enum": [ "markdown", "wysiwyg", "block" ], "type": "string", "description": "The editor content type used for an article.", "x-enumNames": [ "Markdown", "Wysiwyg", "Block" ], "x-enum-varnames": [ "Markdown", "Wysiwyg", "Block" ], "x-ms-enum": { "name": "ContentType", "modelAsString": true } }, "TranslationOption": { "enum": [ "none", "needTranslation", "translated", "inProgress" ], "type": "string", "description": "The translation status of an article.", "x-enumNames": [ "None", "NeedTranslation", "Translated", "InProgress" ], "x-enum-varnames": [ "None", "NeedTranslation", "Translated", "InProgress" ], "x-ms-enum": { "name": "TranslationOption", "modelAsString": true } }, "AvailableLanguage": { "type": "object", "properties": { "lang_code": { "type": "string", "description": "The language code (e.g., \"en\", \"fr\").", "nullable": true, "example": "fr" }, "url": { "type": "string", "description": "The URL of the article in this language.", "format": "uri", "nullable": true, "example": "https://docs.example.com/fr/articles/getting-started-with-single-sign-on" }, "translation_status": { "enum": [ "none", "needTranslation", "translated", "inProgress" ], "type": "string", "allOf": [ { "$ref": "#/components/schemas/TranslationOption" } ], "description": "The translation status for this language.", "x-enumNames": [ "None", "NeedTranslation", "Translated", "InProgress" ], "x-enum-varnames": [ "None", "NeedTranslation", "Translated", "InProgress" ], "x-ms-enum": { "name": "TranslationOption", "modelAsString": true } } }, "additionalProperties": false, "description": "Represents a language in which an article is available." }, "ArticleDocumentSettings": { "type": "object", "properties": { "seo_title": { "type": "string", "description": "The custom SEO title for search engines.", "nullable": true, "example": "SSO Setup Guide - Product Documentation" }, "description": { "type": "string", "description": "The meta description for search engines.", "nullable": true, "example": "Step-by-step instructions for configuring single sign-on with SAML or OIDC providers." }, "exclude_from_external_search": { "type": "boolean", "description": "Whether the article is excluded from external search engine indexing.", "example": false } }, "additionalProperties": false, "description": "SEO and display settings embedded within an article detail." }, "StaleStatusResponse": { "required": [ "expire_days", "is_from_document_settings" ], "type": "object", "properties": { "article_stale_status": { "enum": [ "fresh", "stale" ], "type": "string", "allOf": [ { "$ref": "#/components/schemas/ArticleStaleStatus" } ], "description": "Whether the article is up to date (fresh) or requires review (stale).", "x-enumNames": [ "Fresh", "Stale" ], "x-enum-varnames": [ "Fresh", "Stale" ], "x-ms-enum": { "name": "ArticleStaleStatus", "modelAsString": true } }, "stale_reason": { "type": "string", "description": "The reason the article was marked stale, if any.", "nullable": true }, "expired_at": { "type": "string", "description": "The date the article is next due for review (UTC). Once this date passes, the article is considered stale.", "format": "date-time", "nullable": true, "example": "2026-01-31T05:10:26Z" }, "is_from_document_settings": { "type": "boolean", "description": "Whether the review schedule was inherited from project-level documentation settings.", "example": false }, "expire_days": { "type": "integer", "description": "The number of days from publication after which the article should next be reviewed.", "format": "int32", "example": 30 } }, "additionalProperties": false, "description": "Content freshness information for an article, derived from its review reminder schedule." }, "ArticleStaleStatus": { "enum": [ "fresh", "stale" ], "type": "string", "description": "The content freshness classification of an article, derived from its review reminder schedule.", "x-enumNames": [ "Fresh", "Stale" ], "x-enum-varnames": [ "Fresh", "Stale" ], "x-ms-enum": { "name": "ArticleStaleStatus", "modelAsString": true } } }, "securitySchemes": { "ApiKey": { "type": "apiKey", "description": "API key for machine-to-machine integrations, webhooks, and CI/CD (recommended). This is a static, pre-shared secret - treat it as an opaque string and do not parse it; it is an API key, not an OAuth 2.0 access token. Create one in the portal under **Settings > Knowledge base portal > API keys** using the **Create API key** button - this is a different credential from the V1/V2 *API token*, which lives on its own screen and will not authenticate a V3 request. The plaintext key (format `d360_sk_...`) is shown only once, at creation. Send it in the `X-API-Key` header: `X-API-Key: d360_sk_...`. Each key carries a fixed portal role, content role, and content-access scope, supports an optional expiry, and can be disabled or deleted at any time from the portal.", "name": "X-API-Key", "in": "header" }, "Bearer": { "type": "oauth2", "description": "All V3 endpoints require a Bearer token. Generate tokens in the Document360 portal under **Settings > API Tokens**. Tokens are project-scoped, require the `customerApi` scope, and do not expire by default. Tokens can be revoked at any time from the portal. Include the token in every request: `Authorization: Bearer `. Alternatively, use the Authorize button below to sign in via OAuth2 Authorization Code flow with PKCE.", "flows": { "authorizationCode": { "authorizationUrl": "https://identity.document360.io/connect/authorize", "tokenUrl": "https://identity.document360.io/connect/token", "scopes": { "openid": "OpenID Connect", "profile": "User profile", "email": "User email", "customerApi": "Document360 Customer API" }, "x-usePkce": { "disableManualConfiguration": true, "hideClientSecretInput": true } } }, "x-d360-clientId": "apiHubWebClient" } } } } ````