You can use the blog post API to publish and manage blog posts. Learn more about how to create and maintain your blog on the HubSpot Knowledge Base.
- The following properties are deprecated and will not be included in the response of any of the V3 endpoints:
campaign_name
is_draft
keywords
- The
topicIds
property has been renamed totagIds
.
You can retrieve blog posts either individually by ID or by retrieving all blog posts:
- To retrieve an individual blog post, make a
GET
request to/cms/v3/blogs/posts/<postId>
. - To retrieve all blog posts, make a
GET
request to/cms/v3/blogs/posts
.
When retrieving all blog posts, you can filter and sort the returned posts using the operators and properties below. You can also use the standard filters using the createdAt
and updatedAt
dates. Learn more about the available filtering, sorting, and pagination options below.
Provide any filters as query parameters in your request, by adding the property name
, followed by two underscore characters, then include the associated operator
as a suffix. For example, you can filter the results to only include blog posts where the name
property contains the word marketing
using the parameter: &name__contains=marketing
.
You can include any number of the following filters as query parameters in the request URL. All specified filters will be applied to narrow down results.
Filter | Operator |
---|---|
Equals | eq (or none) |
Not equal | ne |
Contains | contains |
Less than | lt |
Less than or equal | lte |
Greater than | gt |
Greater than or equal | gte |
Null | is_null |
Not null | not_null |
Like | like |
Not like | not_like |
Contains (case insensitive) | icontains |
Starts with | startswith |
In | in |
Not in | nin |
The table below lists the properties that can be filtered on, along with their supported filter types.
Property | Supported filters |
---|---|
id | eq , in |
slug | eq , in , nin , icontains |
campaign | eq , in |
state | eq , Not equal , in , nin , contains |
publishDate | eq , gt , gte , lt ,lte |
createdAt | eq , gt , gte , lt ,lte |
updatedAt | eq , gt , gte , lt ,lte |
name | eq , in , icontains |
archivedAt | eq , gt , gte , lt ,lte |
createdById | eq |
updatedById | eq |
blogAuthorId | eq , in |
translatedFromId | is_null , not_null |
contentGroupId | eq , in |
tagId | eq , in |
The table below lists the query parameters you can use to filter by publish state.
Publish State | Query parameters |
---|---|
Draft | state=DRAFT |
Scheduled | state=SCHEDULED |
Published | state=PUBLISHED |
Please note: the currentState
field on the blog post object is a generated field which also reflects the blog's publish state, but you cannot use it as a property to filter against in your requests.
To filter blog posts based on a multi-language group, you can include one of the query parameters in the table below. For example, to get blog posts associated with a German variation of your blog, you'd include contentGroupId__eq=<germanBlogId>
as a query parameter.
Description | Query parameters |
---|---|
Primary blog post in a multi-language group | translatedFromId__is_null |
Variation blog post in a multi-language group | translatedFromId__not_null |
Blog post with specific language | contentGroupId__eq |
You can provide sorting and pagination options as query parameters. Specify the property name as the value to the sort
query parameter to return the blog posts in the natural order of that property. You can reverse the sorting order by including a dash character before the property name (e.g., sort=-createdAt
).
By combining query parameters for filtering, sorting, and paging, you can retrieve blog posts that match more advanced search criteria. For example, the request below fetches blog posts that don't have a language assigned, ordered by the most recently updated. Including the limit
and offset
parameters below returns the second page of results.
curl
https://api.hubapi.com/cms/v3/blogs/posts?sort=-updatedAt&&language__not_null&limit=10&offset=10 \
--request POST \
--header "Content-Type: application/json"
Blog posts in HubSpot have both draft and live versions.
- Drafted blog posts appear in HubSpot's editor, but are not live on the website. They can be reviewed and edited by users in HubSpot or via the API, and can be published when needed. After a blog post is published, the draft version can be updated as needed, then later published to update the live content.
- Live blog posts are blog posts that appear on the website. The draft version can be updated without affecting the live blog post content. Published posts can be unpublished to remove them from the website and return them to a draft version.
To create a blog post, make a POST
request to the /cms/v3/blogs/posts
, specifying the blog post's details in the request body. By default, the post will be created as an unpublished draft. If needed, a blog post can be published at the time of creation as long as the properties necessary for publishing are set.
xxxxxxxxxx
{
"name": "Example blog post",
"contentGroupId": "184993428780",
"slug": "slug-at-the-end-of-the-url",
"blogAuthorId": "4183274253",
"metaDescription": "My meta description.",
"useFeaturedImage": false,
"postBody": "<p>Welcome to my blog post! Neat, huh?</p>"
}
Parameter | Type | Description |
---|---|---|
name Required | String | Description |
contentGroupId Required | String | The ID of the parent blog to publish the post to. You can retrieve the ID using the blog details API. |
slug | String | The URL slug of the blog post. HubSpot will automatically generate the full URL using this value, along with the parent blog domain and slug. If no value is provided, the name value will be used as a temporary slug (hyphenated). You will need to set a specific slug before the post can be published. |
blogAuthorId | String | The ID of the blog author. You can retrieve this value using the blog authors API. |
metaDescription | String | The post's meta description. |
useFeaturedImage | Boolean | Whether to include a featured image for the blog post. By default, this field is set to true . To include a featured image, include a value for the featuredImage parameter. |
postBody | String | The HTML content of the blog post. |
Please note: editing blog post content directly in HubSpot using the content editor is the simplest way to modify content. While you can use the the API to create and update blog post, it's not recommended over using the editor, especially for blogs that rely on more complex modules.
Learn more about the structure of the blog post model in the blog posts endpoint reference.
You can update the draft version of a blog post by making a PATCH
request to /cms/v3/blogs/posts/<postId>/draft
. You must include a JSON payload that represents the blog post model. Properties you provide in the request payloud will override existing draft properties without any complex merging logic. As a result, if you're updating nested properties, you should provide the full definition of the object. Partial updates are not supported.
For example, the following request body would update the title and URL slug of a blog post:
xxxxxxxxxx
{
"name": "Example blog post",
"slug": "my-updated-post"
}
Because this request would only update the draft, you would need to make a second request to publish the changes to the website.
To instead update a blog post and immediately publish those changes (updating both the draft and live versions of the post), make a PATCH
request to /cms/v3/blogs/posts/<postId>
, along with a request body containing the content you want to update.
Depending on the state of the blog post, there are a few endpoints you can use to publish it.
- If the blog post is currently a draft, not yet published, make a
PATCH
request to the/cms/v3/blogs/posts/<postId>
endpoint. In the request body, include a JSON payload that sets thestate
toPUBLISHED
. The post must have the following properties set in order to be published:
Property | Type | Description |
---|---|---|
name | String | The title of the blog post. |
contentGroupId | String | The ID of the parent blog to publish the post to. You can retrieve the ID using the blog details API. |
slug | String | The URL slug of the blog post. If no slug was specified at the time of creation, HubSpot will have assigned a temporary slug to the post. This temporary slug must be updated to a specific value in order for the post to be published. |
blogAuthorId | String | The ID of the blog author. You can retrieve this value using the blog authors API. |
metaDescription | String | The post's meta description. |
featuredImage | String | An image to use as the post's featured image. Alternatively, you can opt to not include a featured image by omitting this field and instead setting useFeaturedImage to false . |
state | String | The publish state of the post. Must be set to PUBLISHED . |
- If the blog post is currently published, you can publish any content that's currently drafted by making a
POST
request to/cms/v3/blogs/posts/<postId>/draft/push-live
. This endpoint does not require a request body.
As an alternative to immediate publishing, you can schedule the draft version of your blog post to be published later by making a POST
request to /cms/v3/blogs/posts/schedule
. In the request body, include a JSON payload that contains the id
of the target blog post and a publishDate
(ISO8601 format).
To reset the draft version of a blog post back to its current live version, make a POST
request to /cms/v3/blogs/posts/<postId>/draft/reset
. This endpoint does not require a request body.
To help you maintain blog posts across multiple languages, HubSpot's CMS allows you to group together language variants of the same content. You can learn more about working with multi-language blog posts in on HubSpot's Knowledge Base.
You can create a new language variant for an existing blog post by making a POST
request to the /multi-language/create-language-variant
endpoint. The endpoint accepts a JSON payload containing the id
of the blog post to clone and the language
identifier of the new variant.
You can add a blog post to an existing multi-language group by making a POST
request to the /multi-language/attach-to-lang-group
endpoint. The endpoint accepts a JSON payload containing the id
of the target blog post, the language
identifier of the blog post being added, and the primaryId
of the blog post designated as the primary blog post in the target multi-language group.
To detach a blog post from a multi-language group, make a POST
request to the /multi-language/detach-from-lang-group
endpoint. The endpoint accepts a JSON payload containing the id
of the target blog post.