# Noctant Private-Beta Self-Onboarding Guide

Date: 2026-06-29
Status: shareable private-beta onboarding guide

This is the one guide to give to a trusted private-beta app team or coding AI.
It contains the complete external path for connecting an app to Noctant through
the Operator API.

It is intentionally limited to public contracts: HTTPS API, generated OpenAPI,
hosted launch URLs, signed webhooks, REST reconciliation, and bounded replay.
It does not require access to Noctant databases, NATS, Docker networks, internal
services, or source code.

## What "Self-Onboarding" Means Today

Private-beta self-onboarding means:

1. Noctant admin creates and activates the operator once.
2. Noctant admin gives the app its environment values once.
3. The app verifies its own setup with `GET /v1/me`.
4. The app runs the API smoke flow.
5. The app proves its webhook receiver.
6. The app opens a hosted launch and proves the user/product flow.
7. The app stores the proof and can keep iterating without Noctant internals.

This is not random public signup yet. A random internet company must not be able
to mint Operator API keys without review, rate-limit policy, webhook policy,
product grants, abuse controls, and support ownership.

## URLs

Staging:

- Operator API: `https://api-staging.noctant.com`
- Docs: `https://docs-staging.noctant.com`
- This guide: `https://docs-staging.noctant.com/operator-api/self-onboarding`
- Journal app guide: `https://docs-staging.noctant.com/operator-api/journal-app`
- OpenAPI JSON: `https://docs-staging.noctant.com/openapi/operator-api.json`

The OpenAPI JSON is the machine-readable source of truth. Generate a client
from it or call the API directly with plain HTTPS.

## What Noctant Provides

For each app/environment, Noctant provides:

```sh
NOCTANT_OPERATOR_API_BASE_URL=https://api-staging.noctant.com
NOCTANT_OPERATOR_API_KEY=...
NOCTANT_OPERATOR_ID=...
NOCTANT_OPERATOR_ORG_ID=...
NOCTANT_WEBHOOK_SIGNING_SECRET=...
NOCTANT_EXECUTION_PROFILE_KEY=...
NOCTANT_RETURN_URL=https://your-app.example/noctant/return
NOCTANT_WEBHOOK_URL=https://your-app.example/webhooks/noctant/operator
```

Rules:

- Store these values as server-side secrets.
- Never put the API key or webhook signing secret in browser code.
- Never log API keys, webhook secrets, cookies, authorization headers, or raw
  launch tokens.
- `NOCTANT_RETURN_URL` must use an origin that Noctant allowlisted for this
  operator.
- `NOCTANT_WEBHOOK_URL` must be an HTTPS endpoint controlled by the operator.

## Required First Check

Before creating users or accounts, call:

```http
GET /v1/me
Authorization: Bearer <NOCTANT_OPERATOR_API_KEY>
```

The app must verify:

- `operator_id` equals `NOCTANT_OPERATOR_ID`;
- `org_id` equals `NOCTANT_OPERATOR_ORG_ID`;
- environment is the expected one;
- status is `active`;
- access is `allowlisted_beta`;
- webhook is configured and enabled;
- allowed origins include the origin of `NOCTANT_RETURN_URL`;
- scopes include the actions the app will use.

For the first journal/account-creator smoke, the required scopes are:

- `users:create`
- `accounts:create`
- `launch_sessions:create`
- `account_summary:read`
- `orders:read`
- `positions:read`
- `trades:read`
- `webhook_deliveries:read`
- `webhooks:replay`

If this check fails, stop and fix onboarding. Do not continue with partial
assumptions.

## API Smoke Flow

The app should run this flow with unique but stable test ids:

```text
external_user_id    = <app-prefix>-user-<run-id>
external_account_id = <app-prefix>-account-<run-id>
```

Use those ids for retries. Do not change ids when retrying the same logical
object.

Flow:

1. `GET /v1/me`
2. `POST /v1/users`
3. `POST /v1/accounts`
4. `POST /v1/launch-sessions`
5. `GET /v1/accounts/by-external-id/summary`
6. `GET /v1/accounts/by-external-id/orders`
7. `GET /v1/accounts/by-external-id/positions`
8. `GET /v1/accounts/by-external-id/trades`
9. `GET /v1/webhooks/deliveries`
10. `POST /v1/webhooks/replays`
11. Repeat the same replay request with the same idempotency key.

Every write request must include:

```http
x-noctant-request-id: <uuid>
```

The request id is for logs and audit correlation. It is not the same as
endpoint idempotency.

The replay request must include an idempotency key. Repeating the exact same
body with the exact same key must be safe. Reusing the same key with different
facts is a caller bug.

## Maintained SDK Smoke

The Noctant repo contains a maintained TypeScript smoke helper:

```text
packages/operator-api-typescript-sdk/examples/private-beta-self-onboarding.ts
```

It proves the API onboarding path against the public Operator API surface:

- verifies operator context;
- creates the test user;
- creates the sponsored journal account;
- creates a hosted launch session;
- redacts the launch token from evidence;
- reads back summary/orders/positions/trades;
- reads the webhook delivery ledger;
- requests bounded replay twice with the same idempotency key;
- returns a sanitized report.

The report contains object ids, counts, and the redacted launch URL only. It
does not contain the API key, webhook signing secret, or launch token.

Example usage inside the target app:

```ts
import {
  configureSelfOnboardingFromEnvironment,
  runPrivateBetaSelfOnboardingSmoke,
} from "@noctant/operator-api-typescript-sdk/examples/private-beta-self-onboarding";

const input = configureSelfOnboardingFromEnvironment(process.env);
const report = await runPrivateBetaSelfOnboardingSmoke(input);

console.log(JSON.stringify(report, null, 2));
```

