EmofyEmofy Developers
Guides

SDK Quickstart

Get your first Emofy integration running end-to-end with the TypeScript SDK — from API key to webhook signature verification.

This guide takes you from zero to a working integration: create an API key, install the SDK, make your first request, and verify a webhook signature — no hand-written types, no human help.

For the SDK overview and the full type/method reference, see the TypeScript SDK section.

1. Get an API key

API keys are created in the Developer Portal under your organization's settings. Each key is scoped to one organization, and each endpoint requires specific scopes (e.g. tasks:read, tasks:write).

Keep the key server-side — it authenticates as your whole organization. Store it in an environment variable, never in client code.

2. Install the SDK

npm install @emofy/dev-sdk
# or: pnpm add @emofy/dev-sdk / yarn add @emofy/dev-sdk

The SDK is a standalone package — it depends only on fetch and node:crypto, so it installs clean in any TypeScript project.

3. Make your first request

import { createEmofyClient, EmofyApiError } from "@emofy/dev-sdk";

const client = createEmofyClient({
  apiKey: process.env.EMOFY_API_KEY!,
  baseUrl: "https://api.emofy.net/api/v1",
});

try {
  // List tasks — paginated, with structured pagination meta.
  const { data, pagination } = await client.tasks.list({ limit: 20 });
  console.log(`Got ${data.length} tasks; hasMore=${pagination?.hasMore}`);

  // Create a task. Pass an idempotency key so a retried request never
  // double-creates.
  const created = await client.tasks.create(
    { title: "Welcome aboard" },
    { idempotencyKey: crypto.randomUUID() },
  );
  console.log("Created", created.data);
} catch (err) {
  if (err instanceof EmofyApiError) {
    // err.code is the machine-readable V1 error code, err.requestId
    // correlates with your server logs.
    console.error(err.status, err.code, err.requestId, err.message);
  }
}

Responses are unwrapped from the V1 { data, meta } envelope automatically — you work with data and meta directly. Rate-limit headers (X-RateLimit-*) are surfaced on every result as rateLimit, and the client automatically retries 429/5xx with Retry-After-aware backoff.

4. Subscribe to webhooks

Register a webhook endpoint in the Developer Portal. Emofy will POST events to your URL, each signed with an Emofy-Signature header.

5. Verify the webhook signature

Always verify the signature before trusting the payload. Pass the raw request body — never re-serialized JSON, since whitespace and key order matter.

import { verifyWebhookSignature } from "@emofy/dev-sdk/webhooks";

// Express example — capture the raw body (e.g. express.raw()).
app.post("/webhooks/emofy", express.raw({ type: "application/json" }), (req, res) => {
  const signature = req.header("Emofy-Signature");
  const valid = verifyWebhookSignature(
    req.body, // raw Buffer
    signature,
    process.env.EMOFY_WEBHOOK_SECRET!,
  );

  if (!valid) {
    return res.status(400).send("invalid signature");
  }

  const event = JSON.parse(req.body.toString("utf8"));
  // ...handle the event...
  res.status(200).send("ok");
});

verifyWebhookSignature handles the secret-rotation grace window (it accepts any of the v1= segments), enforces a 5-minute replay window, and compares in constant time.

Next steps

On this page