Spark SDK

Build custom portal blocks that run inside the epilot customer portal.

@epilot/spark-sdk is the toolkit for building portal blocks: custom applications that render inside an <iframe> embedded in the epilot customer portal. The SDK handles everything the portal boundary makes hard: authenticating against the portal, reading entities, executing Integration Hub use cases, staying in sync with the portal's theme and language, and resizing the iframe to fit your content.

You write a normal React (or framework-agnostic) app. The SDK gives it a secure, typed line back to the portal it lives in.

Mental model

A portal block never talks to epilot APIs directly. It runs in a sandboxed iframe on a different origin, so every interaction goes through a postMessage bridge to the parent portal window, which holds the user's auth and proxies requests on your behalf.

┌─────────────────────────────────────────────────────────┐
│  epilot Customer Portal  (parent window, holds auth)     │
│                                                          │
│   ┌──────────────────────────────────────────────────┐  │
│   │  <iframe>  Your portal block                      │  │
│   │                                                   │  │
│   │   @epilot/spark-sdk                               │  │
│   │     • initialize()        → session (token, …)    │  │
│   │     • getEntity()         → entity reads          │  │
│   │     • executeUseCase()    → Integration Hub       │  │
│   │     • onLocaleUpdate()    → language sync         │  │
│   │     • updateContentHeight → iframe resize         │  │
│   └──────────────────────────────────────────────────┘  │
│              ▲  postMessage bridge  ▼                     │
└─────────────────────────────────────────────────────────┘

The lifecycle is always the same:

  1. Connect: call initialize(). The portal hands back a SparkSession containing an auth token, the API base URL, the active theme and language, and your block's installation config.
  2. Read & act: use getEntity / searchEntities to read portal data and executeUseCase to call Integration Hub.
  3. Stay in sync: the SDK keeps theme and language aligned with the portal automatically, and you report your content height so the portal can size the iframe.

The examples in these docs follow a HEMS built with Spark, a complete portal block. Almost every code sample is drawn from that pattern, so you can see each piece in full context.

Installation

npm install @epilot/spark-sdk
# or
pnpm add @epilot/spark-sdk

Quick start

import { initialize, getEntity } from '@epilot/spark-sdk'

// 1. Connect to the parent portal (do this once, at startup)
const session = await initialize()
console.log('Connected to portal', session.portalId)

// 2. Read data through the portal's auth
const contract = await getEntity({
  slug: 'contract',
  entity_id: '5da0a718-c822-403d-9f5d-20d4584e0528',
})

console.log(contract?._title)

In a React app you'll wrap this in a provider so the whole tree can wait for the connection. See Getting started for the full pattern used by a HEMS built with Spark.

Explore the SDK

Why use the SDK

  • Secure by construction: auth never leaves the parent portal; the bridge can be locked to trusted origins.
  • Typed end to end: entity and use-case shapes are fully typed, with convenience re-exports from @epilot/customer-portal-client.
  • Framework-agnostic core: the bridge is plain Promises and callbacks; the React patterns in these docs are a convention, not a requirement.
  • Tree-shakeable, ESM & CJS: import only what you use.

On this page