2 min read

How to Integrate Rankai to a Custom Built Site

API Endpoints Overview

Rankai provides two essential API endpoints for integrating content:

  • Articles List Endpoint: Fetch a paginated list of all your published articles

  • Single Article Endpoint: Fetch a specific article by its slug with customizable format

Endpoint 1: Get Articles List

Use this endpoint to retrieve a paginated list of all your published articles with summary information.

API URL

GET https://rankai.ai/api/v1/{projectId}/articles?page=[page-num]&limit=[limit]

Parameters

  • projectId: Your unique project identifier (replace {projectId} in the URL)

  • page: Page number for pagination (optional, defaults to 1)

  • limit: Number of articles per page (optional, defaults to 10, max 100)

Response Format

{
  "success": true,
  "data": [
    {
      "id": "article-id-1",
      "slug": "article-slug-1",
      "title": "Article Title",
      "description": "Article description",
      "publishedDate": "2025-01-15T10:00:00Z",
      "featuredImageUrl": "https://example.com/image.jpg"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 10,
    "total": 25,
    "totalPages": 3
  }
}

Example Usage

// JavaScript/Node.js example
const response = await fetch('https://rankai.ai/api/v1/{projectId}/articles?page=1&limit=10');
const data = await response.json();

if (data.success) {
  data.data.forEach(article => {
    console.log(article.title);
  });
}

Endpoint 2: Get Single Article

Use this endpoint to fetch a specific article by its slug with full content in your preferred format.

API URL

GET https://rankai.ai/api/v1/{projectId}/articles/{slug}?format=[html|markdown]&publishedUrl=[your-url]

Parameters

  • projectId: Your unique project identifier (replace {projectId} in the URL)

  • slug: The article's URL slug (replace {slug} in the URL)

  • format: Content format - "html" or "markdown" (optional, defaults to "html")

  • publishedUrl: The full URL where this article is published on your site (required for tracking)

Response Format

{
  "success": true,
  "data": {
    "id": "article-id",
    "title": "Complete Article Title",
    "description": "Article description",
    "publishedDate": "2025-01-15T10:00:00Z",
    "content": "<div>Full article content in HTML or Markdown...</div>",
    "featuredImageUrl": "https://example.com/image.jpg"
  }
}

Example Usage

// JavaScript/Node.js example
const publishedUrl = encodeURIComponent('https://yourdomain.com/blog/my-article-slug');
const response = await fetch(
  `https://rankai.ai/api/v1/{projectId}/articles/my-article-slug?format=html&publishedUrl=${publishedUrl}`
);
const data = await response.json();

if (data.success) {
  console.log(data.data.title);
  console.log(data.data.content); // Full HTML content
}

Next.js Implementation Example

Article List Component

// Server Component Example (Next.js 13+)
async function fetchArticles(projectId: string, page: number = 1, limit: number = 10) {
  const res = await fetch(
    `https://rankai.ai/api/v1/${projectId}/articles?page=${page}&limit=${limit}`,
    { 
      next: { revalidate: 86400 } // Revalidate every 24 hours (86400 seconds), change this base on your need
    }
  );

  if (!res.ok) {
    throw new Error('Failed to fetch articles');
  }

  const response = await res.json();

  // Return the response directly without transformation
  return response;
}

export default async function ArticleList({ 
  projectId, 
  searchParams 
}: { 
  projectId: string;
  searchParams: { page?: string };
}) {
  const currentPage = parseInt(searchParams.page || '1', 10);
  const response = await fetchArticles(projectId, currentPage, 10);
  const articlesToDisplay = response.data;
  const pagination = response.pagination;

  return (
    <div>
      {articlesToDisplay.map((article: any) => (
        <article key={article.slug || article.id}>
          <h2>{article.title}</h2>
          <p>{article.description}</p>
          {article.featuredImageUrl && (
            <img src={article.featuredImageUrl} alt={article.title} />
          )}
          <time>{new Date(article.publishedDate).toLocaleDateString()}</time>
        </article>
      ))}
    </div>
  );
}

Single Article Component

// Single Article Server Component Example (Next.js 13+)
async function fetchArticle(articleId: string, publishedUrl?: string) {
  // Build the URL with optional publishedUrl parameter
  const baseUrl = `https://rankai.ai/api/v1/${projectId}/articles/${articleId}`;
  const url = publishedUrl 
    ? `${baseUrl}?publishedUrl=${encodeURIComponent(publishedUrl)}`
    : baseUrl;
  
  const res = await fetch(
    url,
    { 
      next: { revalidate: 86400 } // Revalidate every 24 hours (86400 seconds), change this base on your need
    }
  );

  if (!res.ok) {
    throw new Error('Failed to fetch article');
  }

  const response = await res.json();
  return response.data;
}

export async function generateMetadata({ 
  params 
}: { 
  params: { articleId: string };
}) {
  // Pass the published URL for tracking
  const publishedUrl = `https://yourdomain.com/articles/${params.articleId}`;
  const article = await fetchArticle(params.articleId, publishedUrl);
  
  // Use processed featured image from HTML content
  const imageUrl = article.featuredImageUrl || '';

  return {
    title: article.h1Title || article.title,
    description: article.description,
    openGraph: {
      title: article.h1Title || article.title,
      description: article.description,
      url: `/articles/${params.articleId}`,
      images: imageUrl
        ? [
            {
              url: imageUrl,
              width: 1200,
              height: 660,
            },
          ]
        : [],
      locale: 'en_US',
      type: 'article',
    },
  };
}

export default async function ArticlePage({ 
  params 
}: { 
  params: { articleId: string };
}) {
  // Pass the published URL for tracking
  const publishedUrl = `https://yourdomain.com/articles/${params.articleId}`;
  const article = await fetchArticle(params.articleId, publishedUrl);

  return (
      <div dangerouslySetInnerHTML={{ __html: article.content }} />
  );
}

Best Practices

  • Pass Published URL: Always include the publishedUrl parameter to help track where your articles are published. This enables better analytics and indexing tracking

  • Implement Caching: Cache API responses to reduce load times and API calls

  • Error Handling: Always check the "success" field in responses and handle errors gracefully

  • Pagination: Use the pagination data to implement proper pagination controls

Troubleshooting

Common Issues

  • Invalid Format Error: Ensure format parameter is either "html" or "markdown"

  • Article Not Found: Verify the slug exists and the article is published

With these API endpoints, you can seamlessly integrate Rankai's SEO-optimized content into your custom-built website. The flexible format options and pagination support make it easy to build robust content management systems that scale with your needs.