Skip to content

Blogs

Blogs let you publish long-form content to your SMBcrm account. List the blog sites already set up, then list, read, create, and update posts on them. Look up the authors and categories used to organize your posts.

Base URL: https://services.smbcrm.com · Version header: v3 · Scopes: blogs/list.readonly (list sites), blogs/posts.readonly (list and read posts), blogs/check-slug.readonly (check a URL slug), blogs/post.write (create a post), blogs/post-update.write (update a post), blogs/author.readonly (list authors), blogs/category.readonly (list categories). See Scopes.

GET/blogs/site/all

List the blog sites in your account.

scope blogs/list.readonlyauth Location token or PIT

locationId is required. skip and limit are optional pagination parameters. Add searchTerm to filter by name or description. Each site’s _id is the blogId you’ll use everywhere else on this page.

Terminal window
curl "https://services.smbcrm.com/blogs/site/all?locationId=<location_id>&limit=20&skip=0" \
-H "Authorization: Bearer <token>" \
-H "Version: v3"
200 OK
{
"data": [
{ "_id": "<blog_id>", "name": "Company Blog" }
]
}
GET/blogs/posts/all

List the blog posts on a blog site.

scope blogs/posts.readonlyauth Location token or PIT

locationId, blogId, limit, and offset are required. limit accepts values from 0 to 50. To read more, page through with offset. Add searchTerm to search across post title, description, URL slug, and category name, or status to filter to one of ALL, DRAFT, PUBLISHED, SCHEDULED, SCHEDULE_FAILED, ARCHIVED, or DELETED. SCHEDULE_FAILED marks scheduled posts that failed to publish.

Terminal window
curl "https://services.smbcrm.com/blogs/posts/all?locationId=<location_id>&blogId=<blog_id>&limit=20&offset=0" \
-H "Authorization: Bearer <token>" \
-H "Version: v3"
200 OK
{
"blogs": [
{
"_id": "<post_id>",
"blogId": "<blog_id>",
"locationId": "<location_id>",
"title": "5 Tips for Faster Onboarding",
"description": "Getting new customers to their first win faster.",
"status": "PUBLISHED",
"urlSlug": "5-tips-for-faster-onboarding",
"canonicalLink": "https://example.com/blog/5-tips-for-faster-onboarding",
"imageUrl": "https://example.com/images/onboarding.jpg",
"imageAltText": "A customer completing onboarding",
"author": "<author_id>",
"categories": ["<category_id>"],
"tags": ["onboarding"],
"archived": false,
"isAiGenerated": false,
"currentVersion": "<version_id>",
"publishedAt": "2026-01-15T00:00:00.000Z",
"createdAt": "2026-01-15T00:00:00.000Z",
"updatedAt": "2026-01-15T00:00:00.000Z"
}
],
"count": 1
}

count is the total number of posts that match the query, regardless of limit and offset. Page through with offset until you’ve read count posts. The list doesn’t include post bodies. Use Get a blog post to read rawHTML.

GET/blogs/posts/post/{postId}

Get one blog post, including its HTML content.

scope blogs/posts.readonlyauth Location token or PIT

postId (path) and locationId (query) are required. Unlike the list endpoint, the response includes the post body in rawHTML, along with wordCount and readTimeInMinutes. The endpoint returns published posts.

Terminal window
curl "https://services.smbcrm.com/blogs/posts/post/<post_id>?locationId=<location_id>" \
-H "Authorization: Bearer <token>" \
-H "Version: v3"
200 OK
{
"blogPost": {
"_id": "<post_id>",
"blogId": "<blog_id>",
"locationId": "<location_id>",
"title": "5 Tips for Faster Onboarding",
"description": "Getting new customers to their first win faster.",
"rawHTML": "<p>Getting new customers to their first win faster starts here.</p>",
"wordCount": 850,
"readTimeInMinutes": 4,
"status": "PUBLISHED",
"urlSlug": "5-tips-for-faster-onboarding",
"canonicalLink": "https://example.com/blog/5-tips-for-faster-onboarding",
"imageUrl": "https://example.com/images/onboarding.jpg",
"imageAltText": "A customer completing onboarding",
"author": "<author_id>",
"categories": ["<category_id>"],
"tags": ["onboarding"],
"archived": false,
"isAiGenerated": false,
"currentVersion": "<version_id>",
"publishedAt": "2026-01-15T00:00:00.000Z",
"createdAt": "2026-01-15T00:00:00.000Z",
"updatedAt": "2026-01-15T00:00:00.000Z"
}
}
POST/blogs/posts

