CBGAccount developer documentation

Blog API documentation

Public and token-protected APIs for reading, checking, saving, and publishing SEO-ready CBGAccount blog stories.

Publishing workflow

Create a draft, run the same SEO check, then publish

External systems should follow the same flow as the admin editor: read categories and tags, save a draft with all SEO fields, run the publishing check, fix blocking items, then publish.

OpenAPI JSONhttps://www.cbgaccount.com/api/v1/blog/openapi.jsonPublic API Basehttps://www.cbgaccount.comMedia URL Basehttps://media.cbgaccount.com

Authentication

Token model

Anonymous endpoints

Published posts, categories, tags, authors, RSS, sitemap, robots, and OpenAPI JSON are publicly readable.

Token endpoints

SEO checks, saving posts, publishing, unpublishing, deleting, and taxonomy writes use API Tokens. Third-party systems never log in to the admin backend; a CBGAccount admin creates a scoped token once and gives it to the integration owner.

Authorization: Bearer cbg_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
X-API-Token: cbg_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Contract basics

Response wrapper, scopes, limits, and ownership

Result wrapper

JSON APIs return the same wrapper shape used by the admin backend. Treat code=0000 as success; all other codes should be handled as business or validation failures.

{
  "code": "0000",
  "message": "success",
  "data": "{ endpoint specific payload }"
}
Token scopes

Use blog:read for read audit, blog:write for SEO checks, drafts, taxonomy writes, author writes, and media uploads, and blog:publish for publishing, unpublishing, deleting, and status operations.

Authorization: Bearer <API_TOKEN>
X-API-Token: <API_TOKEN>
Rate limit and audit log

Each token plus IP is limited to 120 requests per minute. Token usage, required scope, path, status, message, IP, and latency are visible in the admin Token logs.

HTTP 200 + business error code when the request is rejected by API policy.
Public versus admin boundary

