Skip to content

SDK & API

Configure the public settlement API and separate authenticated Organization API, then use the browser SDK safely.

Run the read-only service

Use an actual reviewed policy and matching RPC. The API defaults to loopback. Set an exact Front CORS origin; a hosted HTTPS Front needs a reachable HTTPS API. Send public operation data, never wallet secrets or private notes.

The settlement service does not automatically load .env files. Start the index worker separately before attaching its SQLite database. The default API address is 127.0.0.1:3001; it has no signing key, private-note upload, proving or broadcast endpoint.

Terminal · from Core
export CORE_POLICY_FILE=/absolute/path/to/trusted-policy.json
export CORE_RPC_URL=https://rpc.testnet.near.org
export CORE_ALLOWED_ORIGINS=https://your-front-origin.example
export CORE_INDEX_DB=/absolute/path/to/settlement.sqlite
npm run index -- once
npm run serve

# In a separate process, keep indexing new records.
npm run index -- watch

HTTP endpoints

MethodPathPurpose
GET/healthzProcess liveness; not chain readiness.
GET/readyzVerified deployment and attached-index readiness snapshot.
GET/v1/configPublic policy for independent comparison.
GET/v1/group/capacityPinned tree capacity and first-member deposit observation.
GET/v1/vaultsVerified finalized vault discovery.
POST/v1/recipients/readinessFinalized account existence, token registration and exact registration call.
POST/v1/deposits/preparePublic commitment/root planning with bounded verified capacity.
POST/v1/ft/preflightBalances, registrations, storage prerequisites, and costs.
POST/v1/settlements/statusBound finalized state and permitted recovery.
POST/v1/transactions/verifyExact finalized wallet-call verification.
POST/v1/invoices/verifyMerchant signature and current FullAccess key.
POST/v1/invoices/statusIndexed invoice totals, references, timing, and coverage.
GET/v1/index/statusCheckpoint, provenance, and discovery coverage.
GET/v1/activityPublic journal events with stable filtered pagination.

Browser SDK and wallet execution

Front vendors Core’s browser-safe SDK/declarations with a SHA-256 manifest checked at build. Wallets sign each reviewed call; no service signing key is used.

Build the bundle in Core and synchronize it into Front. This repository workflow does not require a published npm package.

Terminal · sibling repositories
cd Core
npm run build:client
cd ../Front
npm run sync:core
npm run verify:core
npm run build

Index coverage and failure states

SQLite persists journal records, checkpoints, and verified provenance. V2 invoice lookup uses a disclosure-root index for up to 32 signed-derived references, with bounded matching-record reads.

Errors distinguish disabled, not-ready, and failed reads. Incomplete coverage yields review_required. The checkpoint is not a latest-chain assertion or proof of complete company history.

API limits and cancellation

The default API permits two concurrent work requests and 120 weighted points per direct socket peer per minute. Capacity/catalog/readiness queries cost 5 points. Per-route source-read budgets and a 15-second deadline bound each request. Rate or concurrency rejections provide Retry-After; clients do not automatically repeat wallet signatures.

The CLI server cancels its HTTP RPC transport on timeout or disconnect. Non-cancellable adapters keep their work slot until underlying reads settle. Forwarding headers are ignored; clients behind a proxy share its peer budget unless the edge enforces individual limits.

/healthz checks liveness. /readyz verifies the deployment and, when attached, index age, block lag and current journal count. Set CORE_API_REQUIRE_INDEX=true to require an index. Readiness is a snapshot, not complete provenance or a guarantee of payment liquidity.

Recipient readiness

POST /v1/recipients/readiness accepts only a public recipient account. The server verifies the pinned group and reads account existence and token registration at one final block. It returns account_missing, registration_required or ready, with no account-creation estimate or broadcast. The browser client first checks the API policy and rejects substituted destinations or registration calls.

Read-only SDK and CLI
const result = await gateway.recipientReadiness(trustedPolicy, recipient, { signal });
// result.state, result.checkedAtBlock, result.registrationCall

npm run cli -- recipient-readiness trusted-policy.json https://rpc.testnet.near.org receiver.testnet

Browser notes and public deposits

createPrivateNote, encryptNoteBackup and openNoteBackup run locally. The note domain and Poseidon commitment match the existing circuits. The encrypted core-private-note format binds the complete policy and is separate from journal and invoice-library storage.

POST /v1/deposits/prepare accepts only a public commitment, disclosure root and optional vault. The server verifies the original group at one final block and returns a public FT plan and bounded capacity observation. The client checks policy, commitment, reference, vault, token, add-on fee and attachments before returning the plan.

