Build on NORYX

Read accounts, deals, signals, evidence and decisions, ask for research and next best actions, receive events as they happen, and give AI assistants NORYX’s context. Every call is scoped by its key, limited to its organisation and audited.

1. Get an API key

An Admin creates keys in Settings → API keys. A key acts for the Admin who created it, within its scopes, is shown once, expires, can be revoked and has its own per-minute limit. See keys and scopes.

2. Call the API with the TypeScript SDK

@noryx/sdk is generated from the public OpenAPI document: every path, parameter and response is typed. It retries what is safe to retry, waits for Retry-After, paces requests under your key’s limit and verifies webhook signatures.

examples/quickstart.ts
/**
 * Quickstart: find an account, list its open deals and their latest next best action, and ask
 * NORYX for a fresh one. Run against your API:
 *   NORYX_API_URL=http://localhost:4000 NORYX_API_KEY=nrx_... pnpm --filter @noryx/sdk example:quickstart
 */
import { createNoryx, paginate, unwrap, type Noryx } from '@noryx/sdk';

export async function quickstart(noryx: Noryx, log: (line: string) => void = console.log) {
  // 1. Search: names, domains and keywords, ranked.
  const found = unwrap(
    await noryx.GET('/v1/search', { params: { query: { q: 'ACME', types: 'account' } } }),
  );
  const account = found.results[0];
  if (!account) throw new Error('No account matches "ACME"');
  log(`Account: ${account.entityId}`);

  // 2. Every open deal of the account (keyset pagination, handled for you).
  const deals = [];
  for await (const deal of paginate((cursor) =>
    noryx.GET('/v1/deals', {
      params: {
        query: {
          accountId: account.entityId,
          status: 'open',
          limit: 50,
          ...(cursor ? { cursor } : {}),
        },
      },
    }),
  ))
    deals.push(deal);
  log(`Open deals: ${deals.map((d) => `${d.name} (${d.stage})`).join(', ')}`);

  // 3. The latest next best action on the first deal, if NORYX already has one.
  const deal = deals[0];
  if (!deal) return { accountId: account.entityId, deals: 0, runId: null };
  const decisions = unwrap(
    await noryx.GET('/v1/decisions', {
      params: {
        query: { subjectId: deal.id, kind: 'next_best_action', current: 'true', limit: 1 },
      },
    }),
  );
  log(`Latest next best action: ${decisions.items[0]?.title ?? 'none yet'}`);

  // 4. Ask for a fresh one (needs the intelligence:run scope); it runs in the background.
  const { run, created } = unwrap(
    await noryx.POST('/v1/intelligence-runs', {
      body: { kind: 'next_best_action', subjectId: deal.id },
    }),
  );
  log(
    `Next best action ${created ? 'requested' : 'already running'}: run ${run.id} (${run.status})`,
  );
  return { accountId: account.entityId, deals: deals.length, runId: run.id };
}

if (import.meta.url === `file://${process.argv[1] ?? ''}`) {
  const noryx = createNoryx({
    apiKey: process.env.NORYX_API_KEY ?? '',
    baseUrl: process.env.NORYX_API_URL ?? 'http://localhost:4000',
  });
  await quickstart(noryx);
}

3. Or with curl

examples/curl.sh
#!/usr/bin/env bash
# The public API with curl. Set NORYX_API_URL (e.g. http://localhost:4000) and NORYX_API_KEY.
set -euo pipefail

# Accounts, newest first (keyset pagination: pass nextCursor back as ?cursor=).
curl -sS --fail-with-body "$NORYX_API_URL/v1/accounts?limit=5" \
  -H "Authorization: Bearer $NORYX_API_KEY"

# Search accounts, people and deals.
curl -sS --fail-with-body "$NORYX_API_URL/v1/search?q=ACME&limit=3" \
  -H "Authorization: Bearer $NORYX_API_KEY"

# Open deals of one account.
curl -sS --fail-with-body "$NORYX_API_URL/v1/deals?status=open&limit=5" \
  -H "Authorization: Bearer $NORYX_API_KEY"

Next

  • API reference

    Every public operation, its scope and schemas.

  • Webhooks

    Signed events, retries, replays and verification.

  • MCP

    NORYX in Claude Desktop and other AI assistants.