RankFloRankFlo

API Reference

The RankFlo Content Delivery API lets you fetch published posts, search content, and embed analytics into any website or app. All endpoints are public, CORS-enabled, and require only a Project API Key.


Authentication

Every request needs your Project API Key (blg_xxx). Get yours from Dashboard → Projects.

bash
# Query parameter (simplest — safe for frontend)
GET /api/v1/content?project_key=blg_xxx

# Authorization header
GET /api/v1/content
Authorization: Bearer blg_xxx

Project keys only return published posts. Drafts and scheduled posts are never exposed.

Base URL

text
https://app.rankflo.io

For self-hosted instances, replace with your own domain. All endpoints are at /api/v1/.

Rate Limits

120 requests per minute per project key (sliding window). Returns 429 Too Many Requests with Retry-After header when exceeded.


GET /api/v1/content

Fetch published posts for a project.

bash
curl "https://app.rankflo.io/api/v1/content?project_key=blg_xxx"

Query parameters

ParameterTypeDefaultDescription
project_keystringRequired. Your project API key
slugstringFetch a single post by slug
pagenumber1Page number
limitnumber20Posts per page (max 100)
sortstringnewestnewest / oldest / title / updated
tagstringFilter by tag slug
localestringFilter by locale (en, fr)
formatstringhtmlhtml or json (raw blocks)
fieldsstringSparse fieldset (title,slug,excerpt)
updated_sincestringISO 8601 timestamp for incremental sync

Response

json
{
  "data": [{
    "id": "abc123",
    "slug": "my-first-post",
    "title": "My First Post",
    "excerpt": "A short summary.",
    "content": "<p>Full HTML content...</p>",
    "featuredImage": "https://...",
    "readingTime": 5,
    "publishedAt": "2026-03-15T09:00:00.000Z",
    "author": { "name": "Jane Smith" },
    "tags": [{ "name": "SEO", "slug": "seo" }],
    "seo": {
      "metaTitle": "My First Post",
      "metaDescription": "A short summary.",
      "ogImage": "https://..."
    }
  }],
  "meta": {
    "page": 1,
    "limit": 20,
    "total": 47,
    "totalPages": 3
  }
}

Full-text search across published posts using Postgres FTS.

bash
curl "https://app.rankflo.io/api/v1/search?project_key=blg_xxx&q=headless+cms"
ParameterDescription
qRequired. Search query
limitMax results (default 10, max 50)
tagFilter results by tag slug

GET /api/v1/tags

List all tags for a project with post counts.

bash
curl "https://app.rankflo.io/api/v1/tags?project_key=blg_xxx"

Webhooks

RankFlo fires webhooks when posts are published or updated. See the Webhooks guide for payload format and signature verification.


Next.js Integration

typescript
// lib/rankflo.ts
const KEY = process.env.RANKFLO_PROJECT_KEY!;
const URL = "https://app.rankflo.io";

export async function getPosts(opts?: { tag?: string; limit?: number }) {
  const params = new URLSearchParams({ project_key: KEY });
  if (opts?.tag) params.set("tag", opts.tag);
  if (opts?.limit) params.set("limit", String(opts.limit));

  const res = await fetch(`${URL}/api/v1/content?${params}`, {
    next: { revalidate: 60 },
  });
  return res.json();
}

export async function getPost(slug: string) {
  const res = await fetch(
    `${URL}/api/v1/content?project_key=${KEY}&slug=${slug}`,
    { next: { revalidate: 60 } }
  );
  const { data } = await res.json();
  return data;
}
typescript
// app/blog/page.tsx
import { getPosts } from "@/lib/rankflo";

export default async function BlogPage() {
  const { data: posts } = await getPosts({ limit: 20 });
  return (
    <main>
      {posts.map((post) => (
        <article key={post.slug}>
          <a href={`/blog/${post.slug}`}>{post.title}</a>
          <p>{post.excerpt}</p>
        </article>
      ))}
    </main>
  );
}

Use revalidate: 60 for ISR — pages stay cached but refresh every 60 seconds. For instant updates, add a webhook that calls revalidatePath().