Agora CMS API

Ágora CMS is a headless content management system that exposes all your editorial content through a standard REST API. You can integrate it into any frontend — Next.js, Astro, Nuxt, a mobile app or a Python script — without proprietary SDKs or special configuration. Each workspace has its own API Key and its own endpoints. All you need is HTTP and JSON.


Base URL

All requests are made to:

https://app.agorastack.com/api/v1

The current API version is v1. When breaking changes are introduced, a v2 will be published while keeping the previous version active for at least 12 months.

Authentication

All requests require the X-API-Key header with your workspace API Key.

X-API-Key: your-api-key

You can obtain and manage your API Key in Settings → API inside the admin panel.

Starting from version 1.0, the ?api_key= query string parameter is disabled in production for security reasons. Always use the X-API-Key header.

Response structure

All endpoints return JSON with a consistent structure.

Collection response:

{
  "data": [ ... ],
  "meta": {
    "total": 100,
    "page": 1,
    "limit": 20,
    "pages": 5
  }
}

Single resource response:

{
  "data": { ... }
}

Errors

Error structure:

{
  "error": true,
  "message": "Error description",
  "code": 401
}

HTTP status codes used by the API:

Code Meaning
200OK — The request was successful
400Bad Request — Invalid or missing parameters
401Unauthorized — Invalid or missing API Key
403Forbidden — You don't have permission for this resource
404Not Found — The resource does not exist
422Unprocessable Entity — Invalid input data
429Too Many Requests — You have exceeded the request limit
500Internal Server Error — Server-side error

Common parameters

Most public API endpoints accept these parameters:

Parameter Type Required Description
web_id string (UUID) Yes ID of the website you want to retrieve content from. Find it in Settings → Websites.
lang string No ISO language code (es, en, fr…). If omitted, returns the default language.
page integer No Page number for pagination. Default: 1.
limit integer No Results per page. Default: 20. Maximum: 100.

Getting started

Integrating Ágora CMS into your project takes just a few minutes. You only need your API Key and the web_id of the site you want to connect. Follow these three steps:

  1. Get your API Key — log into the admin panel, go to Settings → API and copy your key. If you don't have one yet, click "Generate new key".
  2. Make your first request — test the posts endpoint with curl to verify authentication works: curl "https://app.agorastack.com/api/v1/posts?web_id=YOUR_WEB_ID" -H "X-API-Key: YOUR_API_KEY"
  3. Integrate into your frontend — use fetch, axios or any HTTP client. The examples in this documentation include ready-to-copy code.

Compatibility

The Ágora CMS API is a standard REST API that returns JSON. It is compatible with any technology that can make HTTP requests: Next.js (App Router and Pages Router), Astro with fetch at build time or SSR, Nuxt, standalone Vue, React, Svelte, mobile apps with React Native or Flutter, Python scripts with requests, PHP applications, or any automation with cURL.

There is no official SDK to install and no additional dependencies. If your environment can make a GET request with a custom header, you can use Ágora CMS.

Authentication in detail

Your API Key is a unique string per workspace. You can find it in Settings → API in the panel. Never expose it in client-side code served in the browser — always use it on the server (getStaticProps, server components, API endpoints, etc.).

You can rotate your API Key from the same panel at any time. When you rotate, the previous key becomes invalid immediately — make sure to update all integrations before doing so. If you think your key has been compromised, rotate it immediately: go to Settings → API → Rotate key.

In development environments you can use the same key as in production, or create a separate website in the panel to have isolated test data. There is no environment distinction at the API level — you manage the separation yourself through the web_id.

Rate limiting

The API applies a request limit per API Key to ensure service stability. When you exceed it, the server responds with 429 Too Many Requests and includes the Retry-After header indicating how many seconds to wait before retrying.

To handle rate limiting correctly, implement a retry mechanism with exponential backoff:

async function fetchWithRetry(url, options, retries = 3) {
  for (let i = 0; i < retries; i++) {
    const res = await fetch(url, options)
    if (res.status !== 429) return res
    const retryAfter = res.headers.get('Retry-After') || 2
    await new Promise(r => setTimeout(r, retryAfter * 1000 * (i + 1)))
  }
  throw new Error('Too many retries')
}

In projects with static builds (Astro, Next.js with SSG) the limit is rarely a problem because requests happen at compile time, not on every user visit. In SSR projects with heavy traffic, cache responses in memory or in Redis.

Pagination

Endpoints that return collections always include the meta object with pagination information:

"meta": {
  "total": 87,   // total records
  "page": 1,     // current page
  "limit": 20,   // records per page
  "pages": 5     // total pages
}

To implement infinite scroll or load all results in sequence, use meta.pages as the stop condition:

async function fetchAllPosts(webId, apiKey) {
  const base = 'https://app.agorastack.com/api/v1'
  const headers = { 'X-API-Key': apiKey }
  let page = 1
  let all = []

  while (true) {
    const res = await fetch(
      `${base}/posts?web_id=${webId}&page=${page}&limit=100`,
      { headers }
    )
    const { data, meta } = await res.json()
    all = [...all, ...data]
    if (page >= meta.pages) break
    page++
  }

  return all
}

For infinite scroll in the frontend, store the current page in state and update the results array by concatenating each new load. Use meta.page < meta.pages to show or hide the "Load more" button.