The default deposit scan checks up to 20 vault records. An explicit member can be verified beyond that window, but remains a partial scan unless checkedRecords equals vaultCount. A prepared plan is a snapshot, not a reservation; full groups reject new deposits.

Local backup and public planning
const note = await createPrivateNote(trustedPolicy);
const encrypted = await encryptNoteBackup(trustedPolicy, note, passphrase);
const restored = await openNoteBackup(downloadedFile, passphrase, trustedPolicy);
const result = await gateway.prepareDeposit(trustedPolicy, {
  commitment: restored.note.commitment, disclosureRoot
});
// Import result.plan in the existing wallet session.

Local receipt SDK

createReceipt, encryptReceiptBackup, openReceiptBackup, discloseReceipt and verifyReceiptDisclosure run locally. The eight fixed fields and SHA-256 Merkle paths match the existing Node receipt format. No receipt HTTP route is added.

The CLI disclose command accepts browser-encrypted receipts using CORE_RECEIPT_PASSWORD in the environment. Public selected proofs remain compatible with verify-bundle.

Private backup and selected proof
const receipt = await createReceipt(values);
const encrypted = await encryptReceiptBackup(receipt, passphrase);
const full = await openReceiptBackup(downloadedBackup, passphrase);
const selected = await discloseReceipt(full, ['asset', 'amount']);
await verifyReceiptDisclosure(selected, independentlyObtainedRoot);

Run the Organization API

Use a separate process and database for team access. The loopback default is port 3002, while the settlement API uses port 3001. Enter the independently configured Organization API origin in the Organization workspace. Do not point it at the read-only settlement API.

The server requires its own audience origin, owner-only database file, exact frontend Origin allowlist and HTTPS testnet RPC. localhost and 127.0.0.1 are different origins. A hosted frontend requires a reachable HTTPS backend; the current site does not include a deployed public Organization API.

Terminal · from Core, in a separate process
export CORE_ORGANIZATION_ORIGIN=http://localhost:3002
export CORE_ORGANIZATION_DB="$PWD/data/organizations/organizations.sqlite"
export CORE_ORGANIZATION_ALLOWED_ORIGINS=http://localhost:3000
export CORE_ORGANIZATION_RPC_URL=https://rpc.testnet.near.org
npm run serve:organizations

Organization API endpoints

These routes belong to the Organization API origin. Except for process liveness and challenge/login, requests need an approved Origin and an origin-bound bearer session. The server checks the current finalized wallet key and current organization membership. A browser sends Origin automatically; a nonbrowser HTTP caller must provide it explicitly.

Existing-record mutations need the returned version. Never automatically replay a role, invitation, removal or ownership change after an uncertain response. Refresh the organization and audit log first.

Method / routePurpose
POST /v1/auth/challengeCreate a five-minute account/audience/origin-bound sign-in challenge.
POST /v1/auth/loginRedeem the NEP-413 signature once for a one-hour session.
POST /v1/auth/logoutRevoke the supplied session; does not require an identity RPC read.
GET /v1/organizationsList only the principal’s active organization memberships.
POST /v1/organizationsCreate a workspace name with the authenticated account as Owner.
GET /v1/organizations/:idRead the current role, permissions and versions.
GET /v1/organizations/:id/membersRead the member directory when permitted.
PATCH /v1/organizations/:id/members/:accountChange a permitted role using the member version.
DELETE /v1/organizations/:id/members/:accountRemove a permitted member or leave using the membership version.
GET /v1/me/invitationsRead only invitations addressed to this authenticated account.
POST /v1/me/invitations/:id/accept or /declineExplicitly resolve a targeted invitation using its version.
GET / POST /v1/organizations/:id/invitationsList or create permitted directed invitations.
DELETE /v1/organizations/:id/invitations/:inviteRevoke a permitted invitation using its version.
GET /v1/organizations/:id/rolesRead the fixed role/permission matrix.
PATCH /v1/organizations/:idRename the workspace using the organization version.
POST /v1/organizations/:id/ownershipExplicitly transfer to an active member using the organization version.
GET /v1/organizations/:id/audit?before=<sequence>Read up to 50 organization-scoped audit events per page.

Organization browser client

After verified wallet sign-in, create the client for that same approved service origin and keep the returned session only in memory. This example runs inside Front after the user selects an organization; only an Owner or Admin can rename it. The complete login and role boundaries are described in Organizations & access.

TypeScript · Front browser module
import { OrganizationClient, type Organization } from "@/vendor/core-client/index.js";

