Blog Posts API
This release adds API support for the store's blog, making it possible to create, publish and maintain blog articles from external tools such as content platforms, SEO tools and AI-powered content generators.
Blog posts as an API resource
OpenTiendas now exposes blog posts through the API.
Unlike products, categories or brands, each blog post is an article in one locale: it has its own ID, URL, content, featured image, SEO metadata, related content, publication date and publication status. The translations of the same article are separate blog posts that share the same post group: its post_group_id and, optionally, your own post_group_internal_id.
This makes filtering, sorting, pagination and deletion work the same way for every locale, and lets each translation be published, updated or deleted independently.
Available endpoints
The following endpoints are now available:
GET /api/v1/blog-posts/
POST /api/v1/blog-posts/
GET /api/v1/blog-posts/{id}/
PATCH /api/v1/blog-posts/{id}/
DELETE /api/v1/blog-posts/{id}/
The list endpoint returns blog posts in every locale, and supports filtering by:
- blog post IDs, post group IDs and post group internal IDs,
- locale,
- publication status,
- complete slug (the last part of the blog post URL),
- creation, update and publication date ranges.
Results can be sorted by publication date (the default, newest first), creation date or update date.
All endpoints require the new blog_posts permission in the API access.
Detailed request and response schemas, filters and examples are available in the API Reference.
Creating an article and its translations
Each request creates a blog post in one locale. The translations of an article can be grouped in two ways.
With the post_group_id returned by OpenTiendas
Create the first blog post without post_group_id:
POST /api/v1/blog-posts/
{
"locale": "en-GB",
"name": "How to improve your ecommerce SEO",
"description": "<p>Practical tips to improve your online store visibility.</p>",
"body_html": "<h2>Introduction</h2><p>Search engine optimization is essential for ecommerce growth.</p>",
"image_url": "https://example.com/images/seo-guide.jpg",
"image_alt": "Organic traffic chart",
"meta_title": "Ecommerce SEO Guide",
"related_posts": [12],
"products": [1534]
}
A new post group is created, and its post_group_id is returned in the response. To add a translation, create another blog post with that post_group_id and a different locale:
{
"post_group_id": 31,
"locale": "es-ES",
"name": "Cómo mejorar el SEO de tu tienda online",
"body_html": "<h2>Introducción</h2><p>El SEO es fundamental para atraer tráfico orgánico.</p>"
}
With your own post_group_internal_id
Send your own identifier of the article in post_group_internal_id with every translation. If no post group has it, a new one is created with it; otherwise, the blog post is added to that post group. This way, translations can be created without reading the post_group_id returned for the first one:
{
"post_group_internal_id": "seo-guide",
"locale": "en-GB",
"name": "How to improve your ecommerce SEO",
"body_html": "<h2>Introduction</h2><p>Search engine optimization is essential for ecommerce growth.</p>"
}
{
"post_group_internal_id": "seo-guide",
"locale": "es-ES",
"name": "Cómo mejorar el SEO de tu tienda online",
"body_html": "<h2>Introducción</h2><p>El SEO es fundamental para atraer tráfico orgánico.</p>"
}
post_group_internal_id is the same internal ID used by the blog CSV import and shown in the shop backoffice, so articles can be managed with both. It cannot be sent together with post_group_id. Use the post_group_internal_ids filter to get every translation of an article by its internal ID.
Locales and translations
The locale must be one of the locales active in the store. Each post group can only have one blog post per locale, and post_group_id and locale cannot be changed after creation. post_group_internal_id can be changed with PATCH: it belongs to the post group, so it changes for every translation of the article (and it may affect existing integrations).
The read-only post_group_translations field lists every locale of the article, including the blog post itself, with the id and url of each translation. It is useful for hreflang links or to know which translations are missing.
HTML content and images
The content of a blog post is a single HTML field, body_html: the same content that is edited in the shop backoffice.
- External images (
<img>) are downloaded to the store's media library (Images and documents), and the saved content points to the stored copy. An image that was already downloaded is reused, and images already hosted by the store are not downloaded again. - Embedded base64 images (
data:URIs) are also stored in the media library, and the same image is reused if it is sent again. - Up to 50 external images can be downloaded per request, and image URLs cannot be longer than 1000 characters.
- If an image cannot be downloaded, the request fails with a descriptive error and nothing is saved.
- To show products inside the content, include them as regular HTML (image, name and link).
When updating a blog post, body_html replaces its whole content.
The featured image is set with image_url (JPEG, PNG, GIF or WebP) and its alternative text with image_alt. Sending the current image_url back keeps the image as it is, and sending it empty or null removes it. If a blog post has no featured image, the store shows the image of the translation in the default locale.
Related content
Each blog post can define:
related_posts: other blog posts in the same locale, shown as related content in the given order,products,categories,brandsandsubstores: what the blog post is about. They are shown at the end of the blog post with links to them, and they are used to choose the automatic related posts. A blog post with categories is also shown on the pages of those categories (and of their parent and child categories) if the store shows blog posts on category pages.
All of them are lists of OpenTiendas IDs. When updating, sending a list replaces it entirely, an empty list removes all its items, and lists not included in the request remain unchanged.
The store may complete the related posts shown on the blog post page with automatic suggestions. These suggestions are not returned by the API: related_posts only contains the posts chosen explicitly.
Publication and SEO
New blog posts are unpublished unless status: published is sent. A published blog post is visible in the store only from its publication_date (YYYY-MM-DD), which defaults to the creation date.
Each blog post has its own meta_title, meta_description and slug_base (the editable part of its URL). The complete slug and the public url are returned by the API.
Updating a blog post never recreates it, so its ID and URL stay the same unless slug_base is changed explicitly. For content synchronization, updating existing blog posts is recommended over deleting and recreating them.
Field selection and response shape
The blog post resource follows the same field selection and response shape rules as the rest of the OpenTiendas API.
The fixed field is:
id
The default fields are:
post_group_id,locale,name,status,publication_date,url.
The rest of the fields (body_html, post_group_translations, related_posts…) can be requested with the fields query parameter.
👉 Field selection and response shape
Recommended workflow for content generation
For integrations with external content generation tools:
- Generate the article content and SEO metadata.
- Create the blog post with
status: unpublishedand keep the returnedidandpost_group_id, or send your ownpost_group_internal_id. - Optionally create its translations with the same
post_group_idorpost_group_internal_id. - Review the generated article if required.
- Set
status: publishedwithPATCHwhen the article is ready.
This lets you automate content generation while keeping control over what is published.
Summary
This release expands the OpenTiendas API with blog management by:
- exposing blog posts as an API resource, one per locale,
- adding endpoints to list, create, retrieve, update and delete blog posts,
- grouping translations of the same article with
post_group_idor your ownpost_group_internal_id, - storing the images of the content in the store's media library,
- and managing related posts and the products, categories, brands and substores each post is about.

