Get started
Connect to the genko.me delivery API from JavaScript and show a list and a single entry, using either the SDK or plain fetch.
This guide connects JavaScript to the genko.me blog API and fetches a list and a single entry. It shows both @genko-me/sdk and plain fetch.
Prerequisites
- A genko.me account and workspace. You need the Owner role to create an API and issue an API key.
- Node.js 18 or later if running in Node.js. The SDK and examples use the global
fetchandURLAPIs. In a browser, you only need one that supportsfetch. - One list API and one published entry. If needed, create them in steps 2 and 3 of the quickstart.
Replace your-workspace with your workspace ID and blog with your endpoint throughout this guide.
Install
Install the SDK only if you plan to use it. Skip this step for plain fetch.
npm install @genko-me/sdk@genko-me/react provides display components for Next.js, so it is not needed here.
Configure an API key and workspace ID
If your dashboard URL is https://genko.me/w/your-workspace, your workspace ID is your-workspace.
Create an API key in Settings and plan → API keys (/w/your-workspace/settings/api-keys). Scope it to blog under Selected APIs only to limit exposure if the key leaks. You cannot view its value again after creation.
In Node.js, put it in an environment variable.
GENKO_API_KEY=your-issued-keyconst apiKey = process.env.GENKO_API_KEY;Node.js 20.6 or later can load it with node --env-file=.env app.js. Do not commit .env to Git.
If you call the API directly from a browser, the key appears in the JavaScript you serve. See the overview for when this is acceptable.
Show a list
With the SDK
Keep the connection configuration in one place for the later examples.
import { createGenko, listApi } from "@genko-me/sdk";
export const genko = createGenko({ workspace: "your-workspace", apiKey: process.env.GENKO_API_KEY, apis: { blog: listApi() },});The key under apis becomes the endpoint name. For an object API, use objectApi() instead of listApi().
import { genko } from "./lib/genko.js";
const { contents, totalCount } = await genko.apis.blog.list({ limit: 10, orders: "-publishedAt", fields: ["title", "publishedAt"],});
console.log(`${totalCount} entries total`);for (const post of contents) { console.log(post.id, post.title, post.publishedAt);}fields accepts an array or a string such as "title,publishedAt". The available queries match the query reference.
With plain fetch
const BASE_URL = "https://api.genko.me";const WORKSPACE = "your-workspace";
export async function getList(endpoint, queries = {}) { const url = new URL(`${BASE_URL}/v1/${WORKSPACE}/${endpoint}`); for (const [key, value] of Object.entries(queries)) { if (value !== undefined) url.searchParams.set(key, String(value)); }
const response = await fetch(url, { headers: { "X-API-KEY": process.env.GENKO_API_KEY }, });
if (!response.ok) { const { message } = await response.json().catch(() => ({})); throw new Error(`Delivery API returned ${response.status}: ${message ?? "Unknown error."}`); }
return response.json();}URLSearchParams (url.searchParams) correctly encodes brackets in filters and non-ASCII values. Do not concatenate a query string yourself.
const { contents, totalCount } = await getList("blog", { limit: 10, orders: "-publishedAt", fields: "title,publishedAt",});The response is an object with contents, totalCount, offset, and limit. When no entries match, contents is an empty array rather than an error.
Show a single entry
Append an id from the list to the path to fetch a single entry.
With the SDK
import { genko } from "./lib/genko.js";
const post = await genko.apis.blog.getOrNull("headless-cms-nextjs");if (!post) { console.log("Entry not found.");} else { console.log(post.title); console.log(post.body); // Rich text is an HTML string}get() throws when an entry is missing. getOrNull() returns null only for a 404; authentication and server errors still throw.
With plain fetch
export async function getEntry(endpoint, id, queries = {}) { const url = new URL(`${BASE_URL}/v1/${WORKSPACE}/${endpoint}/${encodeURIComponent(id)}`); for (const [key, value] of Object.entries(queries)) { if (value !== undefined) url.searchParams.set(key, String(value)); }
const response = await fetch(url, { headers: { "X-API-KEY": process.env.GENKO_API_KEY }, });
if (response.status === 404) return null; if (!response.ok) throw new Error(`Delivery API returned ${response.status}.`);
return response.json();}Unlike a list response, a detail response is the entry object itself, without a contents wrapper. Unpublished, deleted, and nonexistent IDs all return 404.
Handle errors
The SDK throws GenkoApiError when the API returns an error. Its status property holds the HTTP status.
import { GenkoApiError } from "@genko-me/sdk";
try { await genko.apis.blog.list();} catch (error) { if (error instanceof GenkoApiError && error.status === 401) { console.error("Check your API key."); } throw error;}See Errors and limits for causes by status. A network failure that never receives an HTTP response throws a different error.
Next steps
Continue with the tutorial for pagination, previewing saved drafts, and webhook signature verification.
Last updated: October 6, 2026