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.
List published posts
Retrieve a list of your most recent published posts.Body content is excluded from this list to keep the response lightweight.
Query Parameters
| Param | Default | Desc |
|---|---|---|
| limit | 6 | Max posts to return (1-20) |
| category | null | Filter by category name |
Example Request
fetch('https://nurio.sh/api/public/YOUR-WORKSPACE/posts')
.then(res => res.json())
.then(data => console.log(data.posts));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.
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.
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?