Create a blog post.

scope blogs/post.writeauth Location token or PIT

locationId, blogId, rawHTML, and status are required. Everything else is optional: title, description, imageUrl, imageAltText, categories, tags, author, urlSlug, canonicalLink, publishedAt, wordCount, readTimeInMinutes, and archived. status is one of DRAFT, PUBLISHED, SCHEDULED, ARCHIVED, or DELETED. To schedule a post, set status to SCHEDULED and publishedAt to the time it should go live.

Terminal window
curl -X POST https://services.smbcrm.com/blogs/posts \
-H "Authorization: Bearer <token>" \
-H "Version: v3" \
-H "Content-Type: application/json" \
-d '{
"locationId": "<location_id>",
"blogId": "<blog_id>",
"title": "5 Tips for Faster Onboarding",
"description": "Getting new customers to their first win faster.",
"rawHTML": "<p>Getting new customers to their first win faster starts here.</p>",
"imageUrl": "https://example.com/images/onboarding.jpg",
"imageAltText": "A customer completing onboarding",
"status": "DRAFT",
"categories": ["<category_id>"],
"tags": ["onboarding"],
"author": "<author_id>",
"urlSlug": "5-tips-for-faster-onboarding",
"publishedAt": "2026-01-15T00:00:00.000Z"
}'
201 Created
{
"data": {
"_id": "<post_id>",
"blogId": "<blog_id>",
"locationId": "<location_id>",
"title": "5 Tips for Faster Onboarding",
"description": "Getting new customers to their first win faster.",
"status": "DRAFT",
"urlSlug": "5-tips-for-faster-onboarding",
"canonicalLink": "https://example.com/blog/5-tips-for-faster-onboarding",
"imageUrl": "https://example.com/images/onboarding.jpg",
"imageAltText": "A customer completing onboarding",
"author": "<author_id>",
"categories": ["<category_id>"],
"tags": ["onboarding"],
"archived": false,
"isAiGenerated": false,
"currentVersion": "<version_id>",
"publishedAt": "2026-01-15T00:00:00.000Z",
"createdAt": "2026-01-15T00:00:00.000Z",
"updatedAt": "2026-01-15T00:00:00.000Z"
}
}

To send only the required fields:

Terminal window
curl -X POST https://services.smbcrm.com/blogs/posts \
-H "Authorization: Bearer <token>" \
-H "Version: v3" \
-H "Content-Type: application/json" \
-d '{
"locationId": "<location_id>",
"blogId": "<blog_id>",
"rawHTML": "<p>Getting new customers to their first win faster starts here.</p>",
"status": "DRAFT"
}'
PUT/blogs/posts/{postId}

Update an existing blog post.

scope blogs/post-update.writeauth Location token or PIT

postId (path), locationId, blogId, rawHTML, and status are required. All other fields are optional: title, description, imageUrl, imageAltText, categories, tags, author, urlSlug, canonicalLink, publishedAt, wordCount, readTimeInMinutes, archived, tocStyle, and externalFonts. Set scheduledAt (ISO 8601) together with a status of SCHEDULED to schedule the post.

status is one of DRAFT, PUBLISHED, SCHEDULED, ARCHIVED, or DELETED. There is no delete endpoint: update a post with status set to DELETED to mark it as deleted. The status filter on List blog posts accepts DELETED to find those posts.

