Kallfi

Quickstart

Configure a server-side Kallfi API client and create your first Soul.

Create a shared description-only Soul, then start a surface-owned operation and follow it to completion.

Server-side only

API credentials belong only in your server environment; never expose them in browser code or a public repository.

Get a credential

Kallfi issues a company-scoped bearer credential during partner onboarding. Store it in the secret manager used by your backend and configure the versioned API base URL:

KALLFI_API_KEY="<your-server-side-api-key>"
KALLFI_API_BASE="https://api.kallfi.com/v1"

Every mutation also needs an Idempotency-Key. Generate one stable, unique value for the logical action and reuse that value only when retrying the same request body.

Install a server SDK

The preview SDKs are versioned together in kallfi/kallfi-sdk. Until Kallfi activates their npm and PyPI Trusted Publishers, install the immutable v0.1.1 source tag through the normal package managers:

npm install "github:kallfi/kallfi-sdk#v0.1.1"

Both clients are server-only. The npm package name is @kallfi/sdk; the Python import is kallfi. Registry commands such as npm install @kallfi/sdk and python -m pip install kallfi will be documented as available only after those artifacts are actually published.

Create a Soul

import { randomUUID } from "node:crypto";
import { Kallfi } from "@kallfi/sdk";

const kallfi = Kallfi.fromEnv();
const accepted = await kallfi.souls.create(
  {
    external_soul_id: "guide-aurora",
    kind: "creature",
    description: "A curious celestial guide with a calm, concise voice.",
    source_asset_ids: [],
  },
  { idempotencyKey: randomUUID() },
);

const operation = await kallfi.operations.wait(accepted.operation.operation_id, {
  timeoutMs: 120_000,
});

console.log({ soulId: accepted.soul.soul_id, operation });

Creation returns 202 Accepted with the new shared Soul projection and an asynchronous operation. Keep your own external_soul_id; it is the stable identifier that connects the Soul to your system. Soul creation has no surface field because Account, Auth, handles, and Soul identity are shared. wait is explicitly bounded and never treats a client timeout as cancellation of server work.

Start a surface-owned operation

The exact surface values are nsfw-disabled and nsfw-enabled. Include surface on every response or generation creation request. Choose it from the operation's intended Kallfi web surface; never derive it from developers.kallfi.com, developers.kallfi.red, or a client-supplied label.

import { randomUUID } from "node:crypto";
import { Kallfi } from "@kallfi/sdk";

const kallfi = Kallfi.fromEnv();
const accepted = await kallfi.souls.createResponse(
  "soul_guide_aurora",
  {
    surface: "nsfw-disabled",
    messages: [{ role: "user", content: "Welcome everyone to the stream." }],
    max_output_tokens: 256,
  },
  { idempotencyKey: randomUUID() },
);

const operation = await kallfi.operations.wait(
  accepted.operation.operation_id,
  { timeoutMs: 120_000 },
);

console.log({ surface: accepted.operation.surface, operation });

surface is required for ResponseCreateRequest and GenerationCreateRequest, and Kallfi stores it on the accepted operation. A later GET /v1/operations/{operation_id} returns that immutable surface from the operation ID; it has no surface query or alternate selector. Reusing an idempotency key or resource identity with another surface returns 409 with the stable surface_conflict code.

Raw HTTP

An empty source_asset_ids array creates a Soul from its description alone:

curl --request POST "$KALLFI_API_BASE/souls" \
  --header "Authorization: Bearer $KALLFI_API_KEY" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: <stable-unique-key>" \
  --data '{
    "external_soul_id": "guide-aurora",
    "kind": "creature",
    "description": "A curious celestial guide with a calm, concise voice.",
    "source_asset_ids": []
  }'

Do not submit a second create request when a call times out after dispatch. Retry with the same idempotency key and read the original operation until Kallfi reports an authoritative state. In production, signed webhooks avoid continuous polling.

Surface-owned response creation uses the same single proposed API origin:

curl --request POST "$KALLFI_API_BASE/souls/soul_guide_aurora/responses" \
  --header "Authorization: Bearer $KALLFI_API_KEY" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: <stable-unique-key>" \
  --data '{
    "surface": "nsfw-disabled",
    "messages": [{"role": "user", "content": "Welcome everyone to the stream."}],
    "max_output_tokens": 256
  }'

Generation creation follows the same rule and carries the intended surface in its body:

{
  "surface": "nsfw-enabled",
  "kind": "video",
  "prompt": "Introduce tonight's live show from a neon studio.",
  "quote_id": "quote_live_intro_01",
  "duration_ms": 8000
}

Add source assets

To condition appearance, content style, or live behavior, first create and upload each source asset through POST /v1/soul-source-assets. Wait for asset validation, then include the admitted source-asset IDs in the ordered source_asset_ids array of POST /v1/souls.

Use the API reference for complete request schemas, operation states, errors, and webhook contracts.

On this page