Skip to content

Getting started

Register a Hekana app, send a store through the consent screen, exchange the code for a token and call the Apps API. Which SDK packages exist.

On this page

This page takes an app from registration to a first Apps API call. Every request below is to the Hekana API at https://api.hekana.com/api/v1. Replies are wrapped as { "success": true, "data": ..., "requestId": "..." }, including the OAuth token reply; read data.

Read this first. The OAuth flow only runs for approved apps, and approval is a manual review. You can register and submit today, but you cannot obtain a token for a draft app. Plan to build against the response shapes in the API reference until the review passes.

Packages: what exists

PackageState
@hekana/apps-sdkTyped Apps API client (HekanaApps), verifyWebhook() and a hekana-apps CLI. TypeScript source in the Hekana repository. Not published to npm.
hekana-sdkA read-only client for the separate agent API (products, orders, customers). Not on npm. It does not call the Apps API.
create-hekana-appScaffolds a project that uses hekana-sdk. Not on npm, so npx create-hekana-app does not work yet.

Until @hekana/apps-sdk is released, call the API over HTTP as shown below. Its method names (orders.list, data.put, checkoutExtensions.put) mirror the endpoints, so moving to it later is a small change.

1. Register the app

Registering is a call made with the session of a store owner or admin (the developer is a store, and the app belongs to it).

POST /oauth/apps (request body)JSON
{
  "name": "Reorder reminders",
  "redirect_uris": ["https://example.com/hekana/callback"],
  "scopes": ["read_orders", "read_customers", "send_messages"],
  "type": "confidential"
}
  • redirect_uris: 1 to 10 addresses. They must be https (plain http only for localhost and 127.0.0.1) with no fragment, and are matched exactly.
  • scopes: up to 20, from the list in Authentication and scopes.
  • type: confidential (default) gets a client secret; public has none and relies on PKCE alone.

The reply holds the app, its clientId (starts with hkna_) and, for a confidential app, clientSecret. The secret is shown once. Keep it on your server. POST /oauth/apps/:id/rotate-secret replaces it and shows the new one once.

The app starts as a draft. Before you can submit it, add its listing (see Testing and going live), then call POST /oauth/apps/:id/submit.

After approval, send the store owner to the Hekana dashboard page /oauth/authorize with these query parameters:

text
client_id=<your client id>
redirect_uri=<one of your registered redirect URIs>
scope=read_orders read_customers
state=<random value you check on return>
code_challenge=<base64url SHA-256 of your code verifier>
code_challenge_method=S256

PKCE with S256 is required; plain is refused. scope must be a subset of what the app registered. The owner sees the app name and the scopes, and approves or denies. On approval the browser returns to your redirect_uri with code and your state. A code lives 60 seconds and works once.

3. Exchange the code for tokens

exchange.tsTypeScript
const res = await fetch("https://api.hekana.com/api/v1/oauth/token", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    grant_type: "authorization_code",
    code,                       // from the redirect
    redirect_uri,               // the same one
    client_id: process.env.HEKANA_CLIENT_ID,
    client_secret: process.env.HEKANA_CLIENT_SECRET, // confidential apps
    code_verifier,              // the verifier behind your code_challenge
  }),
});
const { data } = await res.json();
// data: { access_token, token_type: "Bearer", expires_in: 3600, refresh_token, scope }

Store both tokens per store. The access token lasts one hour; see Authentication for refresh.

4. Call the API

first-call.tsTypeScript
const res = await fetch("https://api.hekana.com/api/v1/apps-api/orders?limit=5", {
  headers: {
    Authorization: `Bearer ${accessToken}`,
    "Hekana-Api-Version": "2026-10-01",
  },
});
const { data } = await res.json();
// data: { data: [...orders], total, page, limit, nextCursor }

The token decides the store. There is no store id in any request.

5. Listen for events

Subscribe with POST /apps-api/webhooks and verify every delivery. See Webhooks.

The hekana-apps CLI

The command in the SDK source is a thin command line over the same client, for poking at an installation: orders list, products list|get, customers list|get, data list|get|put|delete and verify-webhook. It reads the token from the HEKANA_TOKEN environment variable (never an argument) and prints JSON. It ships as TypeScript source with the SDK and has the same publishing status.

Next steps