Terminal window
curl -X PUT https://services.smbcrm.com/blogs/posts/<post_id> \
-H "Authorization: Bearer <token>" \
-H "Version: v3" \
-H "Content-Type: application/json" \
-d '{
"locationId": "<location_id>",
"blogId": "<blog_id>",
"title": "5 Tips for Faster Onboarding (Updated)",
"description": "Getting new customers to their first win faster.",
"rawHTML": "<p>Getting new customers to their first win faster starts here.</p>",
"imageUrl": "https://example.com/images/onboarding.jpg",
"imageAltText": "A customer completing onboarding",
"status": "PUBLISHED",
"categories": ["<category_id>"],
"tags": ["onboarding"],
"author": "<author_id>",
"urlSlug": "5-tips-for-faster-onboarding",
"wordCount": 850,
"publishedAt": "2026-01-15T00:00:00.000Z"
}'
200 OK
{
"updatedBlogPost": {
"_id": "<post_id>",
"blogId": "<blog_id>",
"locationId": "<location_id>",
"title": "5 Tips for Faster Onboarding (Updated)",
"description": "Getting new customers to their first win faster.",
"status": "PUBLISHED",
"urlSlug": "5-tips-for-faster-onboarding",
"canonicalLink": "https://example.com/blog/5-tips-for-faster-onboarding",
"imageUrl": "https://example.com/images/onboarding.jpg",
"imageAltText": "A customer completing onboarding",
"author": "<author_id>",
"categories": ["<category_id>"],
"tags": ["onboarding"],
"archived": false,
"isAiGenerated": false,
"currentVersion": "<version_id>",
"publishedAt": "2026-01-15T00:00:00.000Z",
"createdAt": "2026-01-15T00:00:00.000Z",
"updatedAt": "2026-01-15T00:00:00.000Z"
}
}
GET/blogs/posts/url-slug-exists

Check whether a post URL slug is already in use.

scope blogs/check-slug.readonlyauth Location token or PIT

locationId and urlSlug are required. Pass postId when you’re checking the slug for a post you’re editing, so it doesn’t collide with itself.

Terminal window
curl "https://services.smbcrm.com/blogs/posts/url-slug-exists?locationId=<location_id>&urlSlug=5-tips-for-faster-onboarding&postId=<post_id>" \
-H "Authorization: Bearer <token>" \
-H "Version: v3"
200 OK
{ "exists": false }
GET/blogs/authors

List the blog authors in your account.

scope blogs/author.readonlyauth Location token or PIT

locationId, limit, and offset are required. limit accepts values from 0 to 50. To read more, page through with offset. Add searchTerm to search by author name or description, which helps you find an author’s _id before you create a post.

Terminal window
curl "https://services.smbcrm.com/blogs/authors?locationId=<location_id>&limit=20&offset=0" \
-H "Authorization: Bearer <token>" \
-H "Version: v3"
200 OK
{
"authors": [
{
"_id": "<author_id>",
"name": "Jordan Lee",
"locationId": "<location_id>",
"description": "Writes about customer onboarding.",
"role": "author",
"imageUrl": "https://example.com/images/jordan-lee.jpg",
"imageAltText": "Portrait of Jordan Lee",
"socials": [
{ "type": "twitter", "url": "https://twitter.com/example" }
],
"canonicalLink": "https://example.com/authors/jordan-lee",
"updatedAt": "2026-01-15T00:00:00.000Z"
}
],
"count": 1
}

count is the total number of authors that match the query, regardless of limit and offset. description, role, imageUrl, imageAltText, socials, and canonicalLink are optional and can be absent.

GET/blogs/categories

List the blog categories in your account.

scope blogs/category.readonlyauth Location token or PIT

locationId, limit, and offset are required. limit accepts values from 0 to 50. To read more, page through with offset. Add searchTerm to search by category label or description, which helps you find a category’s _id before you create a post.

Terminal window
curl "https://services.smbcrm.com/blogs/categories?locationId=<location_id>&limit=20&offset=0" \
-H "Authorization: Bearer <token>" \
-H "Version: v3"
200 OK
{
"categories": [
{
"_id": "<category_id>",
"label": "Product Updates",
"locationId": "<location_id>",
"urlSlug": "product-updates",
"description": "News about new features and improvements.",
"imageUrl": "https://example.com/images/product-updates.jpg",
"imageAltText": "Product updates banner",
"canonicalLink": "https://example.com/categories/product-updates",
"updatedAt": "2026-01-15T00:00:00.000Z"
}
],
"count": 1
}

count is the total number of categories that match the query, regardless of limit and offset. description, imageUrl, imageAltText, and canonicalLink are optional and can be absent.

  • Social Planner: schedule and publish social content alongside your blog posts.
  • Locations: look up the locationId every endpoint on this page requires.
  • Scopes: permissions reference for the blogs/* scopes.