<!--
Sitemap:
- [Newton Agent NeoBank](/index)
- [Getting Started](/getting-started)
- [Onboard an Agent](/guides/onboard-an-agent)
- [Give an Agent a Budget](/guides/agent-budget)
- [Pay for an API](/guides/pay-for-an-api)
- [Issue a Card](/guides/issue-a-card)
- [Meter Your API](/guides/meter-your-api)
- [Handle Approvals](/guides/handle-approvals)
- [Listen for Events](/guides/listen-for-events)
- [SDK Essentials](/reference/sdk)
- [ModularVault](/reference/sdk/modular-vault)
- [PlatformClient](/reference/sdk/platform-client)
- [FacilitatorClient](/reference/sdk/facilitator-client)
- [createX402Fetch](/reference/sdk/create-x402-fetch)
- [buildPolicyParams](/reference/sdk/build-policy-params)
- [Networks & Addresses](/reference/networks)
-->

# PlatformClient

The HTTP client for the hosted platform API. Use it to manage agents and their signing sessions, read vault data, set policy, and run the card rail — all with an operator API key, no local private key required.

```typescript
import { PlatformClient } from "@newton-xyz/isaac";

const platform = new PlatformClient({
  baseUrl: "https://api.example.com",
  apiKey: "nab_sk_...", // operator API key
});
```

You can also get a pre-configured instance from a managed vault with `vault.getPlatformClient()`.

## Agents

```typescript
const { address, sessionExpiresAt } = await platform.createAgent("research-bot");
const agents = await platform.listAgents();
const agent = await platform.getAgent(address);
await platform.refreshSession(address); // extend the signing session
await platform.deactivateAgent(address);
```

`createAgent(name)` provisions a managed key and an initial signing session. `refreshSession(address)` extends a session before it expires; `getAgent`/`listAgents` return the agent's `name`, `hdIndex`, `status`, and `sessionExpiresAt`.

### Signing

```typescript
const { signature } = await platform.sign(address, "message", "hello");
```

`sign(address, type, payload)` signs with the agent's managed key. `type` is `"transaction"`, `"message"`, or `"typed_data"`.

## Vault reads

```typescript
const vaults = await platform.listVaults();
const balance = await platform.getVaultBalance(vaultAddress, [tokenAddress]);
const fleet = await platform.getVaultAgents(vaultAddress);
const history = await platform.getVaultHistory(vaultAddress);
const spending = await platform.getVaultSpending(vaultAddress, "day");
const token = await platform.getTokenMetadata(tokenAddress); // symbol, decimals
```

## Policy

Policy is per-agent. Set up an agent's policy module, then update its params.

```typescript
await platform.setupPolicy(vaultAddress, agentAddress, "token");
const policy = await platform.getAgentPolicy(vaultAddress, agentAddress);
await platform.updatePolicyParams(
  vaultAddress,
  agentAddress,
  params,
  policy.policyId,
  policy.module,
  policy.expireAfter,
);
```

Build `params` with [buildPolicyParams](/reference/sdk/build-policy-params). `setupPolicy` requires the agent's module to already be installed on the vault.

## Smart-payer sessions

Use these methods after an operator allows a discovered service for an agent and deploys an isolated `SessionBudgetSmartPayer`.

```typescript
const session = await platform.createSmartPayerSession(vaultAddress, agentAddress, {
  serviceAuthorizationId,
  expectedBindingFingerprint,
  payerAddress,
  token,
  recipient,
  maxAmount: "1000000",
  validAfter,
  validBefore,
  sessionId,
  authorizedSessionSigner,
  refundRecipient,
});

const sessions = await platform.listSmartPayerSessions(vaultAddress, agentAddress, {
  limit: 20,
  offset: 0,
});
const sameSession = await platform.getSmartPayerSession(
  vaultAddress,
  agentAddress,
  session.id,
);
```

`createSmartPayerSession` records one immutable session term set for the deployed payer. The platform binds the session to the service authorization's recipient, token, network, and binding fingerprint. The SDK x402 smart-payer helper currently consumes Base Sepolia sessions (`eip155:84532`).

