API & SDK

Integrate Helix into your applications with our type-safe Client SDK and Content Delivery API.

Client SDK (@helix/client)

The SDK provides a Drizzle-style query builder for type-safe data fetching and a high-level Document API for expanding content graphs.

Installation

npm install @helix/client

Initialization

The getClient() function reads credentials from environment variables (HELIX_API_URL, HELIX_API_KEY, HELIX_SPACE_ID).

import { getClient, tables, eq } from '@helix/client';
import * as schema from './types'; // Your exported Entity classes

const client = getClient();
const { pages, articles } = tables(schema);

Query API (Recommended)

Build type-safe queries with full autocompletion using a Drizzle-style API.

Basic Queries

// Fetch a list of published articles with specific fields
const posts = await client
  .select({
    title: articles.title,
    slug: articles.slug,
    authorName: articles.author.name // Dotted access for relations
  })
  .from(articles)
  .where(eq(articles.status, 'published'))
  .orderBy(articles.publishedAt, 'desc')
  .limit(10)
  .execute({ locale: 'en' });

Advanced Filtering

Use powerful operators for complex queries:

import { eq, ilike, gt, and, or } from '@helix/client';

// Case-insensitive search with multiple conditions
const searchResults = await client
  .select()
  .from(articles)
  .where(
    and(
      ilike(articles.title, '%typescript%'), // Case-insensitive LIKE
      eq(articles.status, 'published'),
      gt(articles.views, 1000) // Greater than
    )
  )
  .execute({ locale: 'en' });

// OR conditions
const featuredOrPopular = await client
  .select()
  .from(articles)
  .where(
    or(
      eq(articles.featured, true),
      gt(articles.views, 10000)
    )
  )
  .execute({ locale: 'en' });

Filtering on Relational Data

One of the most powerful features is the ability to filter on related entity fields:

// Find articles by a specific author
const adaArticles = await client
  .select({
    title: articles.title,
    authorName: articles.author.name,
    authorBio: articles.author.bio
  })
  .from(articles)
  .where(eq(articles.author.name, 'Ada Lovelace'))
  .execute({ locale: 'en' });

// Complex relational filtering
const techArticlesByVerifiedAuthors = await client
  .select()
  .from(articles)
  .where(
    and(
      eq(articles.category.slug, 'technology'),
      eq(articles.author.verified, true),
      gt(articles.author.followerCount, 1000)
    )
  )
  .execute({ locale: 'en' });

Pagination & Sorting

// Offset-based pagination
const page2 = await client
  .select()
  .from(articles)
  .orderBy(articles.createdAt, 'desc')
  .limit(20)
  .offset(20)
  .execute({ locale: 'en' });

// Cursor-based pagination (recommended for large datasets)
const nextPage = await client
  .select()
  .from(articles)
  .orderBy(articles.createdAt, 'desc')
  .limit(20)
  .cursor('article_xyz123') // ID of last item from previous page
  .execute({ locale: 'en' });

Multi-Locale Queries

// Fetch the same content in different locales
const enVersion = await client
  .select()
  .from(pages)
  .where(eq(pages.slug, 'about'))
  .execute({ locale: 'en' });

const svVersion = await client
  .select()
  .from(pages)
  .where(eq(pages.slug, 'about'))
  .execute({ locale: 'sv' });

Document API

A simpler API for fetching fully expanded content documents.

// Get a single page by its slug, expanding relations 2 levels deep
const homePage = await client
  .entities(pages)
  .getBySlug('home', { locale: 'en', depth: 2 });

// Get a list of articles
const recentArticles = await client
  .entities(articles)
  .list({ locale: 'en', limit: 5, depth: 1 });

Content Delivery API

The REST API is available at space-scoped endpoints and provides high-performance, read-only content delivery.

Authentication

Use bearer tokens (API keys) and specify the space in the X-Space-ID header.

curl -H "Authorization: Bearer your-api-key" \
     -H "X-Space-ID: your-space-id" \
     https://api.helix.dev/api/content?type=Article&locale=en

Endpoints

POST /api/query

The primary endpoint for the SDK's Query API. It accepts a JSON query plan. It is recommended to use the SDK instead of calling this directly.

GET /api/content

Query and expand entities.

GET /api/content?type=Article&locale=en&depth=2&limit=10

GET /api/content/{id}

Fetch a single entity by ID.

GET /api/content/article-123?locale=en&depth=2

All PATCH requests to update content require an If-Match header containing the entity's current ETag to prevent lost updates.