> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rankai.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Publish to a website built with code

> Retrieve and display RankAI articles on a website built with code, with API endpoints and a Next.js example.

Use this guide for a website you build and maintain through code, such as Next.js, React, or plain HTML. This includes sites built by you, a developer, or with AI coding tools. Your website's code retrieves published articles from RankAI's API and displays them on public pages.

The guide covers the two main API endpoints and a Next.js example you can adapt to your site. If your blog uses a supported CMS, choose its [platform guide](/integrations/overview) first, even when the rest of your website uses code.

## 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 (HTML or Markdown).

## 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 based on your need
    }
  );

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

  const response = await res.json();
  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(projectId: string, articleId: string, publishedUrl: string) {
  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 based 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 };
}) {
  const publishedUrl = `https://yourdomain.com/articles/${params.articleId}`;
  const article = await fetchArticle('YOUR_PROJECT_ID', params.articleId, publishedUrl);
  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 };
}) {
  const publishedUrl = `https://yourdomain.com/articles/${params.articleId}`;
  const article = await fetchArticle('YOUR_PROJECT_ID', params.articleId, publishedUrl);

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

## Best practices

* **Pass published URL:** Always include the publishedUrl parameter so we can 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 (e.g. use Next.js `revalidate`).
* **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 the 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 display RankAI's content, optimized for SEO and AEO, on your website. The flexible format options and pagination support make it easy to build robust content flows that scale with your needs.

## Install the technical SEO & AEO script

The article API above supplies content for your website to display. Follow the separate [illustrated technical SEO & AEO setup](/integrations/technical-seo/custom-site) to install the RankAI script.

***

*Last reviewed: October 12, 2026.*


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.