DEV Community

Alex Spinov
Alex Spinov

Posted on

Strapi Has a Free API You Should Know About

Strapi auto-generates a full REST and GraphQL API from your content types — and it's the most popular open-source headless CMS.

Content Type Builder

Define your schema in the admin panel or code:

// src/api/post/content-types/post/schema.json
{
  "kind": "collectionType",
  "collectionName": "posts",
  "attributes": {
    "title": { "type": "string", "required": true },
    "content": { "type": "richtext" },
    "slug": { "type": "uid", "targetField": "title" },
    "cover": { "type": "media" },
    "category": { "type": "relation", "relation": "manyToOne", "target": "api::category.category" },
    "tags": { "type": "relation", "relation": "manyToMany", "target": "api::tag.tag" },
    "publishedAt": { "type": "datetime" }
  }
}
Enter fullscreen mode Exit fullscreen mode

Auto-Generated REST API

# List with filters, sort, pagination, populate
GET /api/posts?filters[category][name][$eq]=tech&sort=publishedAt:desc&pagination[page]=1&pagination[pageSize]=10&populate=*

# Single entry
GET /api/posts/1?populate[category]=*&populate[tags]=*

# Create
POST /api/posts
{ "data": { "title": "New Post", "content": "...", "category": 1 } }

# Update
PUT /api/posts/1
{ "data": { "title": "Updated Title" } }

# Delete
DELETE /api/posts/1
Enter fullscreen mode Exit fullscreen mode

Custom Controllers

// src/api/post/controllers/post.js
module.exports = {
  async findFeatured(ctx) {
    const posts = await strapi.entityService.findMany('api::post.post', {
      filters: { featured: true },
      sort: { publishedAt: 'desc' },
      limit: 5,
      populate: ['cover', 'category']
    })
    return posts
  }
}

// src/api/post/routes/custom.js
module.exports = {
  routes: [
    { method: 'GET', path: '/posts/featured', handler: 'post.findFeatured' }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Middleware & Policies

// src/api/post/policies/is-owner.js
module.exports = async (ctx, config, { strapi }) => {
  const post = await strapi.entityService.findOne('api::post.post', ctx.params.id, {
    populate: ['author']
  })
  if (post.author.id !== ctx.state.user.id) {
    return ctx.unauthorized('You can only edit your own posts')
  }
  return true
}
Enter fullscreen mode Exit fullscreen mode

Webhooks

Configure in admin panel: trigger HTTP requests when content changes. Perfect for:

  • Rebuild static site on publish
  • Invalidate CDN cache
  • Sync to search index
  • Send notifications

Real-World Use Case

A startup needed a content API for their React Native app + marketing website. Options: build custom (weeks), WordPress REST API (slow, bloated), or Strapi. They chose Strapi: 30 minutes to define content types, instant REST API, admin panel for content editors. Two years later, same Strapi instance serves mobile app, web app, and internal tools.

Strapi is the Node.js API generator disguised as a CMS.


Build Smarter Data Pipelines

Need to scrape websites, extract APIs, or automate data collection? Check out my ready-to-use scrapers on Apify — no coding required.

Custom scraping solution? Email me at spinov001@gmail.com — fast turnaround, fair prices.

Top comments (0)