Until the SDK is published as a public npm package, an app can either vendor
the example, generate its own client from the OpenAPI JSON, or implement the
same requests with raw HTTPS.

## Hosted Launch Proof

`POST /v1/launch-sessions` returns a short-lived, one-time launch URL.

Rules:

- Create it only when the browser is ready to redirect.
- Do not store the plaintext token in durable logs.
- In proof reports, redact it as:

```text
https://app-staging.noctant.com/launch/<redacted>
```

The user should land in Noctant on the expected route and account. If browser
launch fails, collect sanitized evidence: status code, request id, operator id,
external account id, launch session id, and timestamp. Do not collect cookies
or tokens.

## Webhook Receiver Proof

The app must implement an HTTPS webhook receiver before the integration is
trusted.

For every webhook:

1. Read the raw body bytes before JSON parsing.
2. Verify `X-Noctant-Signature` with `NOCTANT_WEBHOOK_SIGNING_SECRET`.
3. Reject stale timestamps.
4. Verify header event id/type match the body envelope.
5. Store event ids durably.
6. Treat duplicate event ids as duplicate success.
7. Reject the same event id if the stored facts differ.

Headers:

```http
X-Noctant-Event-Id: ...
X-Noctant-Event-Type: ...
X-Noctant-Signature: t=<unix_seconds>,v1=<hex-hmac-sha256>
```

The HMAC input is:

```text
<unix_seconds>.<raw body bytes>
```

For the first journal flow, expect account/trading events such as
`account.created` and `trade.closed`, depending on the operator's enabled event
filter.

## Reconciliation Proof

Webhooks are not enough. The app must also reconcile through REST:

- read account summary;
- read orders;
- read positions;
- read closed trades;
- compare stored webhook effects with REST readback;
- use bounded replay if a webhook was missed.

This is what makes redeploys, receiver downtime, retries, and webhook delivery
delays recoverable.

## Historical Replay And Manual Backtest

Do not use account-bound launch sessions for replay/backtest.

Historical replay/backtest uses:

```http
POST /v1/historical-launch-sessions
```

That route is controlled by explicit feed, time-window, product-mode, and
operator grants. It intentionally does not fake a live account. This prevents
analytics, trades, and account state from being mixed between live-style
accounts and historical simulation.

Use the journal/account-creator smoke first. Only add historical replay or
manual backtest after the normal operator setup is proven.

## Activation Checklist

Noctant side:

- operator row exists;
- operator status is `active`;
- operator access is `allowlisted_beta`;
- API key is provisioned;
- webhook signing secret is provisioned;
- webhook URL is configured;
- allowed origins include the app's return URL origin;
- operator preset/scopes are correct;
- execution profile key is enabled;
- rate limit tier is intentional;
- readiness screen passes;
- sanitized smoke proof is attached.

App side:

- secrets are server-side only;
- `GET /v1/me` check passes;
- API smoke report passes;
- webhook signature verification passes;
- event id storage is idempotent;
- REST reconciliation works;
- bounded replay works;
- browser hosted launch lands on the right route/account;
- a test trade can be reconciled by webhook and REST readback.

## What The Other App Can Do After This Passes

With this onboarding path, a trusted private-beta app can:

- create or replay stable operator users;
- create or replay sponsored simulated journal accounts;
- send users into hosted Noctant terminal sessions;
- receive signed account/trading webhooks;
- reconcile account state through REST;
- request bounded webhook replay;
- iterate on its own app without touching Noctant internals.

It still cannot:

- create its own Operator API key without Noctant admin;
- change its webhook URL without Noctant admin or a future self-serve admin
  surface;
- access accounts sponsored by other operators;
- access arbitrary historical feeds/time windows without explicit grants;
- rely on SDK-only behavior that is not present in OpenAPI.

## Copy-Paste Prompt For Another Coding AI

```text
Integrate this app with Noctant as a trusted private-beta operator.

Use only the public Noctant Operator API at NOCTANT_OPERATOR_API_BASE_URL.
Use Authorization: Bearer NOCTANT_OPERATOR_API_KEY for REST calls.
Do not use Noctant databases, NATS, Docker networks, or source internals.

First call GET /v1/me and verify operator id, org id, status, access,
environment, allowed origins, webhook config, and required scopes.

Then run the onboarding smoke:
POST /v1/users
POST /v1/accounts
POST /v1/launch-sessions
GET /v1/accounts/by-external-id/summary
GET /v1/accounts/by-external-id/orders
GET /v1/accounts/by-external-id/positions
GET /v1/accounts/by-external-id/trades
GET /v1/webhooks/deliveries
POST /v1/webhooks/replays twice with the same idempotency key

Every write must include x-noctant-request-id.
Never log API keys, webhook secrets, cookies, authorization headers, or raw
launch tokens. Redact launch URLs as /launch/<redacted>.

Implement webhook signature verification using X-Noctant-Signature over
"<timestamp>.<raw body bytes>" with NOCTANT_WEBHOOK_SIGNING_SECRET.
Store event ids durably and process duplicates idempotently.

Use https://docs-staging.noctant.com/openapi/operator-api.json as the contract.
```

## Source References

- OpenAPI: `docs/api/operator-api.openapi.json`
- SDK package: `packages/operator-api-typescript-sdk`
- Self-onboarding SDK smoke:
  `packages/operator-api-typescript-sdk/examples/private-beta-self-onboarding.ts`
- Journal account flow:
  `packages/operator-api-typescript-sdk/examples/private-beta-journal-account-creator.ts`
- Historical launch flow:
  `packages/operator-api-typescript-sdk/examples/private-beta-historical-launch.ts`
- Internal admin runbook:
  `docs/operator-api/private-beta-internal-onboarding-runbook.md`
