🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@neuraldraft/sdk

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@neuraldraft/sdk

Official TypeScript SDK for the Neural Draft Project API — typed helpers for brand, content, blog, images, galleries, products, booking, and async jobs.

latest
Source
npmnpm
Version
0.3.4
Version published
Weekly downloads
1
-97.06%
Maintainers
1
Weekly downloads
 
Created
Source

@neuraldraft/sdk

Official TypeScript SDK for the Neural Draft Project API. Typed helpers for brand, content, blog, images, products, booking, and async jobs.

npm version License: MIT

A small, zero-dependency, typed client over the Neural Draft v1 REST API. Wraps the same auth, pagination, error, and resource conventions documented in the OpenAPI spec.

Demo

Five lines of TypeScript: read brand, list products, create a published blog post.

SDK demo

Watch the full MP4 →

Install

npm install @neuraldraft/sdk

Requires Node 20+ (uses the built-in fetch). Also works in any modern runtime that has fetch and AbortController in scope (Bun, Deno via npm: import, edge workers).

Quickstart

Get a project API key from the dashboard. Use a test-mode key (ndsk_test_…) in development; live keys (ndsk_live_…) bill against your project's credits.

import { NeuralDraftClient } from "@neuraldraft/sdk";

const nd = new NeuralDraftClient({
  apiKey: process.env.NEURALDRAFT_API_KEY!,
});

const project = await nd.projects.me();
console.log(`Hello, ${project.name}.`);

By convention the API key lives in NEURALDRAFT_API_KEY. Never hard-code it; never commit it.

Configuration

new NeuralDraftClient({
  apiKey: "ndsk_live_...",                    // required
  apiUrl: "https://api.neuraldraft.io/v1",    // optional, this is the default
  userAgent: "my-app/1.0.0",                  // optional, identifies your app in API logs
  timeout: 30_000,                            // optional, ms; defaults to no timeout
  fetch: customFetch,                         // optional, inject for testing or proxying
});

API surface

The client groups methods into resource namespaces that match the API tags.

projects

const project = await nd.projects.me(); // GET /projects/me

brand

const brand = await nd.brand.get();                                    // GET  /brand
await nd.brand.update({ colors: { primary: { hex: "#2A4A3C" } } });    // PATCH /brand

content

// Read a single key
const v = await nd.content.get("hero.headline", { lang: "fr" });
console.log(v.value, v.all_locales);

// Upsert a value (creates the key if it doesn't exist). Charges 1 credit.
await nd.content.set("hero.headline", "Welcome", "en");

// Bulk-create translation keys with default values. 409 (key exists) is
// treated as "skipped" rather than failing the batch.
const r = await nd.content.bulkCreate(
  { "hero.headline": "Find your calm", "hero.cta": "Get started" },
  "en",
);
console.log(r.created, r.skipped_existing);

// Async translate one key into many target locales. Charges 7 credits per
// language. Returns a JobReference — poll via nd.jobs.poll(job.id).
const job = await nd.content.translate("hero.headline", ["fr", "de"]);

components

// Register editable HTML. data-translate="..." attributes become content keys;
// data-image-key="..." attributes become image slots.
const cmp = await nd.components.register({
  html: '<section><h1 data-translate="hero.headline">Hello</h1></section>',
  intent: "marketing_hero",
  page_slug: "home",
});
console.log(cmp.id, cmp.editor_url);

const list = await nd.components.list({ page_slug: "home", page_size: 50 });
const one = await nd.components.get("cmp_2Ngd9KqLmRpW");

blogPosts

// Manual draft (synchronous, 0 credits — counts against your post quota)
const post = await nd.blogPosts.create({
  title: "5-minute breathwork",
  content: "<p>Hi.</p>",
  language_code: "en",
});

// AI generation (async — returns a Job; costs 60 credits)
const job = await nd.blogPosts.generateAi({
  topic: "5-minute breathwork for anxious mornings",
  word_count: 1200,
  primary_keyword: "morning breathwork",
  translate_to_all: true,
});
const finished = await nd.jobs.poll(job.id);
console.log("Generated:", finished.result);

// Translate an existing post to additional languages (7 credits per language)
const tjob = await nd.blogPosts.translate(post.id, ["de", "fr"]);

// Read & list
const posts = await nd.blogPosts.list({ status: "published", lang: "en" });
const one = await nd.blogPosts.get("5-minute-breathwork-for-anxious-mornings");

