genko.meDocs
Frameworks and languagesJavaScript

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 fetch and URL APIs. In a browser, you only need one that supports fetch.
  • 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.

bash
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.

.env
GENKO_API_KEY=your-issued-key
js
const 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.

lib/genko.js
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().

list.js
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

lib/genko-fetch.js
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.

js
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

detail.js
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

lib/genko-fetch.js
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.

js
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

On this page