> For the complete documentation index, see [llms.txt](https://docs.catalyx.solutions/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.catalyx.solutions/catalyx-blockchain-manager/canton-network/version-2.0/support-and-resources/api-reference.md).

# API Reference

The CatalyX REST API — endpoints, authentication, and error handling.

The CatalyX API is the integration surface for the platform. The UI is built entirely on it, so anything you can do in the UI you can automate.

It does two things:

* **Reads** validator and application state from the Kubernetes custom resources. It never writes them.
* **Proxies** privileged Canton operations — the Ledger API, the participant Admin API, the network Scan API, and the validator app's admin API — so callers do not need direct network access to the nodes.

{% hint style="warning" %}
The API is **not** read-only overall. Reading CRDs is read-only, but the proxy operations create parties and users, upload DAR packages, onboard and offboard wallet users, and authorize topology changes. Treat it as a privileged administrative API.
{% endhint %}

## Base URL and discovery

Endpoints are served under `/api/v1` on the platform hostname, for example `https://validators.example.com/api/v1/validators`.

The API publishes its own OpenAPI description:

|                  |                        |
| ---------------- | ---------------------- |
| OpenAPI document | `GET /v3/api-docs`     |
| Swagger UI       | `GET /swagger-ui.html` |

{% hint style="danger" %}
Both are served **without authentication**, so anyone who can reach the hostname can enumerate the API surface. If that is unacceptable in your environment, restrict them with a Traefik middleware via `api.ingress.middlewares`, or block the paths at your edge. See [Platform Installation](/catalyx-blockchain-manager/canton-network/version-2.0/installation-instructions-canton/platform-installation.md).

The published document also declares no security scheme, so Swagger UI has no *Authorize* control and generated clients get no authentication wiring. Add the bearer token yourself.
{% endhint %}

## Authentication

Send an OIDC bearer token on every `/api/v1` request:

```
Authorization: Bearer <access-token>
```

Tokens are validated against the JWKS endpoint configured at install time (`api.auth.jwksUri`). Signature and expiry are checked.

{% hint style="warning" %}
**In 2.0 there is no scope, audience, or per-validator authorisation.** Any token the configured issuer signs can call every endpoint, including the mutating ones. Access control must therefore be enforced at token issuance: restrict who can obtain a token for the UI client in your identity provider, and treat API access as equivalent to platform administrator access.
{% endhint %}

Unauthenticated requests return `401` with an empty body and a `WWW-Authenticate: Bearer` header.

## Namespace scoping

Every endpoint operates on the single namespace the API is configured to watch (`api.namespace` in the Helm values — see [Platform Installation](/catalyx-blockchain-manager/canton-network/version-2.0/installation-instructions-canton/platform-installation.md)). There is no namespace parameter, and resources elsewhere return `404`.

***

## Validators

<table><thead><tr><th width="90">Method</th><th width="380">Path</th><th>Returns</th></tr></thead><tbody><tr><td>GET</td><td><code>/api/v1/validators</code></td><td>Every <code>Validator</code> resource, sorted by namespace and name.</td></tr><tr><td>GET</td><td><code>/api/v1/validators/{name}</code></td><td>One <code>Validator</code> resource.</td></tr><tr><td>GET</td><td><code>/api/v1/validators/{name}/status</code></td><td>Just the resource's <code>status</code>.</td></tr><tr><td>GET</td><td><code>/api/v1/validators/{name}/details</code></td><td>Aggregate view: the validator, its Ledger API endpoint, the authenticated user, all ledger users, and all DAR packages.</td></tr><tr><td>GET</td><td><code>/api/v1/validators/{name}/balances</code></td><td>Canton Coin balance from the Scan service.</td></tr><tr><td>GET</td><td><code>/api/v1/validators/{name}/traffic-status</code></td><td>Synchronizer traffic counters.</td></tr><tr><td>GET</td><td><code>/api/v1/validators/{name}/participant-status</code></td><td>Participant node health.</td></tr><tr><td>GET</td><td><code>/api/v1/validators/{name}/keys</code></td><td>Public keys in the participant's key vault.</td></tr><tr><td>GET</td><td><code>/api/v1/validators/{name}/identity-dump</code></td><td>The participant identity export, as a file download.</td></tr></tbody></table>

{% hint style="info" %}
`/details` degrades rather than failing. If one of its sections cannot be fetched, the response still returns `200` with that section replaced by a corresponding `*Error` field. Check for those fields rather than relying on the status code alone.

`/balances` behaves similarly: a balance lookup failure returns `200` with an `error` field in the body.
{% endhint %}

{% hint style="danger" %}
`/identity-dump` returns the validator's cryptographic identity. Protect calls to it as you would a private key export, and never log the response body. See [Identity Dumps & Database Backups](/catalyx-blockchain-manager/canton-network/version-2.0/validator-management/identity-dumps.md).
{% endhint %}

## Applications

<table><thead><tr><th width="90">Method</th><th width="380">Path</th><th>Returns</th></tr></thead><tbody><tr><td>GET</td><td><code>/api/v1/applications</code></td><td>Every <code>Application</code> resource.</td></tr><tr><td>GET</td><td><code>/api/v1/applications/{name}</code></td><td>One <code>Application</code> resource.</td></tr><tr><td>GET</td><td><code>/api/v1/applications/{name}/status</code></td><td>Just the resource's <code>status</code>.</td></tr><tr><td>GET</td><td><code>/api/v1/applications/metrics</code></td><td>Resource metrics for every application.</td></tr><tr><td>GET</td><td><code>/api/v1/applications/{name}/metrics</code></td><td>Resource metrics for one application.</td></tr></tbody></table>

Metrics report **CPU in millicores and memory in bytes**. Any usage, request, or limit value may be `null`. A `metricsAvailable: false` response means the cluster metrics API was unreachable — usually a missing `metrics-server`.

## Parties

<table><thead><tr><th width="90">Method</th><th width="440">Path</th><th>Purpose</th></tr></thead><tbody><tr><td>GET</td><td><code>/api/v1/validators/{name}/parties</code></td><td>Look up parties by ID prefix. Optional <code>partyId</code> query parameter.</td></tr><tr><td>POST</td><td><code>/api/v1/validators/{name}/parties</code></td><td>Allocate a participant-managed party. Requires the <code>partyIdHint</code> query parameter.</td></tr><tr><td>GET</td><td><code>/api/v1/validators/{name}/local-parties</code></td><td>Parties hosted by this participant, with their hosts, permissions, and threshold.</td></tr><tr><td>GET</td><td><code>/api/v1/validators/{name}/external-parties</code></td><td>Externally-signed parties onboarded here.</td></tr><tr><td>GET</td><td><code>/api/v1/validators/{name}/topology-proposals</code></td><td>Hosting proposals on the synchronizer, each flagged with whether this participant must act.</td></tr><tr><td>GET</td><td><code>/api/v1/validators/{name}/participant-lookup</code></td><td>Advisory check of a participant UID. Requires <code>participantUid</code>.</td></tr></tbody></table>

## External parties

The onboarding and hosting flow. See [External & Multi-Host Parties](/catalyx-blockchain-manager/canton-network/version-2.0/validator-management/external-and-multi-host-parties.md) for the concepts.

<table><thead><tr><th width="90">Method</th><th width="470">Path</th><th>Purpose</th></tr></thead><tbody><tr><td>POST</td><td><code>/api/v1/validators/{name}/external-parties/generate-topology</code></td><td>Generate topology transactions and the multi-hash to sign.</td></tr><tr><td>POST</td><td><code>/api/v1/validators/{name}/external-parties/allocate</code></td><td>Allocate the party using the party's signature over the multi-hash.</td></tr><tr><td>POST</td><td><code>/api/v1/validators/{name}/external-parties/approve-pending</code></td><td>Authorize a hosting proposal naming this participant. Requires <code>partyId</code>.</td></tr><tr><td>POST</td><td><code>/api/v1/validators/{name}/external-parties/amend-hosting/prepare</code></td><td>Prepare a hosting change, returning a transaction hash to sign.</td></tr><tr><td>POST</td><td><code>/api/v1/validators/{name}/external-parties/amend-hosting/submit</code></td><td>Submit the signed hosting change.</td></tr></tbody></table>

### `generate-topology`

<table><thead><tr><th width="290">Field</th><th width="130">Required</th><th>Notes</th></tr></thead><tbody><tr><td><code>partyHint</code></td><td>Yes</td><td>Incorporated into the generated party ID.</td></tr><tr><td><code>publicKeyBase64</code></td><td>Yes</td><td>X.509 SubjectPublicKeyInfo, DER encoded, then Base64.</td></tr><tr><td><code>keySpec</code></td><td>No</td><td>Defaults to Ed25519.</td></tr><tr><td><code>hosts</code></td><td>No</td><td>Array of <code>{ participantUid, permission }</code>. <code>permission</code> is <code>CONFIRMING</code> or <code>OBSERVING</code>; <code>participantUid</code> must be <code>alias::fingerprint</code>. Omit for a single-hosted party.</td></tr><tr><td><code>confirmationThreshold</code></td><td>No</td><td>Defaults to <code>1</code>. Must not exceed the number of confirming participants.</td></tr><tr><td><code>localParticipantObservationOnly</code></td><td>No</td><td>Defaults to <code>false</code>. When <code>true</code>, this validator observes but does not confirm.</td></tr></tbody></table>

Returns the generated `partyId`, the `multiHash` to sign, the `topologyTransactions`, the `synchronizerId`, and `otherHostingParticipantUids`.

{% hint style="danger" %}
**This call does not verify that the participant UIDs you name exist.** It succeeds for an unknown UID; `allocate` then fails — after the party has already signed the multi-hash, which consumes it. Use `participant-lookup` to check every UID first.
{% endhint %}

### `allocate`

Requires `synchronizerId`, `topologyTransactions`, `signature`, and `publicKeyFingerprint`. `signatureFormat` and `signingAlgorithmSpec` default to the Ed25519 pair and must match the key you used.

Returns `partyId`, the `hosts` still owing approval, and `complete` — which is `false` until every named host has authorized.

{% hint style="warning" %}
`allocate` affects **this participant only**. It does not fan out to co-hosts. Each co-host authorizes independently via `approve-pending`.
{% endhint %}

### `amend-hosting`

`prepare` takes `partyId`, the complete new `hosts` array, and `confirmationThreshold`, and returns the current and next serial plus a `transactionHash` to sign. `submit` takes the signed transaction back.

{% hint style="warning" %}
`hosts` is a **complete replacement**, not a delta. Any host you omit stops hosting the party. At least one must remain.
{% endhint %}

## Ledger users

<table><thead><tr><th width="90">Method</th><th width="420">Path</th><th>Purpose</th></tr></thead><tbody><tr><td>POST</td><td><code>/api/v1/validators/{name}/users</code></td><td>Create a ledger user.</td></tr><tr><td>POST</td><td><code>/api/v1/validators/{name}/users/{userId}</code></td><td>Update a user's primary party, deactivation state, and annotations.</td></tr><tr><td>GET</td><td><code>/api/v1/validators/{name}/users/{userId}/rights</code></td><td>List a user's rights.</td></tr><tr><td>POST</td><td><code>/api/v1/validators/{name}/users/{userId}/rights</code></td><td>Replace a user's rights.</td></tr></tbody></table>

User creation and rights take **query or form parameters**, not a JSON body: `userId`, `primaryParty`, the boolean flags `participantAdmin`, `identityProviderAdmin`, `canReadAsAnyParty`, `canExecuteAsAnyParty`, and the repeatable party lists `canActAs`, `canReadAs`, `canExecuteAs`.

{% hint style="danger" %}
Updating rights **revokes and re-grants** — the rights you send become the user's complete set. Read the current rights first and send them back with your change applied, or you will silently remove access.
{% endhint %}

There is no endpoint that lists users directly. The user list is the `allUsers` field of `/details`.

## Wallet users

<table><thead><tr><th width="90">Method</th><th width="440">Path</th><th>Purpose</th></tr></thead><tbody><tr><td>GET</td><td><code>/api/v1/validators/{name}/wallet-users</code></td><td>List wallet usernames.</td></tr><tr><td>POST</td><td><code>/api/v1/validators/{name}/wallet-users</code></td><td>Onboard a wallet user. Body <code>{ "name": "&#x3C;username>" }</code>.</td></tr><tr><td>DELETE</td><td><code>/api/v1/validators/{name}/wallet-users/{username}</code></td><td>Offboard a wallet user.</td></tr></tbody></table>

The validator refuses to offboard its own wallet user, returning `409`.

## Wallet Gateway

<table><thead><tr><th width="90">Method</th><th width="420">Path</th><th>Purpose</th></tr></thead><tbody><tr><td>GET</td><td><code>/api/v1/validators/{name}/wallet-gateway/wallets</code></td><td>Lists the wallets Wallet Gateway manages for this validator.</td></tr><tr><td>POST</td><td><code>/api/v1/validators/{name}/wallet-gateway/wallets</code></td><td>Creates a wallet for a party. Requires a party hint and a signing provider (<code>dfns</code> today); optionally a primary flag and a DFNS vault.</td></tr><tr><td>GET</td><td><code>/api/v1/validators/{name}/wallet-gateway/providers/dfns</code></td><td>Reads the validator's current DFNS provider settings. Never returns credentials.</td></tr><tr><td>PUT</td><td><code>/api/v1/validators/{name}/wallet-gateway/providers/dfns</code></td><td>Updates the enabled flag, connection details, and/or credentials for the DFNS provider. Each field is optional per call. Takes effect immediately, without editing the <code>Validator</code> resource or restarting anything.</td></tr></tbody></table>

{% hint style="info" %}
These calls only manage wallet *custody* — creating a wallet and reading its state. Nothing here asks Wallet Gateway to sign a transaction; that flow does not exist yet. See [Wallet Gateway](/catalyx-blockchain-manager/canton-network/version-2.0/validator-management/wallet-gateway.md#whats-not-yet-available).
{% endhint %}

***

## DAR packages

<table><thead><tr><th width="90">Method</th><th width="380">Path</th><th>Purpose</th></tr></thead><tbody><tr><td>POST</td><td><code>/api/v1/validators/{name}/dars/upload</code></td><td>Upload a DAR. <code>multipart/form-data</code>, part name <code>file</code>.</td></tr></tbody></table>

The package list is the `dars` field of `/details`.

## Health

<table><thead><tr><th width="90">Method</th><th width="280">Path</th><th>Auth</th></tr></thead><tbody><tr><td>GET</td><td><code>/actuator/health</code></td><td>Public</td></tr><tr><td>GET</td><td><code>/actuator/info</code></td><td>Public</td></tr></tbody></table>

These are the platform's own health endpoints, used by Kubernetes probes. Validator component metrics are exposed by the components themselves, not here.

## Canton console

`GET /api/ws/canton-console` upgrades to a WebSocket carrying a raw terminal stream. It is not a REST endpoint and is intended for the console UI. See [Canton Console](/catalyx-blockchain-manager/canton-network/version-2.0/console-guide-canton/canton-console.md), including its security notes.

***

## Conventions

<table><thead><tr><th width="200">Aspect</th><th>Behaviour in 2.0</th></tr></thead><tbody><tr><td><strong>Status codes</strong></td><td>Success is always <code>200</code> — including creates, which do not return <code>201</code>, and deletes, which return <code>200</code> with a body.</td></tr><tr><td><strong>Pagination</strong></td><td>None. Collection endpoints return complete lists. A <code>nextPageToken</code> may appear in passthrough payloads but cannot be used — there is no corresponding request parameter.</td></tr><tr><td><strong>Filtering</strong></td><td>Only <code>partyId</code> on party lookup and <code>participantUid</code> on participant lookup. Both are <strong>prefix</strong> filters.</td></tr><tr><td><strong>Sorting</strong></td><td>Validators and applications are sorted by namespace and name. Not client-controllable.</td></tr><tr><td><strong>Rate limiting</strong></td><td>None.</td></tr><tr><td><strong>Timeouts</strong></td><td>Upstream calls have their own timeouts; an upstream that is slow or unavailable surfaces as <code>502</code>.</td></tr></tbody></table>

{% hint style="warning" %}
Because there is no pagination, a party lookup on a production participant can match a very large number of parties. Always send a specific enough `partyId` prefix.
{% endhint %}

## Errors

Two response shapes are in use, and the status code alone does not tell you which you will get. Handle both.

**Validation and not-found errors**

```json
{
  "timestamp": "2026-08-18T10:15:30.123456+00:00",
  "status": 404,
  "error": "Validator not found: <namespace>/my-validator"
}
```

**Upstream errors**

```json
{
  "endpoint": "my-validator-participant.<namespace>.svc.cluster.local:5001",
  "error": "UNAVAILABLE: io exception"
}
```

`401` and `403` return an **empty body**. A robust client should read `error` from the body when present and fall back to the status code otherwise.

### Status codes

| Code  | Meaning                                                                            |
| ----- | ---------------------------------------------------------------------------------- |
| `200` | Success — including creates and deletes                                            |
| `400` | Invalid request. The `error` field names the problem                               |
| `401` | Missing, invalid, or expired token. Empty body                                     |
| `404` | No such validator, application, or party                                           |
| `409` | Conflict — for example offboarding the validator's own wallet user                 |
| `422` | Canton rejected the request as invalid, typically a signature that does not verify |
| `502` | An upstream Canton, Scan, or validator app call failed                             |

{% hint style="info" %}
`422` and `502` are worth distinguishing in your integration. `422` means the request was wrong and retrying will not help. `502` means something upstream was unavailable and retrying may succeed.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.catalyx.solutions/catalyx-blockchain-manager/canton-network/version-2.0/support-and-resources/api-reference.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
