Blog Posts
/api/blog-posts
Get all posts (with filters, pagination, sorting)
/api/blog-posts/:id
Get post by ID
/api/blog-post/:slug
Get post by slug (custom route)
/api/blog-posts
Create post (requires authentication)
/api/blog-posts/:id
Update post (requires authentication)
/api/blog-posts/:id
Delete post (requires authentication)
Blog Categories
/api/blog-categories
Get all categories (with filters, pagination, sorting)
/api/blog-categories/:id
Get category by ID
/api/blog-category/:slug
Get category by slug (custom route)
/api/blog-categories
Create category (requires authentication)
/api/blog-categories/:id
Update category (requires authentication)
/api/blog-categories/:id
Delete category (requires authentication)
Blog Tags
/api/blog-tags
Get all tags (with filters, pagination, sorting)
/api/blog-tags/:id
Get tag by ID
/api/blog-tag/:slug
Get tag by slug (custom route)
/api/blog-tags
Create tag (requires authentication)
/api/blog-tags/:id
Update tag (requires authentication)
/api/blog-tags/:id
Delete tag (requires authentication)
Query Parameters
All GET endpoints support Strapi’s standard query parameters for filtering, sorting, pagination, and population:
| Parameter | Description | Example |
|---|---|---|
populate |
Populate relations (use * for all relations) |
?populate=* or ?populate[category]=* |
filters |
Filter by field values |
?filters[category][slug][$eq]=tech |
sort |
Sort results (asc or desc) |
?sort=publishedAt:desc |
pagination[page] |
Page number (starts from 1) |
?pagination[page]=1 |
pagination[pageSize] |
Number of items per page |
?pagination[pageSize]=10 |
Filter Operators
Strapi supports various filter operators:
$eq– Equal to$ne– Not equal to$lt– Less than$lte– Less than or equal to$gt– Greater than$gte– Greater than or equal to$in– Included in an array$notIn– Not included in an array$contains– Contains (case-sensitive)$notContains– Does not contain$containsi– Contains (case-insensitive)$notContainsi– Does not contain (case-insensitive)$null– Is null$notNull– Is not null$between– Is between two values
Note: You can combine multiple query parameters. For example: GET /api/blog-posts?populate=*&filters[category][slug][$eq]=tech&sort=publishedAt:desc&pagination[page]=1&pagination[pageSize]=10
Response Format
All endpoints return data in Strapi’s standard format:
{
"data": [
{
"id": 1,
"attributes": {
"title": "Post Title",
"slug": "post-title",
// ... other fields
}
}
],
"meta": {
"pagination": {
"page": 1,
"pageSize": 10,
"pageCount": 5,
"total": 50
}
}
}For single item responses:
{
"data": {
"id": 1,
"attributes": {
"title": "Post Title",
// ... other fields
}
}
}Authentication
POST, PUT, and DELETE endpoints require authentication. You need to include a JWT token in the Authorization header:
Authorization: Bearer YOUR_JWT_TOKENNote: GET endpoints are publicly accessible by default. You can configure permissions in Strapi’s admin panel under Settings → Roles & Permissions.
API Examples
Practical examples of how to use the WebbyBlog API endpoints
GET /api/blog-posts
// Response
{
"data": [
{
"id": 1,
"attributes": {
"title": "Start Here with WebbyBlog",
"slug": "getting-started-with-webbyblog",
"content": "...",
"excerpt": "Learn how to use WebbyBlog...",
"publishedAt": "2024-01-15T10:00:00.000Z",
"createdAt": "2024-01-15T09:00:00.000Z",
"updatedAt": "2024-01-15T10:00:00.000Z"
}
}
],
"meta": {
"pagination": {
"page": 1,
"pageSize": 25,
"pageCount": 1,
"total": 1
}
}
}Get Post by Slug
GET /api/blog-post/getting-started-with-webbyblog?populate=*
// Response
{
"data": {
"id": 1,
"attributes": {
"title": "Start Here with WebbyBlog",
"slug": "getting-started-with-webbyblog",
"content": "...",
"excerpt": "Learn how to use WebbyBlog...",
"category": {
"data": {
"id": 1,
"attributes": {
"name": "Technology",
"slug": "technology"
}
}
},
"tags": {
"data": [
{
"id": 1,
"attributes": {
"name": "Tutorial",
"slug": "tutorial"
}
}
]
},
"author": {
"data": {
"id": 1,
"attributes": {
"username": "admin"
}
}
},
"featured_image": {
"data": {
"id": 1,
"attributes": {
"url": "/uploads/image.jpg",
"name": "featured.jpg"
}
}
}
}
}
}Filter Posts by Category
GET /api/blog-posts?filters[category][slug][$eq]=technology&populate=*&sort=publishedAt:desc
// Returns all posts in the "technology" category, sorted by newest firstGet Posts with Pagination
GET /api/blog-posts?pagination[page]=1&pagination[pageSize]=5&populate=*
// Response includes pagination metadata
{
"data": [ ... ],
"meta": {
"pagination": {
"page": 1,
"pageSize": 5,
"pageCount": 3,
"total": 12
}
}
}Filter Posts by Multiple Tags
GET /api/blog-posts?filters[tags][slug][$in][0]=javascript&filters[tags][slug][$in][1]=tutorial&populate=*
// Returns posts that have either "javascript" or "tutorial" tagsGet Recent Posts
GET /api/blog-posts?sort=publishedAt:desc&pagination[pageSize]=5&populate=*
// Returns the 5 most recently published postsGet Category by Slug with Posts
GET /api/blog-category/technology?populate[posts][populate]=*
// Returns the category with all related posts populatedGet Tag by Slug with Posts
GET /api/blog-tag/javascript?populate[posts][populate]=*
// Returns the tag with all related posts populatedCreate a Blog Post
POST /api/blog-posts
Content-Type: application/json
Authorization: Bearer YOUR_JWT_TOKEN
{
"data": {
"title": "My New Blog Post",
"content": "This is the content of my blog post...",
"excerpt": "A short excerpt",
"category": 1,
"tags": [1, 2, 3],
"author": 1,
"meta_title": "SEO Title",
"meta_description": "SEO Description",
"publishedAt": "2024-01-15T10:00:00.000Z"
}
}
// Response
{
"data": {
"id": 2,
"attributes": {
"title": "My New Blog Post",
"slug": "my-new-blog-post",
// ... other fields
}
}
}Update a Blog Post
PUT /api/blog-posts/1
Content-Type: application/json
Authorization: Bearer YOUR_JWT_TOKEN
{
"data": {
"title": "Updated Blog Post Title",
"content": "Updated content...",
"views": 100
}
}
// Response
{
"data": {
"id": 1,
"attributes": {
"title": "Updated Blog Post Title",
// ... updated fields
}
}
}Delete a Blog Post
DELETE /api/blog-posts/1
Authorization: Bearer YOUR_JWT_TOKEN
// Response
{
"data": {
"id": 1,
"attributes": {
// ... deleted post data
}
}
}JavaScript/Fetch Examples
Fetch All Posts
async function getAllPosts() {
const response = await fetch('http://localhost:1337/api/blog-posts?populate=*');
const data = await response.json();
return data.data;
}Fetch Post by Slug
async function getPostBySlug(slug) {
const response = await fetch(
`http://localhost:1337/api/blog-post/${slug}?populate=*`
);
const data = await response.json();
return data.data;
}Create Post
async function createPost(postData, token) {
const response = await fetch('http://localhost:1337/api/blog-posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
body: JSON.stringify({
data: postData
})
});
const data = await response.json();
return data.data;
}
// Usage
const newPost = await createPost({
title: 'My New Post',
content: 'Post content...',
category: 1,
tags: [1, 2]
}, 'your-jwt-token');Filter Posts by Category
async function getPostsByCategory(categorySlug) {
const response = await fetch(
`http://localhost:1337/api/blog-posts?filters[category][slug][$eq]=${categorySlug}&populate=*&sort=publishedAt:desc`
);
const data = await response.json();
return data.data;
}React/Next.js Example
// pages/blog/[slug].js (Next.js)
import { useState, useEffect } from 'react';
export default function BlogPost({ slug }) {
const [post, setPost] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function fetchPost() {
const response = await fetch(
`${process.env.NEXT_PUBLIC_STRAPI_URL}/api/blog-post/${slug}?populate=*`
);
const data = await response.json();
setPost(data.data);
setLoading(false);
}
fetchPost();
}, [slug]);
if (loading) return
Loading...
;
if (!post) return
Post not found
;
return (
{post.attributes.title}
);
}Note: Remember to replace localhost:1337 with your actual Strapi server URL in production. Also, make sure to handle errors appropriately in your applications.