```typescript
interface CreateSmartPayerSessionRequest {
  serviceAuthorizationId: string;
  expectedBindingFingerprint: string;
  payerAddress: Address;
  token: Address;
  recipient: Address;
  maxAmount: string;
  validAfter: number;
  validBefore: number;
  sessionId: Hex;
  authorizedSessionSigner: Address;
  refundRecipient: Address;
}

interface SmartPayerSession {
  id: string;
  vaultAddress: string;
  agentAddress: string;
  serviceAuthorizationId: string;
  serviceId: string;
  network: string;
  bindingFingerprint: string;
  payerAddress: Address;
  token: Address;
  recipient: Address;
  maxAmount: string;
  validAfter: number;
  validBefore: number;
  sessionId: Hex;
  authorizedSessionSigner: Address;
  refundRecipient: Address;
  chainId: number;
  status: "registered" | "canceled" | string;
  lifecycleStatus: "registered" | "canceled" | "expired" | string;
  createdAt: string;
  updatedAt: string;
}
```

## Discovery and service allowlist

Discovery returns the service catalog using the backend contract's snake\_case fields. Undefined filters are omitted from the query string.

```typescript
const discovery = await platform.listDiscoveryServices({
  source: "marketplace",
  trust_tier: "verified",
  category: "api",
  q: "weather",
  page: 1,
  limit: 24,
});

const [service] = discovery.services;
console.log(service.pay_to, service.trust_tier);
```

Preview a catalog service before adding it to an agent's allowlist:

```typescript
const preview = await platform.previewServiceAllowlist(vaultAddress, agentAddress, {
  service_id: service.id,
  token: tokenAddress,
});

console.log(preview.pay_to, preview.binding_fingerprint);
```

Adding the service is an operator-session write with a different auth boundary: the backend route is SIWE-JWT-only (`AuthUser`, not `DualAuth`) because it mints operator-signable calldata, and it rejects `nab_sk_` API keys by construction. It is therefore **not** on `PlatformClient` — use `PlatformOperatorClient` with the vault owner's SIWE session JWT (issued by `POST /auth/siwe/verify`, or carried by an active dashboard session).

Call it after the operator confirms the host, recipient, binding fingerprint, and spend caps. Caps are human decimal strings — the server resolves the token's on-chain decimals and converts to base units itself. The response includes an unsigned transaction for the operator to sign and submit.

```typescript
import { PlatformOperatorClient } from "@newton-xyz/isaac";

const operator = new PlatformOperatorClient({
  baseUrl: "https://api.example.com",
  sessionJwt, // SIWE session JWT — never a nab_sk_ API key
});

const { unsigned_tx, base_policy_id, authorization_id } =
  await operator.addServiceAllowlist(vaultAddress, agentAddress, {
    service_id: service.id,
    token: tokenAddress,
    max_daily_spend: "100", // human decimal string, e.g. 100 USDC
    max_per_tx: "10",
    acknowledged_host: preview.host,
    expected_pay_to: preview.pay_to,
    expected_binding_fingerprint: preview.binding_fingerprint,
    acknowledged: true, // required for untrusted tiers
  });
```

See the [Direction 13 backend contract](../../../../../docs/demos/direction-13-backend-contract.md) for the wire-level route and field names.

## Admin transactions

These return an unsigned transaction for you to sign and submit — the platform never holds the operator key.

```typescript
const tx = await platform.withdrawTx(vaultAddress, tokenAddress, "500000", recipient);
await platform.shutdownTx(vaultAddress);
await platform.unpauseTx(vaultAddress);
```

## Card rail

Each method takes the vault address and a body object; `simulateCardAuth` also takes the card token.

```typescript
await platform.linkCardProgram(vaultAddress, {
  program_id: "...",
  api_key: "...",
});

const card = await platform.createCard(vaultAddress, {
  agent_address: agentAddress, // optional — bind the card to an agent
});

await platform.setCardPolicy(vaultAddress, {
  card_policy_params: policy,
});

// Sandbox only — simulate an authorization against an issued card.
const auth = await platform.simulateCardAuth(vaultAddress, cardToken, {
  amount: 1000,
  descriptor: "Coffee Shop",
});
```

See [Issue a Card](/guides/issue-a-card) for the full flow.

## See also

* [ModularVault](/reference/sdk/modular-vault) — connect to a vault and read balances.
* [createX402Fetch](/reference/sdk/create-x402-fetch) — pay 402-gated endpoints or build smart-payer payloads.
* [FacilitatorClient](/reference/sdk/facilitator-client) — charge agents to call your API.