The public docs cover external /api/v1/blog/* contracts. Third-party callers use token auth only. Token creation, token rotation, online debugging, webhook receiver setup, Search Console actions, and moderation remain admin-only.

Create tokens in admin

Go to Blog API documentation and Token Management in the admin backend. The raw token is displayed only once after creation, then only a masked value is stored for listing. External users receive the token value, not an admin account.

Use least privilege

Give external readers blog:read only. Give importers blog:write for drafts and SEO checks. Only trusted publishing systems should receive blog:publish.

Keep tokens server-side

Never ship a write or publish token in browser JavaScript. Store it in a backend secret manager or environment variable and rotate it when staff, vendors, or integrations change.

Recommended sequence

SEO-ready publishing flow

  1. Read taxonomyGET /categories and /tags so the article links into crawlable category and tag pages.
  2. Upload mediaUpload cover, body, and OG images through /api/v1/blog/media/upload with a blog:write token, then save the returned CloudFlare-ImgBed HTTPS URL directly.
  3. Save draftPOST /posts/save with status=0 and include title, summary, contentHtml, authorId, categoryId, tagIds, cover alt, canonical, robots, OG, FAQ, and takeaways.
  4. Run SEO checkPOST /posts/check to get score, canPublish, blocking items, generated slug, SEO title, description, excerpt, and table of contents.
  5. Fix blocking itemsResolve missing H1/H2, thin content, duplicate slug, weak summary, missing alt text, missing internal links, or missing structured author.
  6. PublishPOST /posts/{id}/publish. The backend refreshes public APIs, sitemap, RSS, Last-Modified/ETag, and webhook events.

Best practices

Recommended third-party implementation checklist

Call sequence

  1. Upload images firstPOST /api/v1/blog/media/upload for cover images, body images, and OG images. Use the returned CloudFlare-ImgBed HTTPS URL as coverImage, ogImage, and img src.
  2. Create taxonomy and authors when neededPOST /api/v1/blog/categories/save, /api/v1/blog/tags/save, and /api/v1/blog/authors/save before saving a post that depends on new categoryId, tagIds, or authorId values.
  3. Prepare business resource cards when neededGET /api/v1/blog/resources/categories and POST /api/v1/blog/resources/search, then insert crawlable resource-card HTML and save relatedProductIds.
  4. Save a full SEO draftPOST /api/v1/blog/posts/save with status=0 and all editor, SEO, OG, FAQ, internal-link, media, and resource fields.
  5. Run the publishing checkPOST /api/v1/blog/posts/check. Use score, canPublish, items, generatedSlug, generatedSeoTitle, generatedSeoDescription, generatedOgTitle, and toc to repair the draft.
  6. Fill the remaining SEO gapsUpdate slug, SEO title, description, OG fields, FAQ, internal links, cover alt, canonical, robots, and related resources before publishing.
  7. Publish only after blocking items passPOST /api/v1/blog/posts/{id}/publish. This refreshes the public article, sitemap, RSS, cache headers, and webhook events.

Core SEO and content fields

A third-party CMS can publish the same article shape as the admin editor when it saves these fields explicitly. Empty canonical means self-canonical; CloudFlare-ImgBed HTTPS URLs can be saved directly.

language, title, summary, contentHtml, coverImage, coverAlt, categoryId, tagIds, authorId, slug, alternateSlug, seoTitle, seoDescription, canonicalUrl, robots, indexable, ogTitle, ogDescription, ogImage, answerSummary, keyTakeaways, faqBlocks, relatedProductIds, status

Endpoint coverage

All public, token, and media endpoints

GET

List published posts

Paginated public articles for blog lists, archives, internal link pickers, and external readers.

/api/v1/blog/posts
Auth
Anonymous, optional Bearer token for audit logs
Scope
blog:read optional
Response
Result<PageBlogPostRes>

Inputs

  • query language: en or zh
  • query current and size
  • query categoryId, tagId, authorId, keyword

Use for

  • Render blog index and archives
  • Power internal-link search in editors
  • Sync published stories to external tools
curl
curl "https://www.cbgaccount.com/api/v1/blog/posts?language=en&current=1&size=10"
Response example
{
  "code": "0000",
  "message": "success",
  "data": "Result<PageBlogPostRes>"
}
GET

Read post detail

Full SEO article payload: HTML body, meta fields, canonical, robots, Open Graph, author, tags, TOC, related posts, and engagement counts.

/api/v1/blog/posts/{slug}
Auth
Anonymous, optional Bearer token for audit logs
Scope
blog:read optional
Response
Result<BlogPostRes>, 301 for old slug redirects

Inputs

  • path slug
  • query language: defaults to en

Use for

  • SSR article pages
  • Structured data generation
  • External article mirrors that preserve canonical URLs
curl
curl "https://www.cbgaccount.com/api/v1/blog/posts/account-infrastructure-growth-workflows?language=en"
Response example
{
  "code": "0000",
  "message": "success",
  "data": "Result<BlogPostRes>, 301 for old slug redirects"
}
POST

Run publishing check

Preflight check using the same rules as the admin editor: score, AEO score, canPublish, blocking items, generated slug, title, description, excerpt, and TOC.

/api/v1/blog/posts/check
Auth
Bearer token required
Scope
blog:write
Response
Result<BlogSeoCheckRes>

Inputs

  • body BlogSeoCheckReq
  • title, contentHtml, language, categoryId are required
  • seoTitle, seoDescription, canonicalUrl, authorId, faqBlocks, keyTakeaways are recommended

Use for

  • Block low-quality drafts before publishing
  • Show beginner-friendly fix actions
  • Generate SEO defaults before save
curl
curl -X POST -H "Authorization: Bearer <API_TOKEN>" -H "content-type: application/json" -d @draft.json "https://www.cbgaccount.com/api/v1/blog/posts/check"
Response example
{
  "code": "0000",
  "message": "success",
  "data": "Result<BlogSeoCheckRes>"
}
POST

Create or update post

Persists every editor SEO field and content block. Create a draft with id empty, update an article with id present.

/api/v1/blog/posts/save
Auth
Bearer token required
Scope
blog:write, blog:publish when status=1
Response
Result<BlogPostRes>

Inputs

  • body BlogPostSaveReq (BlogPostSaveRequest in generated SDKs)
  • status 0 draft, 1 published, 2 offline
  • contentHtml can include figures, videos, tables, FAQ blocks, internal links, and product/resource cards

Use for

  • External CMS draft creation
  • Save all metadata from a custom editor
  • Publish directly only after the SEO check passes
curl
curl -X POST -H "Authorization: Bearer <API_TOKEN>" -H "content-type: application/json" -d @post-save.json "https://www.cbgaccount.com/api/v1/blog/posts/save"
Response example
{
  "code": "0000",
  "message": "success",
  "data": "Result<BlogPostRes>"
}
POST

Publish post

Runs the SEO check again, publishes the saved draft, refreshes public discovery outputs, and dispatches webhook events.

/api/v1/blog/posts/{id}/publish
Auth
Bearer token required
Scope
blog:publish
Response
Result<BlogPostRes>

Inputs

  • path id: blog post id

Use for

  • Final publish step after manual or automated QA
  • Update sitemap, RSS, Last-Modified, ETag, and webhook delivery
curl
curl -X POST -H "Authorization: Bearer <API_TOKEN>" "https://www.cbgaccount.com/api/v1/blog/posts/1/publish"
Response example
{
  "code": "0000",
  "message": "success",
  "data": "Result<BlogPostRes>"
}
GET

Publish or unpublish by status

Status operation for admin-style workflows. Use publish for normal releases; use this mainly for taking posts offline.

/api/v1/blog/posts/operate
Auth
Bearer token required
Scope
blog:publish
Response
Result<boolean>

Inputs

  • query id
  • query status: 1 published, 2 offline

Use for

  • Unpublish stale content
  • Repair status after a migration
curl
curl -H "Authorization: Bearer <API_TOKEN>" "https://www.cbgaccount.com/api/v1/blog/posts/operate?id=1&status=2"
Response example
{
  "code": "0000",
  "message": "success",
  "data": "Result<boolean>"
}
GET

Delete post

Deletes a post and removes it from public discovery. Prefer unpublishing when SEO history should be preserved.

/api/v1/blog/posts/delete
Auth
Bearer token required
Scope
blog:publish
Response
Result<boolean>

Inputs

  • query id

Use for

  • Remove accidental test content
  • Clean failed imports before launch
curl
curl -H "Authorization: Bearer <API_TOKEN>" "https://www.cbgaccount.com/api/v1/blog/posts/delete?id=1"
Response example
{
  "code": "0000",
  "message": "success",
  "data": "Result<boolean>"
}
GET

Read engagement

Returns clap count, approved comment count, and approved public comments without private moderation fields.

/api/v1/blog/posts/{id}/engagement
Auth
Anonymous, optional Bearer token for audit logs
Scope
blog:read optional
Response
Result<BlogEngagementRes>

Inputs

  • path id: blog post id

Use for

  • Render Medium-like interaction counters
  • Fetch approved comments for an article
curl
curl "https://www.cbgaccount.com/api/v1/blog/posts/1/engagement"
Response example
{
  "code": "0000",
  "message": "success",
  "data": "Result<BlogEngagementRes>"
}
POST

Add reaction

Adds a clap-style recommendation with a client idempotency key.

/api/v1/blog/posts/{id}/reactions
Auth
Anonymous, optional Bearer token for audit logs
Scope
blog:read optional
Response
Result<BlogEngagementRes>

Inputs

  • path id
  • body reactionKey, clientKey, count

Use for

  • Article recommend button
  • Track lightweight reader intent without login
curl
curl -X POST -H "content-type: application/json" -d '{"reactionKey":"clap","clientKey":"browser-session-1","count":1}' "https://www.cbgaccount.com/api/v1/blog/posts/1/reactions"
Response example
{
  "code": "0000",
  "message": "success",
  "data": "Result<BlogEngagementRes>"
}
POST

Submit comment

Creates a pending comment. Public responses hide email, IP, user agent, spam reason, and internal post title.

/api/v1/blog/posts/{id}/comments
Auth
Anonymous, optional Bearer token for audit logs
Scope
blog:read optional
Response
Result<BlogPublicCommentRes>

Inputs

  • path id
  • body authorName, authorEmail, content, optional parentId

Use for

  • Article response form
  • Moderated reader discussion
curl
curl -X POST -H "content-type: application/json" -d '{"authorName":"Alex","authorEmail":"[email protected]","content":"Useful guide."}' "https://www.cbgaccount.com/api/v1/blog/posts/1/comments"
Response example
{
  "code": "0000",
  "message": "success",
  "data": "Result<BlogPublicCommentRes>"
}
GET

List categories

Enabled public categories for primary grouping and crawlable category pages.

/api/v1/blog/categories
Auth
Anonymous, optional Bearer token for audit logs
Scope
blog:read optional
Response
Result<BlogCategoryRes[]>

Inputs

  • no required parameters

Use for

  • Build category navigation
  • Choose categoryId before saving a post
curl
curl "https://www.cbgaccount.com/api/v1/blog/categories"
Response example
{
  "code": "0000",
  "message": "success",
  "data": "Result<BlogCategoryRes[]>"
}
POST

Create or update category

Creates or updates a category with localized names and descriptions.

/api/v1/blog/categories/save
Auth
Bearer token required
Scope
blog:write (media upload)
Response
Result<BlogCategoryRes>

Inputs

  • body id, slug, nameZh, nameEn, descriptionZh, descriptionEn, sort, status

Use for

  • Prepare taxonomy before bulk imports
  • Keep category pages crawlable and descriptive
curl
curl -X POST -H "Authorization: Bearer <API_TOKEN>" -H "content-type: application/json" -d '{"nameEn":"Growth Playbooks","nameZh":"增长业务剧本","slug":"growth-playbooks","status":1}' "https://www.cbgaccount.com/api/v1/blog/categories/save"
Response example
{
  "code": "0000",
  "message": "success",
  "data": "Result<BlogCategoryRes>"
}
GET

List tags

Enabled tags grouped by language so public topic pages and admin filters stay aligned.

/api/v1/blog/tags
Auth
Anonymous, optional Bearer token for audit logs
Scope
blog:read optional
Response
Result<BlogTagRes[]>

Inputs

  • query language: en, zh, or all

Use for

  • Render topic pages
  • Choose tagIds before saving a post
curl
curl "https://www.cbgaccount.com/api/v1/blog/tags?language=en"
Response example
{
  "code": "0000",
  "message": "success",
  "data": "Result<BlogTagRes[]>"
}
POST

Create or update tag

Creates or updates a language-aware tag.

/api/v1/blog/tags/save
Auth
Bearer token required
Scope
blog:write
Response
Result<BlogTagRes>

Inputs

  • body id, slug, language, nameZh, nameEn, status

Use for

  • Organize topics by language
  • Improve related-post and internal-link matching
curl
curl -X POST -H "Authorization: Bearer <API_TOKEN>" -H "content-type: application/json" -d '{"language":"all","nameEn":"Account Operations","nameZh":"账号业务运营","slug":"account-operations","status":1}' "https://www.cbgaccount.com/api/v1/blog/tags/save"
Response example
{
  "code": "0000",
  "message": "success",
  "data": "Result<BlogTagRes>"
}
POST

Create or update author

Creates or updates the structured author profile used by author pages, publication cards, and Person JSON-LD. Use author text only as a fallback; authorId gives stronger SEO output.

/api/v1/blog/authors/save
Auth
Bearer token required
Scope
blog:write
Response
Result<BlogAuthorRes>

Inputs

  • body id, slug, language, name, title, bio, avatar, credentials, socialLinks, status, sort

Use for

  • Prepare authorId before saving a post
  • Keep author authority metadata consistent across imported content
curl
curl -X POST -H "Authorization: Bearer <API_TOKEN>" -H "content-type: application/json" -d '{"language":"en","slug":"cbgaccount-editorial-team","name":"CBGAccount Editorial Team","title":"Account operations editorial team","status":1}' "https://www.cbgaccount.com/api/v1/blog/authors/save"
Response example
{
  "code": "0000",
  "message": "success",
  "data": "Result<BlogAuthorRes>"
}
GET

List authors

Enabled structured authors for public author cards, author pages, and Person JSON-LD.

/api/v1/blog/authors
Auth
Anonymous, optional Bearer token for audit logs
Scope
blog:read optional
Response
Result<BlogAuthorRes[]>

Inputs

  • query language: en or zh

Use for

  • Choose authorId before saving a post
  • Render public author directories
curl
curl "https://www.cbgaccount.com/api/v1/blog/authors?language=en"
Response example
{
  "code": "0000",
  "message": "success",
  "data": "Result<BlogAuthorRes[]>"
}
GET

Read author profile

Public author profile with bio, credentials, avatar, social links, and post count.

/api/v1/blog/authors/{slug}
Auth
Anonymous, optional Bearer token for audit logs
Scope
blog:read optional
Response
Result<BlogAuthorRes>

Inputs

  • path slug
  • query language: defaults to en

Use for

  • SSR author profile pages
  • Build author authority signals
curl
curl "https://www.cbgaccount.com/api/v1/blog/authors/cbgaccount-editorial-team?language=en"
Response example
{
  "code": "0000",
  "message": "success",
  "data": "Result<BlogAuthorRes>"
}
GET

List author posts

Paginated published posts linked to an enabled author.

/api/v1/blog/authors/{slug}/posts
Auth
Anonymous, optional Bearer token for audit logs
Scope
blog:read optional
Response
Result<PageBlogPostRes>

Inputs

  • path slug
  • query language, current, size

Use for

  • Public author archives
  • Editorial profile pages
curl
curl "https://www.cbgaccount.com/api/v1/blog/authors/cbgaccount-editorial-team/posts?language=en&current=1&size=10"
Response example
{
  "code": "0000",
  "message": "success",
  "data": "Result<PageBlogPostRes>"
}
GET

Read publication settings

Returns the public publication mark used by blog home, article pages, author cards, and publication cards. It never exposes admin-only SEO, AI, Search Console, or media provider secrets.

/api/v1/blog/publication-settings
Auth
Anonymous, optional Bearer token for audit logs
Scope
blog:read optional
Response
Result<BlogPublicationSettingsRes>

Inputs

  • no required parameters

Use for

  • Render publication logo
  • Keep public brand metadata aligned with admin settings
curl
curl "https://www.cbgaccount.com/api/v1/blog/publication-settings"
Response example
{
  "code": "0000",
  "message": "success",
  "data": "Result<BlogPublicationSettingsRes>"
}
GET

List business resource categories

Returns public account/business resource categories so external publishers can build the same resource picker as the admin editor.

/api/v1/blog/resources/categories
Auth
Bearer token required
Scope
blog:read
Response
Result<BlogResourceCategoryRes[]>

Inputs

  • no required parameters

Use for

  • Filter business resources before insertion
  • Create crawlable product/resource card links in contentHtml
curl
curl -H "Authorization: Bearer <API_TOKEN>" "https://www.cbgaccount.com/api/v1/blog/resources/categories"
Response example
{
  "code": "0000",
  "message": "success",
  "data": "Result<BlogResourceCategoryRes[]>"
}
POST

Search business resources

Searches active public account/business resources. Use the returned id, name, description, category, and price to build a readable resource card, then set relatedProductIds on the post. Product descriptions can contain storefront HTML, so strip tags for picker summaries and escape any inserted card text. Product prices use the main storefront storage unit: display usdtPrice as usdtPrice / 10000. The crawlable public resource URL is /en/products/{id}-{slugified nameEn} for English content and /cn/products/{id}-{slugified nameZh or product} for Chinese content.

/api/v1/blog/resources/search
Auth
Bearer token required
Scope
blog:read
Response
Result<PageBlogResourceRes>

Inputs

  • body current and size
  • body keywords: optional
  • body categoryCode: optional
  • body status: defaults to 1 active

Use for

  • External resource-card picker
  • Keep relatedProductIds aligned with inserted HTML cards
curl
curl -X POST -H "Authorization: Bearer <API_TOKEN>" -H "content-type: application/json" -d '{"current":1,"size":12,"keywords":"regional account","status":1}' "https://www.cbgaccount.com/api/v1/blog/resources/search"
Response example
{
  "code": "0000",
  "message": "success",
  "data": "Result<PageBlogResourceRes>"
}
POST

Upload media asset

Uploads cover, body, OG, author, or publication media for external publishing integrations. CBGAccount defaults this workflow to CloudFlare-ImgBed, so data is the final public HTTPS URL and must not be prefixed with the API base URL.

/api/v1/blog/media/upload
Auth
Bearer token required
Scope
blog:write
Response
Result<string>

Inputs

  • multipart/form-data file
  • Authorization: Bearer token with blog:write
  • recommended image formats: webp, avif, jpg, png

Use for

  • Create coverImage and ogImage URLs
  • Insert SEO images into contentHtml
  • Use stable media URLs in ImageObject and Open Graph metadata
curl
curl -X POST -H "Authorization: Bearer <API_TOKEN>" -F "file=@./cover.webp" "https://www.cbgaccount.com/api/v1/blog/media/upload"
Response example
{
  "code": "0000",
  "message": "success",
  "data": "https://media.cbgaccount.com/file/blog-assets/account-infrastructure-growth-workflows.webp"
}
GET

RSS feed

RSS 2.0 feed for subscription tools and readers.

/api/v1/blog/rss.xml
Auth
Anonymous
Scope
-
Response
application/xml

Inputs

  • query language: defaults to en

Use for

  • RSS subscription
  • External feed readers
curl
curl "https://www.cbgaccount.com/api/v1/blog/rss.xml?language=en"
Response example
{
  "code": "0000",
  "message": "success",
  "data": "application/xml"
}
GET

Sitemap XML

Sitemap mirror for crawlers and integrations. The primary public route is /sitemap.xml.

/api/v1/blog/sitemap.xml
Auth
Anonymous
Scope
-
Response
application/xml

Inputs

  • no required parameters

Use for

  • Crawler discovery
  • Search Console sitemap submission
curl
curl "https://www.cbgaccount.com/api/v1/blog/sitemap.xml"
Response example
{
  "code": "0000",
  "message": "success",
  "data": "application/xml"
}
GET

Robots.txt

Robots directives mirror. The primary public route is /robots.txt.

/api/v1/blog/robots.txt
Auth
Anonymous
Scope
-
Response
text/plain

Inputs

  • no required parameters

Use for

  • Crawler policy checks
  • SEO smoke tests
curl
curl "https://www.cbgaccount.com/api/v1/blog/robots.txt"
Response example
{
  "code": "0000",
  "message": "success",
  "data": "text/plain"
}
GET

OpenAPI JSON

Machine-readable OpenAPI 3.0 document with schemas, request bodies, auth scopes, and responses.

/api/v1/blog/openapi.json
Auth
Anonymous
Scope
-
Response
application/json

Inputs

  • no required parameters

Use for

  • Import into Postman, Apifox, or Swagger UI
  • Generate SDKs and contract tests
curl
curl "https://www.cbgaccount.com/api/v1/blog/openapi.json"
Response example
{
  "code": "0000",
  "message": "success",
  "data": "application/json"
}

Post body

Fields needed for a complete SEO article

idnumber

Leave empty to create a new draft. Send the existing article id to update or publish a saved post.

Required
No for create, yes for update
Editor source
Hidden article record
SEO check
Used to decide create versus update and publish target.
languagestring

Determines public route, language-specific tags, alternate links, and localized rendering.

Required
Yes
Editor source
Basic information
SEO check
Must be en or zh and should match localized tags, routes, hreflang, and content language.
titlestring

Visible article title and primary H1 source. Use reader language, not internal campaign names.

Required
Yes
Editor source
Basic information
SEO check
Checked for H1 alignment, search intent clarity, and reasonable length.
summarystring

Public excerpt and fallback meta description. Explain what problem the article solves.

Required
Yes
Editor source
Basic information
SEO check
Checked for useful first-screen excerpt and meta description fallback quality.
slugstring

URL short name. Keep it stable after publish; the check endpoint can generate a draft slug.

Required
Recommended
Editor source
Basic information or generated default
SEO check
Checked for uniqueness, lowercase readability, and redirect risk after publish.
alternateSlugstring

Slug of the translated counterpart used for bilingual alternates.

Required
When bilingual counterpart exists
Editor source
Language version mapping
SEO check
Checked so hreflang can point to the other language version.
contentHtmlHTML string

Semantic article body. It can include figures, responsive images, videos, tables, quotes, code, FAQ blocks, internal links, and account/resource cards.

Required
Yes
Editor source
Body editor
SEO check
Checked for H1/H2 structure, thin content, heading jumps, image alt, video embeds, tables, FAQ, and internal links.
coverImage / coverAltstring

Primary visual URL and human-readable alt text. Prefer URLs returned by /api/v1/blog/media/upload; CloudFlare-ImgBed HTTPS URLs can be saved directly.

Required
Strongly recommended
Editor source
Media block
SEO check
coverAlt is checked because images affect accessibility, ImageObject, Open Graph, and list cards.
categoryIdnumber

Primary category for navigation, archive grouping, and related content matching.

Required
Yes
Editor source
Basic information
SEO check
Required so every post belongs to a crawlable category page.
tagIdsnumber[]

Topic tags for public topic pages, recommendations, and internal link discovery.

Required
Recommended
Editor source
Basic information
SEO check
Checked for language-aware topic consistency and related-post matching.
authorId / authornumber / string

Bind authorId whenever possible; author text is only a fallback display name.

Required
Recommended
Editor source
Author selector
SEO check
Structured author profile is preferred for Person JSON-LD and author pages.
seoTitle / seoDescriptionstring

Search title and description. Blank values can be generated by /posts/check, then saved explicitly.

Required
Recommended
Editor source
SEO settings or generated defaults
SEO check
Checked for length, duplication, search result usefulness, and title/summary mismatch.
canonicalUrlstring

Canonical URL used when this post should consolidate signals to another official URL.

Required
Optional
Editor source
Advanced SEO
SEO check
Checked for valid URL and production-domain mismatch. Leave blank for self-canonical.
robots / indexablestring / boolean

Indexing controls. Normal publishable posts should be indexable with robots=index,follow.

Required
Optional
Editor source
Advanced SEO
SEO check
Warns when publishable public content is accidentally noindex or nofollow.
ogTitle / ogDescription / ogImagestring

Open Graph metadata for social sharing and external previews.

Required
Recommended
Editor source
Social preview
SEO check
Checked so shared cards do not fall back to weak or missing metadata.
answerSummary / keyTakeawaysstring / string[]

Short answer and takeaways used by article summaries, structured content, and reader scanning.

Required
Recommended
Editor source
SEO assistant
SEO check
Checked for concise answer quality and AEO usefulness.
faqBlocksArray<{ question, answer }>

FAQ blocks used in the article body and FAQPage JSON-LD when valid.

Required
Recommended when the article answers concrete questions
Editor source
FAQ block
SEO check
Checked for question/answer completeness before FAQ schema is emitted.
relatedProductIdscomma-separated string

Comma-separated real resource ids selected from the resource search API, for example "12,18".

Required
Optional
Editor source
Resource/account selector
SEO check
Checked as contextual internal links, not as a requirement for every article.
reviewedAtdatetime string

Last expert or editor review timestamp.

Required
Optional
Editor source
Publish confirmation
SEO check
Used for freshness and editorial review signals on evergreen content.
statusnumber

0 draft, 1 published, 2 offline.

Required
Yes
Editor source
Publish status
SEO check
status=1 requires blog:publish and a passing SEO check.

Examples

Complete publishable API workflow

Complete save request

Send this body to POST /api/v1/blog/posts/save with status=0 to create a draft that already contains the same SEO fields exposed by the admin editor.

{
  "language": "en",
  "title": "Account Infrastructure for Global Growth Workflows",
  "summary": "How teams use ready-to-operate accounts for marketplace launches, regional access, creator operations, and support workflows.",
  "slug": "account-infrastructure-growth-workflows",
  "alternateSlug": "account-infrastructure-growth-workflows-zh",
  "contentHtml": "<h1>Account Infrastructure for Global Growth Workflows</h1><p>Explain the business use case in the first paragraph.</p><h2>Validate regional access before scaling</h2><p>Add concrete workflow evidence and an internal link.</p><figure><img src=\"https://media.cbgaccount.com/file/blog-assets/account-infrastructure-growth-workflows.webp\" alt=\"Account infrastructure workflow diagram for marketplace launch and regional access\" width=\"1200\" height=\"675\" /></figure><h2>Frequently asked questions</h2>",
  "coverImage": "https://media.cbgaccount.com/file/blog-assets/account-infrastructure-growth-workflows.webp",
  "coverAlt": "Account infrastructure workflow diagram for marketplace launch and regional access",
  "categoryId": 1,
  "tagIds": [
    1,
    2
  ],
  "authorId": 1,
  "seoTitle": "Account Infrastructure for Global Growth Workflows | CBGAccount",
  "seoDescription": "Learn how account infrastructure supports marketplace launches, regional access, creator operations, and safer support workflows.",
  "canonicalUrl": "",
  "robots": "index,follow",
  "indexable": true,
  "ogTitle": "Account Infrastructure for Global Growth Workflows",
  "ogDescription": "A practical operating guide for marketplace, regional, creator, and support account workflows.",
  "ogImage": "https://media.cbgaccount.com/file/blog-assets/account-infrastructure-growth-workflows.webp",
  "answerSummary": "Account infrastructure helps teams validate access, ownership, support, and workflow evidence before scaling account-led operations.",
  "keyTakeaways": [
    "Map ownership and recovery before launch",
    "Keep internal links and evidence visible",
    "Review high-value posts after operational changes"
  ],
  "faqBlocks": [
    {
      "question": "When should a team prepare account infrastructure?",
      "answer": "Before launching a new market, creator workflow, support queue, or marketplace operation that depends on repeatable account access."
    }
  ],
  "relatedProductIds": "12,18",
  "reviewedAt": "2026-05-25 12:00:00",
  "status": 0
}
SEO check response

POST /api/v1/blog/posts/check does not save data. Use its suggestions to fill slug, meta, excerpt, OG, and table of contents before saving again.

{
  "code": "0000",
  "message": "success",
  "data": {
    "score": 92,
    "aeoScore": 88,
    "canPublish": true,
    "scoreSummary": "Ready to publish after confirming the canonical URL and final image alt text.",
    "generatedSlug": "account-infrastructure-growth-workflows",
    "generatedSeoTitle": "Account Infrastructure for Global Growth Workflows | CBGAccount",
    "generatedSeoDescription": "Learn how account infrastructure supports marketplace launches, regional access, creator operations, and support workflows.",
    "generatedOgTitle": "Account Infrastructure for Global Growth Workflows",
    "generatedExcerpt": "A practical operating guide for account-led growth teams.",
    "toc": [
      {
        "id": "validate-regional-access-before-scaling",
        "title": "Validate regional access before scaling",
        "level": 2
      },
      {
        "id": "frequently-asked-questions",
        "title": "Frequently asked questions",
        "level": 2
      }
    ],
    "items": [
      {
        "key": "title-length",
        "passed": true,
        "severity": "info",
        "message": "SEO title length is in range."
      },
      {
        "key": "internal-links",
        "passed": true,
        "severity": "info",
        "message": "The article includes internal links."
      }
    ]
  }
}
Publish response

POST /api/v1/blog/posts/{id}/publish runs the SEO check again and only publishes when blocking items pass.

{
  "code": "0000",
  "message": "success",
  "data": {
    "id": 42,
    "slug": "account-infrastructure-growth-workflows",
    "title": "Account Infrastructure for Global Growth Workflows",
    "status": 1,
    "publishedAt": "2026-05-25 12:30:00",
    "canonicalUrl": "https://www.cbgaccount.com/blog/account-infrastructure-growth-workflows",
    "robots": "index,follow",
    "seoScore": 92,
    "sitemapUpdated": true,
    "rssUpdated": true,
    "webhookQueued": true
  }
}
Error response

Do not publish when code is not 0000. Show message and failedItems to the operator so they can fix the article.

{
  "code": "BLOG_SEO_BLOCKED",
  "message": "The draft cannot be published because blocking SEO checks failed.",
  "data": {
    "canPublish": false,
    "failedItems": [
      "missing-cover-alt",
      "thin-content",
      "duplicate-slug"
    ]
  }
}

Automation

Webhook events, signatures, retries, and debugging

Webhook event model

Configure webhook receivers in the admin backend. Public docs describe the contract; the secret and delivery logs stay behind admin login.

  • blog.post.published
  • blog.post.unpublished
  • blog.post.deleted
  • blog.*

Signature and retry policy

X-CBG-Event: blog.post.published
X-CBG-Signature: t=1710000000,v1=hex(hmac_sha256(secret, t + "." + rawBody))

Verify the timestamp, raw body, and HMAC before accepting a delivery. Failed deliveries retry at 5, 10, and 15 minute intervals up to five attempts.

POST/api/admin/blog/webhooks/saveAdmin-only setup endpoint. External developers provide a receiver URL and secret to the CBGAccount admin; they do not log in to the admin backend.
GET/api/admin/blog/webhooks/eventsAdmin-only delivery log for status, response body, retry count, and failure diagnosis.
OpenAPI import

Import /api/v1/blog/openapi.json into Postman, Apifox, Swagger UI, or an SDK generator. Use the generated schema as the source of truth for automated tests.

Online debug location

The public page intentionally does not execute token-protected writes. Use the admin API documentation page for online debugging after login.

Production public URL

When the site is published, expose /blog/api and /zh/blog/api on the public internet so partners can read docs without admin access.