{"paths":{"/api/v1/blog/posts/save":{"post":{"security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlogPostSaveReq"}}},"required":true},"x-required-scopes":["blog:write","blog:publish when status=1"],"description":"Creates a draft when id is empty, updates an existing post when id is present, and persists every SEO field exposed by the admin editor. Use status=0 for draft, status=1 only when publishing through this endpoint with blog:publish, and status=2 to take a post offline.","responses":{"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Missing or invalid API token."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Business validation error, including duplicate slug or SEO check failure."},"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Result"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/BlogPostRes"}}}]}}},"description":"Result wrapper with code=0000 on success."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Token exists but does not have the required scope."}},"summary":"Create or update a blog post"}},"/api/v1/blog/media/upload":{"post":{"security":[{"bearerAuth":[]}],"requestBody":{"content":{"multipart/form-data":{"schema":{"properties":{"file":{"format":"binary","description":"Image file. Recommended formats: webp, avif, jpg, png.","type":"string"}},"type":"object","required":["file"]}}},"required":true},"x-required-scopes":["blog:write"],"description":"Uploads cover, body, Open Graph, or author/publication media for external publishing integrations. The response data is the final public CloudFlare-ImgBed HTTPS URL and can be saved directly into coverImage, ogImage, contentHtml img src, or structured ImageObject fields.","responses":{"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Missing or invalid API token."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Business validation error, including duplicate slug or SEO check failure."},"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Result"},{"type":"object","properties":{"data":{"type":"string"}}}]}}},"description":"Result wrapper with code=0000 on success."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Token exists but does not have the required scope."}},"summary":"Upload blog media with an API token"}},"/api/v1/blog/posts/{id}/comments":{"post":{"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlogCommentReq"}}},"required":true},"security":[{},{"bearerAuth":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Result"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/BlogPublicCommentRes"}}}]}}},"description":"Result wrapper with code=0000 on success."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Business validation error, such as missing comment content or a non-existent public resource."},"301":{"description":"Only detail requests may redirect old slugs to the current slug."}},"x-optional-scopes":["blog:read"],"description":"Creates a comment for moderation. Public article pages only display approved comments.","summary":"Create a pending blog comment","parameters":[{"in":"path","required":true,"schema":{"type":"integer","format":"int64"},"description":"Blog post id.","name":"id"}]}},"/api/v1/blog/posts/{id}/reactions":{"post":{"security":[{},{"bearerAuth":[]}],"x-optional-scopes":["blog:read"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlogReactionReq"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Result"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/BlogEngagementRes"}}}]}}},"description":"Result wrapper with code=0000 on success."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Business validation error, such as missing comment content or a non-existent public resource."},"301":{"description":"Only detail requests may redirect old slugs to the current slug."}},"parameters":[{"in":"path","required":true,"schema":{"type":"integer","format":"int64"},"description":"Blog post id.","name":"id"}],"summary":"Add a clap reaction"}},"/api/v1/blog/posts/{id}/publish":{"post":{"security":[{"bearerAuth":[]}],"responses":{"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Missing or invalid API token."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Business validation error, including duplicate slug or SEO check failure."},"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Result"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/BlogPostRes"}}}]}}},"description":"Result wrapper with code=0000 on success."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Token exists but does not have the required scope."}},"x-required-scopes":["blog:publish"],"description":"Runs the SEO publishing check again before changing status to published. On success, public API, sitemap, RSS, Last-Modified/ETag, and webhook events are updated.","parameters":[{"in":"path","required":true,"schema":{"type":"integer","format":"int64"},"description":"Blog post id.","name":"id"}],"summary":"Publish a saved draft"}},"/api/v1/blog/resources/search":{"post":{"security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlogResourceSearchReq"}}},"required":true},"x-required-scopes":["blog:read"],"description":"Searches active public account/business resources. Use the returned id, title, description, category, and price to generate a crawlable resource card in contentHtml and set relatedProductIds on the blog post. Public resource links should use /en/products/{id}-{slugified English name} or /cn/products/{id}-{slugified Chinese name or product}.","responses":{"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Missing or invalid API token."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Business validation error, including duplicate slug or SEO check failure."},"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Result"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PageBlogResourceRes"}}}]}}},"description":"Result wrapper with code=0000 on success."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Token exists but does not have the required scope."}},"summary":"Search business resources for content cards"}},"/api/v1/blog/authors/{slug}":{"get":{"parameters":[{"in":"path","required":true,"schema":{"type":"string"},"description":"Author slug.","name":"slug"},{"in":"query","required":false,"schema":{"default":"en","type":"string","enum":["en","zh"]},"description":"Language, defaults to en.","name":"language"}],"x-optional-scopes":["blog:read"],"responses":{"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Result"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/BlogAuthorRes"}}}]}}},"description":"Result wrapper with code=0000 on success."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Business validation error, such as missing comment content or a non-existent public resource."},"301":{"description":"Only detail requests may redirect old slugs to the current slug."}},"summary":"Get public author profile","security":[{},{"bearerAuth":[]}]}},"/api/v1/blog/openapi.json":{"get":{"description":"Machine-readable OpenAPI 3.0 JSON for the public and token-protected blog API. The human-readable public documentation is served by the SEO frontend at /blog/api.","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"OpenAPI 3.0 document"}},"summary":"OpenAPI document"}},"/api/v1/blog/resources/categories":{"get":{"responses":{"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Missing or invalid API token."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Business validation error, including duplicate slug or SEO check failure."},"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Result"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/BlogResourceCategoryRes"}}}}]}}},"description":"Result wrapper with code=0000 on success."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Token exists but does not have the required scope."}},"summary":"List business resource categories","security":[{"bearerAuth":[]}],"x-required-scopes":["blog:read"],"description":"Returns public product/resource categories for external systems that need to insert crawlable resource cards into article HTML."}},"/api/v1/blog/posts/operate":{"get":{"security":[{"bearerAuth":[]}],"responses":{"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Missing or invalid API token."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Business validation error, including duplicate slug or SEO check failure."},"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Result"},{"type":"object","properties":{"data":{"type":"boolean"}}}]}}},"description":"Result wrapper with code=0000 on success."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Token exists but does not have the required scope."}},"x-required-scopes":["blog:publish"],"description":"Use /posts/{id}/publish for normal publishing. Use this endpoint mainly for unpublishing or admin-style status operations.","parameters":[{"in":"query","required":true,"schema":{"type":"integer","format":"int64"},"description":"Blog post id.","name":"id"},{"in":"query","required":true,"schema":{"type":"integer","enum":[1,2]},"description":"1 published, 2 offline.","name":"status"}],"summary":"Publish or unpublish a post by status"}},"/api/v1/blog/posts/check":{"post":{"security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlogSeoCheckReq"}}},"required":true},"x-required-scopes":["blog:write"],"description":"Submits the current editor draft without saving it. The response mirrors the admin editor SEO step: score, canPublish, blocking items, table of contents, and generated title/description/slug suggestions.","responses":{"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Missing or invalid API token."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Business validation error, including duplicate slug or SEO check failure."},"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Result"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/BlogSeoCheckRes"}}}]}}},"description":"Result wrapper with code=0000 on success."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Token exists but does not have the required scope."}},"summary":"Run SEO publishing check"}},"/api/v1/blog/posts/{id}/engagement":{"get":{"parameters":[{"in":"path","required":true,"schema":{"type":"integer","format":"int64"},"description":"Blog post id.","name":"id"}],"x-optional-scopes":["blog:read"],"responses":{"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Result"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/BlogEngagementRes"}}}]}}},"description":"Result wrapper with code=0000 on success."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Business validation error, such as missing comment content or a non-existent public resource."},"301":{"description":"Only detail requests may redirect old slugs to the current slug."}},"summary":"Read engagement data","security":[{},{"bearerAuth":[]}]}},"/api/v1/blog/authors/save":{"post":{"security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlogAuthorReq"}}},"required":true},"x-required-scopes":["blog:write"],"description":"Creates or updates the structured author profile used by author pages and Person JSON-LD. External publishing systems can use author text alone, but authorId gives richer SEO output.","responses":{"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Missing or invalid API token."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Business validation error, including duplicate slug or SEO check failure."},"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Result"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/BlogAuthorRes"}}}]}}},"description":"Result wrapper with code=0000 on success."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Token exists but does not have the required scope."}},"summary":"Create or update a blog author"}},"/api/v1/blog/publication-settings":{"get":{"x-optional-scopes":["blog:read"],"responses":{"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Result"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/BlogPublicationSettingsRes"}}}]}}},"description":"Result wrapper with code=0000 on success."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Business validation error, such as missing comment content or a non-existent public resource."},"301":{"description":"Only detail requests may redirect old slugs to the current slug."}},"summary":"Read public publication settings","security":[{},{"bearerAuth":[]}],"description":"Returns public display settings for the CBGAccount publication mark. Nuxt blog pages use this to render the publication logo without exposing admin-only SEO, AI, Search Console, or media provider secrets."}},"/api/v1/blog/posts/{slug}":{"get":{"security":[{},{"bearerAuth":[]}],"x-optional-scopes":["blog:read"],"responses":{"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Result"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/BlogPostRes"}}}]}}},"description":"Result wrapper with code=0000 on success."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Business validation error, such as missing comment content or a non-existent public resource."},"301":{"description":"Only detail requests may redirect old slugs to the current slug."}},"description":"Returns all public article fields required for SEO rendering: content HTML, title, summary, canonical, robots, Open Graph fields, tags, category, table of contents, and engagement counters. If an old slug redirects, the API returns 301 with Location.","parameters":[{"in":"path","required":true,"schema":{"type":"string"},"description":"URL slug.","name":"slug"},{"in":"query","required":false,"schema":{"default":"en","type":"string","enum":["en","zh"]},"description":"Language, defaults to en.","name":"language"}],"summary":"Get a published blog post"}},"/api/v1/blog/categories/save":{"post":{"security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlogCategoryReq"}}},"required":true},"x-required-scopes":["blog:write"],"description":"Use categories for primary article grouping and crawlable category pages.","responses":{"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Missing or invalid API token."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Business validation error, including duplicate slug or SEO check failure."},"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Result"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/BlogCategoryRes"}}}]}}},"description":"Result wrapper with code=0000 on success."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Token exists but does not have the required scope."}},"summary":"Create or update a blog category"}},"/api/v1/blog/posts":{"get":{"security":[{},{"bearerAuth":[]}],"x-optional-scopes":["blog:read"],"responses":{"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Result"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PageBlogPostRes"}}}]}}},"description":"Result wrapper with code=0000 on success."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Business validation error, such as missing comment content or a non-existent public resource."},"301":{"description":"Only detail requests may redirect old slugs to the current slug."}},"description":"Returns crawlable, published posts for Nuxt SSR pages, archive pages, internal-link pickers, RSS builders, and external readers. Optional API token is accepted for usage logging.","parameters":[{"in":"query","required":false,"schema":{"type":"string","enum":["en","zh"]},"description":"Language filter.","name":"language"},{"in":"query","required":false,"schema":{"type":"integer","default":1},"description":"Page number.","name":"current"},{"in":"query","required":false,"schema":{"type":"integer","default":10},"description":"Page size.","name":"size"},{"in":"query","required":false,"schema":{"type":"integer","format":"int64"},"description":"Filter by category id.","name":"categoryId"},{"in":"query","required":false,"schema":{"type":"integer","format":"int64"},"description":"Filter by author id.","name":"authorId"},{"in":"query","required":false,"schema":{"type":"integer","format":"int64"},"description":"Filter by tag id.","name":"tagId"},{"in":"query","required":false,"schema":{"type":"string"},"description":"Search title, summary, or slug.","name":"keyword"}],"summary":"List published blog posts"}},"/api/v1/blog/categories":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Result"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/BlogCategoryRes"}}}}]}}},"description":"Result wrapper with code=0000 on success."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Business validation error, such as missing comment content or a non-existent public resource."},"301":{"description":"Only detail requests may redirect old slugs to the current slug."}},"security":[{},{"bearerAuth":[]}],"x-optional-scopes":["blog:read"],"summary":"List categories"}},"/api/v1/blog/sitemap.xml":{"get":{"summary":"Sitemap XML","responses":{"200":{"content":{"application/xml":{"schema":{"type":"string"}}},"description":"Sitemap XML"}}}},"/api/v1/blog/robots.txt":{"get":{"summary":"Robots.txt","responses":{"200":{"content":{"text/plain":{"schema":{"type":"string"}}},"description":"Robots directives"}}}},"/api/v1/blog/authors/{slug}/posts":{"get":{"security":[{},{"bearerAuth":[]}],"x-optional-scopes":["blog:read"],"responses":{"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Result"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PageBlogPostRes"}}}]}}},"description":"Result wrapper with code=0000 on success."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Business validation error, such as missing comment content or a non-existent public resource."},"301":{"description":"Only detail requests may redirect old slugs to the current slug."}},"description":"Returns published posts linked to an enabled author profile. This powers public author pages and can be used by external editorial archives.","parameters":[{"in":"path","required":true,"schema":{"type":"string"},"description":"Author slug.","name":"slug"},{"in":"query","required":false,"schema":{"default":"en","type":"string","enum":["en","zh"]},"description":"Language, defaults to en.","name":"language"},{"in":"query","required":false,"schema":{"type":"integer","default":1},"description":"Page number.","name":"current"},{"in":"query","required":false,"schema":{"type":"integer","default":12},"description":"Page size.","name":"size"}],"summary":"List posts by author"}},"/api/v1/blog/posts/delete":{"get":{"security":[{"bearerAuth":[]}],"responses":{"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Missing or invalid API token."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Business validation error, including duplicate slug or SEO check failure."},"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Result"},{"type":"object","properties":{"data":{"type":"boolean"}}}]}}},"description":"Result wrapper with code=0000 on success."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Token exists but does not have the required scope."}},"x-required-scopes":["blog:publish"],"description":"Deletes the post and removes it from public discovery. Prefer unpublishing when SEO history or redirects should be preserved.","parameters":[{"in":"query","required":true,"schema":{"type":"integer","format":"int64"},"description":"Blog post id.","name":"id"}],"summary":"Delete a blog post"}},"/api/v1/blog/authors":{"get":{"parameters":[{"in":"query","required":false,"schema":{"type":"string","enum":["en","zh"]},"description":"Optional en or zh.","name":"language"}],"x-optional-scopes":["blog:read"],"responses":{"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Result"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/BlogAuthorRes"}}}}]}}},"description":"Result wrapper with code=0000 on success."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Business validation error, such as missing comment content or a non-existent public resource."},"301":{"description":"Only detail requests may redirect old slugs to the current slug."}},"summary":"List public blog authors","security":[{},{"bearerAuth":[]}]}},"/api/v1/blog/rss.xml":{"get":{"summary":"RSS feed","responses":{"200":{"content":{"application/xml":{"schema":{"type":"string"}}},"description":"RSS feed"}}}},"/api/v1/blog/tags/save":{"post":{"responses":{"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Missing or invalid API token."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Business validation error, including duplicate slug or SEO check failure."},"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Result"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/BlogTagRes"}}}]}}},"description":"Result wrapper with code=0000 on success."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Token exists but does not have the required scope."}},"summary":"Create or update a blog tag","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlogTagReq"}}},"required":true},"security":[{"bearerAuth":[]}],"x-required-scopes":["blog:write"]}},"/api/v1/blog/tags":{"get":{"security":[{},{"bearerAuth":[]}],"x-optional-scopes":["blog:read"],"responses":{"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Result"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/BlogTagRes"}}}}]}}},"description":"Result wrapper with code=0000 on success."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResult"}}},"description":"Business validation error, such as missing comment content or a non-existent public resource."},"301":{"description":"Only detail requests may redirect old slugs to the current slug."}},"description":"Tags can be grouped by language so the admin article list and public tag pages stay language-aware.","parameters":[{"in":"query","required":false,"schema":{"type":"string","enum":["en","zh","all"]},"description":"Optional en, zh, or all.","name":"language"}],"summary":"List tags"}}},"servers":[{"url":"https://www.cbgaccount.com"}],"openapi":"3.0.3","components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"Result":{"type":"object","properties":{"code":{"type":"string","description":"Business code. 0000 means success."},"data":{"nullable":true},"message":{"type":"string","description":"Human-readable message."}}},"BlogSeoCheckItemRes":{"type":"object","properties":{"code":{"type":"string","description":"Stable rule code, such as title_length, image_alt, or internal_links."},"targetStep":{"type":"string","description":"Editor step to open when the user clicks fix: basic, content, seo, aeo, or publish."},"weight":{"type":"integer","description":"Rule weight used in score calculation."},"autoFixType":{"type":"string","description":"Optional admin editor auto-fix action, such as slug, seo_title, seo_description, canonical_self, or cover_alt."},"fixAction":{"type":"string","description":"Concrete fix suggestion shown in the admin editor."},"why":{"type":"string","description":"Why this matters for SEO and indexing."},"targetField":{"type":"string","description":"Editor field or panel to focus, such as slug, coverAlt, contentHtml, faqBlocks, or alternateSlug."},"blocking":{"type":"boolean","description":"Whether this item blocks publishing."},"passed":{"type":"boolean","description":"Whether this item passed."},"label":{"type":"string","description":"Beginner-friendly rule label."},"message":{"type":"string","description":"Current finding."}}},"BlogResourceRes":{"type":"object","properties":{"stock":{"type":"integer","description":"Available stock count."},"descriptionEn":{"type":"string","description":"English resource description."},"descriptionZh":{"type":"string","description":"Chinese resource description."},"categoryName":{"type":"string","description":"Category display name."},"cnyPrice":{"type":"integer","description":"CNY price in the existing product unit."},"nameEn":{"type":"string","description":"English resource name."},"categoryCode":{"type":"string","description":"Primary category code."},"nameZh":{"type":"string","description":"Chinese resource name."},"status":{"type":"integer","description":"1 active, 2 offline, 3 out of stock."},"usdtPrice":{"type":"integer","description":"USDT price in the existing product unit."},"id":{"format":"int64","description":"Internal resource id. Use this in relatedProductIds.","type":"integer"},"productId":{"type":"string","description":"Source product/resource id. Public SEO detail routes use the numeric id plus a slug, for example /en/products/1-local-test-account."}}},"BlogTagRes":{"type":"object","properties":{"id":{"format":"int64","description":"Tag id.","type":"integer"},"status":{"type":"integer","description":"0 disabled, 1 enabled."},"nameEn":{"type":"string","description":"English label."},"nameZh":{"type":"string","description":"Chinese label."},"language":{"type":"string","description":"Language group."},"slug":{"type":"string","description":"Public tag slug."}}},"BlogTagReq":{"properties":{"id":{"format":"int64","description":"Tag id for updates.","type":"integer"},"status":{"type":"integer","description":"0 disabled, 1 enabled."},"nameEn":{"type":"string","description":"English label."},"nameZh":{"type":"string","description":"Chinese label."},"language":{"description":"Language group for filtering and admin organization.","type":"string","enum":["all","en","zh"]},"slug":{"type":"string","description":"Public tag slug."}},"type":"object","required":["language"],"example":{"nameZh":"账号基础设施","slug":"account-infrastructure","status":1,"nameEn":"Account Infrastructure","language":"all"}},"BlogResourceCategoryRes":{"type":"object","properties":{"id":{"format":"int64","description":"Category id.","type":"integer"},"nameEn":{"type":"string","description":"English category name."},"iconUrl":{"type":"string","description":"Public category icon URL."},"nameZh":{"type":"string","description":"Chinese category name."},"children":{"type":"array","items":{"$ref":"#/components/schemas/BlogResourceCategoryRes"}},"code":{"type":"string","description":"Category code used as categoryCode."}}},"PageBlogPostRes":{"type":"object","properties":{"total":{"type":"integer","description":"Total matched records."},"size":{"type":"integer","description":"Page size."},"records":{"type":"array","items":{"$ref":"#/components/schemas/BlogPostRes"}},"current":{"type":"integer","description":"Current page number."}}},"BlogFaqBlock":{"type":"object","properties":{"sortOrder":{"type":"integer","description":"Display order."},"answer":{"type":"string","description":"Direct FAQ answer."},"question":{"type":"string","description":"FAQ question."}}},"BlogEngagementRes":{"type":"object","properties":{"comments":{"type":"array","items":{"$ref":"#/components/schemas/BlogPublicCommentRes"}},"postId":{"format":"int64","description":"Blog post id.","type":"integer"},"commentCount":{"type":"integer","description":"Approved comment count."},"clapCount":{"type":"integer","description":"Total clap count."}}},"BlogAuthorRes":{"type":"object","properties":{"title":{"type":"string","description":"Role or title."},"id":{"format":"int64","description":"Author id.","type":"integer"},"postCount":{"type":"integer","description":"Number of linked posts."},"name":{"type":"string","description":"Public author name."},"credentials":{"type":"string","description":"Credentials or editorial authority statement."},"avatar":{"type":"string","description":"Avatar URL."},"socialLinks":{"type":"string","description":"Social links JSON."},"status":{"type":"integer","description":"0 disabled, 1 enabled."},"language":{"type":"string","description":"Author language."},"slug":{"type":"string","description":"Author URL slug."},"bio":{"type":"string","description":"Author bio."}}},"BlogAuthorReq":{"properties":{"title":{"type":"string","description":"Role or title."},"id":{"format":"int64","description":"Author id for updates.","type":"integer"},"sort":{"type":"integer","description":"Sort order."},"name":{"type":"string","description":"Public author name."},"credentials":{"type":"string","description":"Editorial authority or credentials statement."},"avatar":{"type":"string","description":"Public avatar URL. Upload through /api/v1/blog/media/upload or provide a stable HTTPS URL."},"socialLinks":{"type":"string","description":"JSON string containing public social/profile links."},"status":{"description":"0 disabled, 1 enabled.","type":"integer","enum":[0,1]},"language":{"description":"Author profile language.","type":"string","enum":["en","zh"]},"slug":{"type":"string","description":"Public author slug."},"bio":{"type":"string","description":"Author bio used on author pages."}},"type":"object","required":["language","name"],"example":{"slug":"cbgaccount-editorial-team","bio":"Guides for account operations, market entry, creator workflows, and support handoffs.","title":"Account operations editorial team","language":"en","status":1,"sort":10,"credentials":"CBGAccount editorial review","name":"CBGAccount Editorial Team"}},"ErrorResult":{"type":"object","properties":{"code":{"type":"string","description":"Non-0000 business code or HTTP error code."},"data":{"nullable":true},"message":{"type":"string","description":"Failure reason, such as invalid token, duplicate slug, or SEO blocking item."}}},"BlogSeoCheckRes":{"type":"object","properties":{"totalWeight":{"type":"integer","description":"Total rule weight."},"generatedSeoTitle":{"type":"string","description":"Suggested SEO title."},"score":{"type":"integer","description":"0-100 SEO quality score."},"aeoScore":{"type":"integer","description":"0-100 AI citeability score."},"scoreVersion":{"type":"string","description":"Version of the scoring rules."},"canPublish":{"type":"boolean","description":"True only when no blocking issue remains."},"generatedSlug":{"type":"string","description":"Suggested URL slug."},"generatedOgTitle":{"type":"string","description":"Suggested Open Graph title."},"generatedSeoDescription":{"type":"string","description":"Suggested meta description."},"scoreSummary":{"type":"string","description":"Human-readable score summary."},"items":{"type":"array","items":{"$ref":"#/components/schemas/BlogSeoCheckItemRes"}},"passedWeight":{"type":"integer","description":"Passed rule weight."},"toc":{"type":"array","items":{"$ref":"#/components/schemas/BlogTocItemRes"}},"generatedExcerpt":{"type":"string","description":"Suggested summary excerpt."}}},"BlogSeoCheckReq":{"properties":{"indexable":{"default":true,"description":"False writes noindex behavior and blocks normal public discovery.","type":"boolean"},"id":{"format":"int64","description":"Existing post id when checking an update.","type":"integer"},"seoTitle":{"type":"string","description":"Search title. If blank, the system suggests one."},"summary":{"type":"string","description":"Human summary used as excerpt, RSS description, and draft meta description source."},"faqBlocks":{"type":"array","items":{"$ref":"#/components/schemas/BlogFaqBlock"}},"categoryId":{"format":"int64","description":"Primary category id.","type":"integer"},"authorId":{"format":"int64","description":"Structured author id for Person JSON-LD.","type":"integer"},"coverAlt":{"type":"string","description":"Alt text for the cover image. Required for image SEO."},"contentHtml":{"type":"string","description":"Rendered article HTML. Use semantic H1/H2/H3, p, ul/ol, figure, table, blockquote, pre/code, FAQ sections, videos, internal links, and product cards."},"answerSummary":{"type":"string","description":"TL;DR answer summary for AEO rendering."},"seoDescription":{"type":"string","description":"Search description. If blank, the system suggests one."},"alternateSlug":{"type":"string","description":"Translated article slug for hreflang when a real paired article exists."},"canonicalUrl":{"type":"string","description":"Canonical URL. Leave blank for self-canonical unless syndicating content."},"language":{"description":"Article language.","type":"string","enum":["en","zh"]},"keyTakeaways":{"description":"Structured key takeaways.","items":{"type":"string"},"type":"array"},"title":{"type":"string","description":"Visible article title. Public pages render this as the H1."},"slug":{"type":"string","description":"Public URL slug. Leave blank to auto-generate."}},"type":"object","required":["language","title","contentHtml","categoryId"],"example":{"title":"Account infrastructure for cross-border growth workflows","contentHtml":"<h1>Account infrastructure for cross-border growth workflows</h1><p>Account infrastructure helps teams run localized operations with clearer access, permissions, and audit trails.</p><h2>Map the business workflow first</h2><p>Start from the business process, then choose accounts, roles, regions, and recovery paths.</p><h2>Build reusable operating rules</h2><p>Document ownership, login protection, payment boundaries, and support escalation.</p><p>See the <a href=\"/blog\">CBGAccount Blog</a> for related guides.</p>","seoTitle":"Account Infrastructure for Growth Workflows | CBGAccount","canonicalUrl":"https://www.cbgaccount.com/blog/account-infrastructure-growth-workflows","categoryId":1,"coverAlt":"Team dashboard showing account infrastructure workflow checkpoints","language":"en","slug":"account-infrastructure-growth-workflows","indexable":true,"seoDescription":"Learn how account infrastructure supports regional operations, testing, marketing workflows, and safer team access.","summary":"A practical guide to using account infrastructure across operations, testing, marketing, and regional growth."}},"BlogPublicCommentRes":{"type":"object","properties":{"id":{"format":"int64","description":"Comment id.","type":"integer"},"createTime":{"type":"string","description":"Creation time."},"content":{"type":"string","description":"Comment body."},"authorName":{"type":"string","description":"Public display name."},"parentId":{"format":"int64","description":"Parent comment id.","type":"integer"},"status":{"type":"integer","description":"0 pending, 1 approved, 2 rejected/spam."},"statusText":{"type":"string","description":"Localized status label."},"postId":{"format":"int64","description":"Blog post id.","type":"integer"}}},"BlogPublicationSettingsRes":{"type":"object","properties":{"iconUrl":{"type":"string","description":"Public publication icon URL rendered on blog home, article pages, and author/publication cards."},"iconAlt":{"type":"string","description":"Alt text for the publication icon."}}},"BlogCategoryRes":{"type":"object","properties":{"id":{"format":"int64","description":"Category id.","type":"integer"},"descriptionZh":{"type":"string","description":"Chinese description."},"nameZh":{"type":"string","description":"Chinese name."},"descriptionEn":{"type":"string","description":"English description."},"nameEn":{"type":"string","description":"English name."},"status":{"type":"integer","description":"0 disabled, 1 enabled."},"sort":{"type":"integer","description":"Sort order."},"slug":{"type":"string","description":"Public category slug."}}},"BlogPostSaveReq":{"properties":{"indexable":{"default":true,"description":"False writes noindex behavior and blocks normal public discovery.","type":"boolean"},"id":{"format":"int64","description":"Existing post id when checking an update.","type":"integer"},"seoTitle":{"type":"string","description":"Search title. If blank, the system suggests one."},"summary":{"type":"string","description":"Human summary used as excerpt, RSS description, and draft meta description source."},"faqBlocks":{"type":"array","items":{"$ref":"#/components/schemas/BlogFaqBlock"}},"categoryId":{"format":"int64","description":"Primary category id.","type":"integer"},"authorId":{"format":"int64","description":"Structured author id.","type":"integer"},"coverAlt":{"type":"string","description":"Alt text for the cover image. Required for image SEO."},"contentHtml":{"type":"string","description":"Rendered article HTML. Use semantic H1/H2/H3, p, ul/ol, figure, table, blockquote, pre/code, FAQ sections, videos, internal links, and product cards."},"answerSummary":{"type":"string","description":"TL;DR answer summary."},"seoDescription":{"type":"string","description":"Search description. If blank, the system suggests one."},"alternateSlug":{"type":"string","description":"Translated article slug for hreflang when a real paired article exists."},"canonicalUrl":{"type":"string","description":"Canonical URL. Leave blank for self-canonical unless syndicating content."},"language":{"description":"Article language.","type":"string","enum":["en","zh"]},"keyTakeaways":{"type":"array","items":{"type":"string"}},"title":{"type":"string","description":"Visible article title. Public pages render this as the H1."},"slug":{"type":"string","description":"Public URL slug. Leave blank to auto-generate."},"relatedProductIds":{"type":"string","description":"Comma-separated real product ids selected in the editor and inserted as product-card blocks."},"reviewedAt":{"type":"string","description":"Last reviewed time."},"ogImage":{"type":"string","description":"Open Graph image URL. Use the same CloudFlare-ImgBed HTTPS asset as the cover unless a separate social image is needed."},"author":{"type":"string","description":"Author or editorial source displayed publicly."},"ogDescription":{"type":"string","description":"Open Graph description for social sharing."},"ogTitle":{"type":"string","description":"Open Graph title for social sharing."},"coverImage":{"type":"string","description":"Cover image URL. Recommended external workflow: upload the asset through /api/v1/blog/media/upload with a blog:write token so the value is a CloudFlare-ImgBed HTTPS URL."},"robots":{"description":"Robots directive for the article page.","example":"index,follow","type":"string"},"status":{"description":"0 draft, 1 published, 2 offline.","type":"integer","enum":[0,1,2]},"tagIds":{"description":"Selected tag ids, language-aware in the admin UI.","items":{"type":"integer","format":"int64"},"type":"array"}},"type":"object","required":["language","title","contentHtml","categoryId"],"example":{"indexable":true,"ogDescription":"A business-focused guide to using account infrastructure for regional operations and growth workflows.","ogTitle":"Account infrastructure for growth workflows","summary":"A practical guide to using account infrastructure across operations, testing, marketing, and regional growth.","contentHtml":"<h1>Account infrastructure for cross-border growth workflows</h1><p>Account infrastructure helps teams run localized operations with clearer access, permissions, and audit trails.</p><h2>Map the business workflow first</h2><p>Start from the business process, then choose accounts, roles, regions, and recovery paths.</p><h2>Build reusable operating rules</h2><p>Document ownership, login protection, payment boundaries, and support escalation.</p><figure><img src=\"https://media.cbgaccount.com/file/blog-assets/account-infrastructure.webp\" alt=\"Team dashboard showing account infrastructure workflow checkpoints\" width=\"1200\" height=\"675\"/><figcaption>Use visuals that explain the workflow instead of decorative screenshots.</figcaption></figure><p>See the <a href=\"/blog\">CBGAccount Blog</a> for related guides.</p>","title":"Account infrastructure for cross-border growth workflows","status":0,"ogImage":"https://media.cbgaccount.com/file/blog-assets/account-infrastructure-og.webp","coverImage":"https://media.cbgaccount.com/file/blog-assets/account-infrastructure.webp","robots":"index,follow","canonicalUrl":"https://www.cbgaccount.com/blog/account-infrastructure-growth-workflows","categoryId":1,"language":"en","seoDescription":"Learn how account infrastructure supports regional operations, testing, marketing workflows, and safer team access.","seoTitle":"Account Infrastructure for Growth Workflows | CBGAccount","author":"CBGAccount Editorial","relatedProductIds":"10001,10002","slug":"account-infrastructure-growth-workflows","tagIds":[1,2],"coverAlt":"Team dashboard showing account infrastructure workflow checkpoints"}},"BlogCategoryReq":{"properties":{"id":{"format":"int64","description":"Category id for updates.","type":"integer"},"descriptionZh":{"type":"string","description":"Chinese description for category pages."},"nameZh":{"type":"string","description":"Chinese name."},"descriptionEn":{"type":"string","description":"English description for category pages."},"nameEn":{"type":"string","description":"English name."},"status":{"type":"integer","description":"0 disabled, 1 enabled."},"sort":{"type":"integer","description":"Sort order."},"slug":{"type":"string","description":"Public category slug."}},"type":"object","required":["nameEn"],"example":{"slug":"operations","descriptionZh":"账号基础设施、团队协作和区域化运营指南。","descriptionEn":"Guides for account infrastructure, team workflows, and regional operations.","nameZh":"运营增长","nameEn":"Operations","status":1,"sort":10}},"PageBlogResourceRes":{"type":"object","properties":{"total":{"type":"integer","description":"Total matched resources."},"size":{"type":"integer","description":"Page size."},"records":{"type":"array","items":{"$ref":"#/components/schemas/BlogResourceRes"}},"current":{"type":"integer","description":"Current page number."}}},"BlogReactionReq":{"type":"object","properties":{"clientKey":{"type":"string","description":"Client-side idempotency key to avoid accidental duplicate reactions."},"count":{"type":"integer","description":"Number of claps to add, usually 1."},"reactionKey":{"type":"string","description":"Reaction type. Use clap for Medium-like recommendations."}},"example":{"clientKey":"browser-session-20260522-001","count":1,"reactionKey":"clap"}},"BlogCommentRes":{"type":"object","properties":{"postTitle":{"type":"string","description":"Blog post title for admin displays."},"statusText":{"type":"string","description":"Localized status label."},"postId":{"format":"int64","description":"Blog post id.","type":"integer"},"status":{"type":"integer","description":"0 pending, 1 approved, 2 rejected."},"parentId":{"format":"int64","description":"Parent comment id.","type":"integer"},"authorName":{"type":"string","description":"Public display name."},"authorEmail":{"type":"string","description":"Email for moderation."},"createTime":{"type":"string","description":"Creation time."},"content":{"type":"string","description":"Comment body."},"id":{"format":"int64","description":"Comment id.","type":"integer"}}},"BlogResourceSearchReq":{"type":"object","properties":{"status":{"type":"integer","description":"Defaults to 1 active when omitted."},"sourceType":{"type":"integer","description":"Optional resource source type."},"size":{"type":"integer","description":"Page size."},"categoryCode":{"type":"string","description":"Optional public category code."},"keywords":{"type":"string","description":"Search resource id, name, or description."},"current":{"type":"integer","description":"Page number."}},"example":{"keywords":"regional account","current":1,"size":12,"status":1,"categoryCode":"business-accounts"}},"BlogCommentReq":{"properties":{"parentId":{"format":"int64","description":"Optional parent comment id for replies.","type":"integer"},"content":{"type":"string","description":"Comment body. The system stores it as pending until moderation."},"authorEmail":{"type":"string","description":"Email for moderation. Not rendered publicly."},"authorName":{"type":"string","description":"Public display name."}},"type":"object","required":["authorName","content"],"example":{"authorName":"Alex","content":"This is useful for planning multi-region account operations.","authorEmail":"alex@example.com"}},"BlogPostRes":{"type":"object","properties":{"relatedPosts":{"type":"array","items":{"$ref":"#/components/schemas/BlogPostRes"}},"coverImage":{"type":"string","description":"Cover image URL."},"faqBlocks":{"type":"array","items":{"$ref":"#/components/schemas/BlogFaqBlock"}},"summary":{"type":"string","description":"Excerpt and feed summary."},"indexable":{"type":"boolean","description":"Whether this page should be indexable."},"toc":{"type":"array","items":{"$ref":"#/components/schemas/BlogTocItemRes"}},"ogTitle":{"type":"string","description":"Open Graph title."},"contentHtml":{"type":"string","description":"Rendered article HTML."},"clapCount":{"type":"integer","description":"Recommendation count."},"contentText":{"type":"string","description":"Plain text extracted for search and quality checks."},"robots":{"type":"string","description":"Robots directive."},"canonicalUrl":{"type":"string","description":"Canonical URL."},"authorId":{"format":"int64","description":"Structured author id.","type":"integer"},"author":{"type":"string","description":"Public author."},"category":{"$ref":"#/components/schemas/BlogCategoryRes"},"seoScore":{"type":"integer","description":"Latest SEO score."},"updatedTime":{"type":"string","description":"Last update time."},"answerSummary":{"type":"string","description":"TL;DR answer summary."},"createTime":{"type":"string","description":"Creation time."},"title":{"type":"string","description":"Visible title."},"alternateSlug":{"type":"string","description":"Translated paired article slug."},"relatedProductIds":{"type":"string","description":"Comma-separated product ids."},"tags":{"type":"array","items":{"$ref":"#/components/schemas/BlogTagRes"}},"seoTitle":{"type":"string","description":"Search title."},"slug":{"type":"string","description":"Public slug."},"reviewedAt":{"type":"string","description":"Last reviewed time."},"keyTakeaways":{"type":"array","items":{"type":"string"}},"ogImage":{"type":"string","description":"Open Graph image URL."},"id":{"format":"int64","description":"Blog post id.","type":"integer"},"authorProfile":{"$ref":"#/components/schemas/BlogAuthorRes"},"categoryId":{"format":"int64","description":"Primary category id.","type":"integer"},"commentCount":{"type":"integer","description":"Approved comment count."},"language":{"type":"string","description":"Article language."},"publishedAt":{"type":"string","description":"Publish time."},"status":{"type":"integer","description":"0 draft, 1 published, 2 offline."},"ogDescription":{"type":"string","description":"Open Graph description."},"aeoScore":{"type":"integer","description":"Latest AEO citeability score."},"coverAlt":{"type":"string","description":"Cover image alt text."},"seoDescription":{"type":"string","description":"Search description."}}},"BlogTocItemRes":{"type":"object","properties":{"text":{"type":"string","description":"Heading text."},"level":{"type":"integer","description":"Heading level, usually 2 or 3."},"id":{"type":"string","description":"Anchor id generated from the heading."}}}}},"info":{"version":"1.0.0","description":"Public and token-protected APIs for SEO-friendly blog publishing. External systems can create a draft, run the same SEO checks as the admin editor, save all metadata, and publish only after the article passes validation.","title":"CBGAccount Blog API"}}