// session comes from the verified NEP-413 login flow.
const client = new OrganizationClient(organizationApiOrigin, session.token);
const path = `/v1/organizations/${selectedOrganizationId}`;
const organization = await client.request<Organization>(path);
await client.request(path, "PATCH", {
  name: "Example workspace",
  version: organization.version,
});

Use the private invoice API

The SDK transports signed terms with an explicit in-memory organization session. It does not persist plaintext invoice terms or tokens. A saved record is an archive, not a payment confirmation; checkout still verifies the current merchant key, independently trusted policy, fees and finalized settlement.

Browser SDK
const invoices = new OrganizationInvoiceClient(
  new OrganizationClient(apiOrigin, session.token), organizationId
);
const saved = await invoices.save(stableRequestId, signedInvoice, signal);
const page = await invoices.list(undefined, signal);
const original = await invoices.get(saved.invoice.id, signal);

Reconcile and export organization invoices

invoiceHistory verifies archived terms and the API policy without requiring the historic merchant key to remain current. It never authorizes payment. Existing invoiceStatus and checkout retain the current-key requirement. The dashboard validates exact root/policy/amount bindings and marks uncertainty explicitly. CSV protects formula-like business fields; JSON retains exact atomic amount strings and nullable unknown values.

Browser SDK
const records = await loadOrganizationInvoices(invoices, organizationId, signal);
const status = await gateway.invoiceHistory(record.invoice, { signal });
const observation = await invoiceDashboardObservation(
  record, trustedPolicy, gateway.url, status
);
const rows = [{ record, observation, unavailable: false }];
const filtered = filterInvoiceDashboard(rows, { search: 'INV-', state: 'paid' });
const csv = exportInvoiceDashboard(filtered, 'csv');

Verify and deduplicate payment events

Use the original raw request body; do not parse and re-serialize it before HMAC verification. Signature headers are Core-Event-Id, Core-Webhook-Timestamp, Core-Webhook-Key-Id and Core-Webhook-Signature. Retain deliberate previous keys during rotation. The authenticated event identifies one finalized payment, not a mutable aggregate invoice-paid flag.

OrganizationWebhookClient manages callbacks, delivery pagination, attempt details and versioned retry/rotation. PaymentWebhookInbox is in the Node SDK; its synchronous SQL handler must not perform asynchronous external fulfillment. External work needs a separate transactional outbox/idempotency key. HMAC authenticates the integration; it is not independent light-client or legal/tax verification.

Receiver SDK
const event = await verifyPaymentWebhook(rawUtf8Body, headers, [secret], { organizationId });
// Node SDK: combine receipt uniqueness and business SQL in one transaction.
const inbox = new PaymentWebhookInbox('/private/receiver.sqlite', organizationId);
const result = await inbox.accept(rawUtf8Body, headers, [secret], (db, event) => {
  db.prepare('INSERT INTO received_payments(event_id,amount_tokens) VALUES(?,?)')
    .run(event.id, event.data.amountTokens);
});
// Acknowledge 2xx only after commit, including exact duplicate receipts.

Create and reconcile payout runs

A public manifest contains 1–20 entries with stable intentId, declared worker/contractor category and immutable CorporateContent. Mixed payer/policies and duplicate notes are rejected. All amounts are exact atomic strings, with token fees added on top of note principal. Arbitrary salary amounts/FX/withholding are outside the current fixed-denomination protocol.

PayoutBatchSession keeps a separate guarded operation for each recipient within one encrypted journal. It never batches invisible wallet signatures. Recovery binds the existing destination and shows additional storage. The same origin-bound current organization permissions and one-use corporate dispatch checks apply before each new payment.

Browser SDK
const batches = new PayoutBatchClient(client, organizationId);
const batch = await batches.create(savedManifest, signal);
// A different Owner/Admin approves each exact recipient request.
const run = new PayoutBatchSession(journal, gateway, wallet, client, batch);
const row = batch.payments[0].payload.paymentId;
const review = await run.review(row);
// Review fee/recipient/call, then explicitly request wallet approval.
await run.submitReviewed(row, review.callHash);
const observations = await reconcilePayoutBatch(batch, gateway, gateway.url, signal);
const report = exportPayoutSettlement(batch, observations, 'json');

Source-bound draft SDK

OrganizationTaxDraftClient supports scoped create/list/get, immutable revisions, review decisions and durable generation status/abandonment. draftBasis checks report arithmetic and exact disclosed-value bindings; validateDraftPlan rejects unsupported model content. renderTaxDraft and exportTaxDraft retain citations and preparation scope. verifyTaxDraft checks payload/source-bank hashes; current organization acceptance remains an authorized service decision.

View the source guide Documentation describes the current development implementation.