API Overview

Updated 23 April 2026

Blog Posts

GET

/api/blog-posts

Get all posts (with filters, pagination, sorting)

GET

/api/blog-posts/:id

Get post by ID

GET

/api/blog-post/:slug

Get post by slug (custom route)

POST

/api/blog-posts

Create post (requires authentication)

PUT

/api/blog-posts/:id

Update post (requires authentication)

DELETE

/api/blog-posts/:id

Delete post (requires authentication)

Blog Categories

GET

/api/blog-categories

Get all categories (with filters, pagination, sorting)

GET

/api/blog-categories/:id

Get category by ID

GET

/api/blog-category/:slug

Get category by slug (custom route)

POST

/api/blog-categories

Create category (requires authentication)

PUT

/api/blog-categories/:id

Update category (requires authentication)

DELETE

/api/blog-categories/:id

Delete category (requires authentication)

Blog Tags

GET

/api/blog-tags

Get all tags (with filters, pagination, sorting)

GET

/api/blog-tags/:id

Get tag by ID

GET

/api/blog-tag/:slug

Get tag by slug (custom route)

POST

/api/blog-tags

Create tag (requires authentication)

PUT

/api/blog-tags/:id

Update tag (requires authentication)

DELETE

/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:

Filter Operators

Strapi supports various filter operators:

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_TOKEN

Note: 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 first

Get 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" tags

Get Recent Posts

GET /api/blog-posts?sort=publishedAt:desc&pagination[pageSize]=5&populate=*

// Returns the 5 most recently published posts

Get Category by Slug with Posts

GET /api/blog-category/technology?populate[posts][populate]=*

// Returns the category with all related posts populated

Get Tag by Slug with Posts

GET /api/blog-tag/javascript?populate[posts][populate]=*

// Returns the tag with all related posts populated

Create 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.