Let’s define a practical path from decision to delivery.
OPENAPI · V1
Authorized server applications can list published knowledge articles and publish new bilingual articles directly to the COS knowledge base.
Production API origin: https://project.xiaotunqifu.com. Both operations use HTTPS, POST and Content-Type: application/json.
| Operation | Path |
|---|---|
| List articles | /api/openapi/knowledge/list |
| Create an article | /api/openapi/knowledge/create |
Configure KNOWLEDGE_RELEASE_SECRET_ID and KNOWLEDGE_RELEASE_SECRET_KEY on your server. The key is a 64-character hexadecimal string representing 32 bytes.
Encrypt the UTF-8 JSON payload using AES-256-GCM with a fresh random 12-byte IV and a 16-byte authentication tag. Send a JSON envelope with secretId, timestamp (integer Unix seconds), nonce, iv, ciphertext and tag. Use standard padded Base64 for IV, ciphertext and tag. The tag is separate from ciphertext.
The timestamp must be within 300 seconds of server time. Each nonce is single-use: 16–128 characters from A–Z, a–z, 0–9, _ and -. A Base64URL-encoded 24-byte random value is recommended.
AAD is the UTF-8 encoding of these lines, joined with \n, with no trailing newline:
BW-RELEASE-V1
request
POST
{path}
{secretId}
{timestamp}
{nonce}
Use the complete endpoint path from the table, without a host, query string or trailing slash. Successful responses have the shape {"code":0,"status":200,"data":{...envelope...}}. Decrypt data with the same key, changing the second AAD line to response and using the response timestamp. Verify the authentication tag, Secret ID, matching request nonce and timestamp before consuming the result. HTTP errors contain an unencrypted message and status.
Generate a fresh nonce, timestamp and IV for every attempt, including retries. See the Node.js Crypto documentation for GCM and AAD APIs.
Encrypt {"page":1,"size":20}. Page defaults to 1 (maximum 100000); size defaults to 20 (range 1–100). The decrypted response contains version, page, size, total and records. Records include id, routeSlug, aliases, hash and localized zh / en metadata, without article bodies.
Pass the first response's version with subsequent pages. HTTP 409 means the snapshot changed; restart from page 1. Article paths are /faq/{routeSlug} and /en/faq/{routeSlug}.
The plaintext JSON contains id, zh and en. Use a stable ID starting with faq-api-, followed by lowercase letters, digits and single hyphen separators, up to 150 characters total. Each language object requires:
| Field | Value |
|---|---|
| q | Nonempty title, up to 200 characters; use an English title in en |
| summary | Nonempty summary, up to 2000 characters |
| category | Nonempty category, up to 100 characters |
| tags | Array of up to 20 nonempty strings, each up to 80 characters; an empty array is allowed |
| updatedAt | ISO date-time string, such as 2026-09-24T10:00:00+08:00 |
| a | Nonempty Markdown body, up to 200000 characters |
Both languages are required. The English title determines the stable URL. Existing URLs and article IDs cannot be overwritten through this endpoint.
{
"id": "faq-api-approval-guide",
"zh": {
"q": "如何规划审批流程?",
"summary": "明确审批角色和权限。",
"category": "软件定制",
"tags": ["审批"],
"updatedAt": "2026-09-24T10:00:00+08:00",
"a": "## 角色\n\n确定发起人和审批人。"
},
"en": {
"q": "Planning approval workflows",
"summary": "Define approval roles and permissions.",
"category": "Custom Software",
"tags": ["Approvals"],
"updatedAt": "2026-09-24T10:00:00+08:00",
"a": "## Roles\n\nIdentify who submits and who approves each request."
}
}
The result includes id, version, created, published, status, pending and urls (zh and en). published: true confirms COS publication. status: complete confirms search and website cache synchronization. If status is pending, the pending array identifies search and/or website-cache; resubmit the same ID and content to retry synchronization. An identical retry returns created: false. Different content with an existing ID returns 409.
Download release-client.mjs. This Node.js 24 client handles encryption, transport and response verification. With credentials configured in your environment:
import { readFile } from 'node:fs/promises';
import { releaseRequest } from './release-client.mjs';
console.log(await releaseRequest('list', { page: 1, size: 20 }));
// Run when the article is ready to publish.
const article = JSON.parse(await readFile('./article.json', 'utf8'));
console.log(await releaseRequest('create', article));
Override the API origin with KNOWLEDGE_RELEASE_BASE_URL or pass { baseUrl, secretId, secretKey } as the third argument.
| HTTP status | Meaning |
|---|---|
| 401 | Invalid credentials, authentication tag, timestamp or reused nonce |
| 409 | Publication in progress, conflicting ID/URL or changed pagination version |
| 422 | Invalid article or pagination fields |
| 503 | Dependency unavailable or uncertain publication outcome |
After a timeout or 503, keep the same article ID and content and retry with a fresh encrypted envelope. For 409, follow the returned message: wait for an active publication, resolve a conflict or restart pagination as appropriate.