images

// Async AI generation — costs 32 credits per image
const job = await nd.images.generate({
  prompt: "Serene yoga studio at dawn",
  aspect_ratio: "16:9",
  key: "hero.background",
});
const finished = await nd.jobs.poll(job.id);
const { url, key } = finished.result as { url: string; key: string };

// Synchronous URL swap — 1 credit
await nd.images.replace("hero.background", { url: "https://cdn.example/img.jpg" });

// Direct file upload (multipart) — 1 credit
await nd.images.upload("logo", fileOrBlob, { filename: "logo.svg" });

products

const list = await nd.products.list({ status: "active" });
const p = await nd.products.get(42);

const created = await nd.products.create({
  name: "Cork yoga block (pair)",
  price: 2999,
  currency: "gbp",
  type: "physical",
  status: "active",
});

await nd.products.update(created.id, { price: 2799 });

booking

const services = await nd.booking.listServices({ status: "active" });
const svc = await nd.booking.getService(12);

// Resolves an embeddable widget snippet for a service. Throws ApiError(404)
// if the service id is unknown. Both tenant id and service id are required —
// the widget script lives at /v1/widgets/booking/{tenant_id}/{service_id}.js.
const me = await nd.projects.me();
const widget = await nd.booking.getWidget(me.id, 12);
console.log(widget.embed_html); // <script src="..." async data-neuraldraft-booking="12"></script>

jobs

// One-shot read
const job = await nd.jobs.get("job_2Ngd9KqLmRpW");

// Poll until terminal (completed | failed | cancelled). Throws on timeout.
const finished = await nd.jobs.poll(job.id, {
  intervalMs: 1500,
  timeoutMs: 5 * 60_000,
});
if (finished.status === "failed") {
  console.error(finished.error);
}

// Cancel an in-flight job
await nd.jobs.cancel(job.id);

Central login: workspace picker

When an email is registered against more than one workspace, the central login form needs to know which one to log into. NeuralDraftClient.tenantsForEmail hits the central host (https://app.neuraldraft.io) without an API key and returns the candidate workspaces:

const { tenants } = await NeuralDraftClient.tenantsForEmail("user@example.com");
for (const t of tenants) {
  console.log(t.id, t.name, t.domain);
}

Error handling

Every method throws ApiError on non-2xx responses or transport failures.

import { ApiError } from "@neuraldraft/sdk";

try {
  await nd.blogPosts.generateAi({ topic: "..." });
} catch (err) {
  if (err instanceof ApiError) {
    if (err.status === 401) {
      // Invalid API key — check your env config
    } else if (err.status === 402) {
      // Out of credits — direct user to top up at /billing
    } else if (err.status === 422) {
      // Validation: err.body is the API's RFC 7807 JSON; parse for `errors`
    } else if (err.status === 429) {
      // Rate-limited (60 req/min default) — back off and retry
    } else {
      throw err;
    }
  }
}

Branch on the API's stable machine code (in the JSON body's code field), not on the title string:

const body = JSON.parse(err.body) as { code?: string };
if (body.code === "out_of_credits") { /* … */ }

status: 0 indicates a transport failure (DNS, connection refused, timeout). path carries the API path that produced the error, useful for logs.

Pagination

List endpoints return Paginated<T>:

interface Paginated<T> {
  data: T[];
  meta: { page: number; page_size: number; total: number };
}

Iterate page by page yourself; the SDK is intentionally low-level.

Async jobs

The API returns a Job reference for any operation that takes more than a couple of seconds (blog AI generation, image generation, batch translation). Jobs have a stable lifecycle:

pending → processing → completed | failed | cancelled

client.jobs.poll(id) calls GET /jobs/{id} repeatedly until the job reaches a terminal state. failed and cancelled resolve with the job (don't throw) — inspect job.status and job.error to decide what to do next.

Versioning

This SDK targets the v1 stable surface of the Neural Draft API. Major version bumps mirror breaking API changes; minor versions add new methods or resources. Patch versions are bug fixes only.

Local development

npm install
npm run lint    # tsc --noEmit
npm test
npm run build   # → dist/

To run against a local API:

NEURALDRAFT_API_KEY=ndsk_test_xxx \
NEURALDRAFT_API_URL=http://localhost/v1 \
npx tsx scripts/smoke.ts

License

MIT.

Keywords

neuraldraft

FAQs

Package last updated on 12 May 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts