Nurio Docs Data API
Developer Reference

Data API

Build your own custom frontend while Nurio handles the content generation and backend. Fetch your posts and articles as raw JSON to integrate them anywhere.

Getting Started

The Data API is a set of public endpoints that allow you to retrieve your published content. All endpoints support CORS, meaning you can call them directly from your client-side JavaScript (React, Svelte, Vue, etc.).

Fast & Cached

Requests are globally cached at the edge. Content updates are reflected within 60 seconds of publishing.

No Auth Required

Public endpoints only return "published" content. No API keys are needed for GET requests.

GET

List published posts

Retrieve a list of your most recent published posts.Body content is excluded from this list to keep the response lightweight.

Endpoint
https://nurio.sh/api/public/YOUR-WORKSPACE/posts

Query Parameters

ParamDefaultDesc
limit6Max posts to return (1-20)
categorynullFilter by category name

Example Request

fetch('https://nurio.sh/api/public/YOUR-WORKSPACE/posts')
  .then(res => res.json())
  .then(data => console.log(data.posts));
GET

Retrieve a single post

Fetch the full content of a specific post using its slug. This includes the contentHtml which contains the sanitized body of the article.

Endpoint
https://nurio.sh/api/public/YOUR-WORKSPACE/posts/:slug

Response Schema

{
  "post": {
    "id": "post_123456",
    "title": "How to build a content engine",
    "slug": "how-to-build-a-content-engine",
    "excerpt": "Learn the secrets to scaling your content...",
    "contentHtml": "<p>...</p>",
    "category": "Growth",
    "thumbnailUrl": "https://...",
    "publishedAt": "2026-05-12T10:00:00.000Z",
    "url": "https://yoursite.com/blog/how-to-build-a-content-engine",
    "trackViewUrl": "https://nurio.sh/api/track-view?pid=post_123456&ws=YOUR-WORKSPACE"
  }
}

Analytics & View Tracking

When using the Data API, views are not counted automatically when your server queries the JSON. This prevents server-side builds or caching layers from inflating your numbers.

Recommended

Option A: Universal JS Script (Full Analytics)

Embed this script at the bottom of your single-post page template. It tracks true external referrers (`document.referrer`), scroll depth, reading time, and click heatmap coordinates.

<!-- Universal Tracking Script (Scroll, Time, Referrers, Heatmap) -->
<script>
  (function() {
    var _api = "https://nurio.sh"; // Replace with your Nurio host
    var _id  = "POST_ID";          // Replace with your template's post ID variable dynamically
    var _sid = Math.random().toString(36).slice(2) + Date.now().toString(36);
    var _start = Date.now();
    var _maxScroll = 0;
    var _clicks = [];
    var _sent = false;

    // Track views with the true external referrer
    var viewParams = new URLSearchParams({
      pid: _id,
      ws: "YOUR-WORKSPACE", // Replace with your workspace slug
      sid: _sid,
      ref: document.referrer || ''
    });
    new Image().src = _api + '/api/track-view?' + viewParams.toString();

    // Scroll depth tracking
    window.addEventListener('scroll', function() {
      var pct = Math.round(((window.scrollY + window.innerHeight) / document.documentElement.scrollHeight) * 100);
      if (pct > _maxScroll) _maxScroll = Math.min(pct, 100);
    }, { passive: true });

    // Click heatmap tracking
    document.addEventListener('click', function(e) {
      if (_clicks.length >= 100) return;
      _clicks.push({
        x: Math.round((e.clientX / window.innerWidth) * 100),
        y: Math.round((e.pageY / document.documentElement.scrollHeight) * 100)
      });
    });

    // Session metrics tracking on exit
    function sendSession() {
      if (_sent) return;
      _sent = true;
      try {
        var params = new URLSearchParams({
          sid: _sid,
          sd: String(_maxScroll),
          tt: String(Math.round((Date.now() - _start) / 1000)),
          cp: JSON.stringify(_clicks)
        });
        new Image().src = _api + '/api/track-session?' + params.toString();
      } catch(e) {}
    }
    document.addEventListener('visibilitychange', function() {
      if (document.visibilityState === 'hidden') sendSession();
    });
    window.addEventListener('pagehide', sendSession);
  })();
</script>

Option B: Hidden Image Pixel (Views Only)

A lightweight, zero-JS pixel that only tracks raw page views. Simply include the pre-constructed trackViewUrl returned in the post's JSON payload:

<!-- Place this hidden image inside your single post layout -->
<img 
  src={post.trackViewUrl} 
  alt="" 
  style="display: none;" 
  referrerpolicy="no-referrer-when-downgrade" 
/>

Rate Limiting

To ensure platform stability, the public API is limited to 60 requests per minute per IP address. If you exceed this limit, the API will return a 429 Too Many Requests error.

Need help with custom integrations?