# Palisade [[Source]](https://github.com/ripple/simpleXRPL/blob/95b977b15f8950c5bc076b25165217869c0b06d3/src/custodians/palisade/config.ts#L40) Palisade is a Wallet-as-a-Service. This connector authenticates via OAuth2 client credentials and acts on specific vaults/wallets. See: [Getting started with the API](https://docs.ripple.com/products/wallet/getting-started/getting-started-api) for instructions on creating API credentials to fill in this constructor. For a full table of Palisade v2 API operations and how `simpleXRPL` uses them, see: [Palisade API — simpleXRPL coverage](https://github.com/ripple/simpleXRPL/blob/main/docs/palisade-api-coverage.md). ## PalisadeCustody.create() Exchanges the credentials and discovers the org's wallets. ### Signature ```ts PalisadeCustody.create(config: PalisadeCustodyConfig): Promise ``` ### Config | Field | Type | Required | Description | | --- | --- | --- | --- | | `baseUrl` | `string` | Yes | Palisade API base URL (must be HTTPS). | | `credentials` | `PalisadeCredentials` | Yes | The wallet-read and transactions API credentials. See [Credentials](#credentials). | | `credentials.wallets` | `object` | Yes | Wallet-read credential — authorizes account discovery (`GET /v2/wallets`). A `{ clientId, clientSecret }` pair. | | `credentials.transactions` | `object` | Yes | Transactions credential — authorizes signing and submission. A `{ clientId, clientSecret }` pair. | | `credentials.scoped` | `object` | No | Per-scope credentials for the [`palisade.api`](#palisadeapicall) surface, keyed by Palisade permission scope (e.g. `Policies`, `Webhooks`). See [Credentials](#credentials). | | `primary` | `PalisadeWalletRef` | Yes | The wallet used when an operation is called without an explicit account. | | `primary.vaultId` | `string` | Yes | The primary wallet's vault id. | | `primary.walletId` | `string` | Yes | The primary wallet's id. | | `allowRawSigning` | `boolean` | No | Allow the raw fallback for transactors/fields Palisade can't map natively. Defaults to `false`. | | `defaultTimeoutMs` | `number` | No | How long to wait for a native submission to reach a terminal status. | | `http` | `object` | No | A custom HTTP transport (implements `PalisadeHttpPort`). Defaults to the production fetch port; most callers omit it. | | `now` | `() => number` | No | Injectable clock for the auth service, returning epoch ms, e.g. `() => Date.now()`. Defaults to `Date.now`. | Caution Enabling `allowRawSigning` weakens the custodian's controls. On the raw path the custodian signs an opaque payload rather than a structured operation, so its transaction-level controls (transfer policies, allow-lists, and approval rules keyed to operation semantics) cannot inspect what is being signed. `xrpl.js` protocol validation still runs on every path, so malformed transactions are still rejected; what is lost is the custodian's ability to reason about the transaction's intent. Leave it off unless a specific transactor requires it, and prefer routing those operations through a signer that models them natively. ### Credentials Palisade scopes one permission set per credential, so the connector requires **two**: a `wallets` credential for discovery and a `transactions` credential for signing and submission. Requests route between them by HTTP method — reads (`GET`) go on `wallets`, mutations on `transactions`. `credentials.scoped` adds optional tag-based routing for the [`palisade.api`](#palisadeapicall) escape hatch. Each key is a Palisade permission scope (an operation's OpenAPI tag); every operation in that scope routes to its credential instead of falling back to the method-based pair. Administering policies or webhooks needs this, because those permission sets live on their own credential. ```ts credentials: { wallets: { clientId: '…', clientSecret: '…' }, transactions: { clientId: '…', clientSecret: '…' }, scoped: { Policies: { clientId: '…', clientSecret: '…' }, }, } ``` ## palisade.api.call() Call any Palisade v2 operation directly, using the escape hatch for operations the [verticals](/docs/simplexrpl/references/verticals) don't model first-class (vaults, counterparties, policies, webhooks, balances). Path params, query, body, and the response are all typed from the generated OpenAPI schema. ### Signature ```ts palisade.api.call(operationId: PalisadeOperationId, args?: PalisadeCallArgs): Promise ``` ### Parameters | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `operationId` | `PalisadeOperationId` | Yes | The Palisade operationId, e.g. `VaultService_ListGlobalWallets`. Autocompletes to every generated route. | ### Args | Field | Type | Required | Description | | --- | --- | --- | --- | | `path` | `object` | No | Path parameters, keyed by placeholder name. Required when the route template has placeholders; a missing one throws before any request is sent. | | `query` | `object` | No | Query-string parameters. | | `body` | `object` | No | JSON request body, type-checked against the operation's request schema. | Throws `SimpleXRPLError` if a required path parameter is missing, and [`PalisadeApiError`](/docs/simplexrpl/references/errors) if the API rejects the request. Note `palisade.api` is a **secondary** surface; prefer a [vertical operation](/docs/simplexrpl/references/verticals) when one exists. For a tutorial on how to use `palisade.api`, see: [Call Palisade Operations Directly](/docs/simplexrpl/tutorials/call-palisade-operations-directly). ## Example ```ts const palisade = await PalisadeCustody.create({ baseUrl: 'https://api.sandbox.palisade.co', credentials: { wallets: { clientId: process.env.PALISADE_WALLETS_CLIENT_ID ?? '', clientSecret: process.env.PALISADE_WALLETS_CLIENT_SECRET ?? '', }, transactions: { clientId: process.env.PALISADE_TX_CLIENT_ID ?? '', clientSecret: process.env.PALISADE_TX_CLIENT_SECRET ?? '', }, }, primary: { vaultId: process.env.PALISADE_VAULT_ID ?? '', walletId: process.env.PALISADE_WALLET_ID ?? '', }, }) ```