Skip to content

Proxy API ​

Server-side Canton ledger access using scoped API keys.


Overview ​

The Proxy API allows backend services, bots, and automation workflows to interact with the Canton ledger as a specific party. This is the only external API available to third-party applications — all admin and Canton APIs are internal to the portal and not accessible externally.

To use the Proxy API, request a scoped API key from your instance operator. Keys are created in the admin panel and bound to a specific Canton party with optional restrictions.

All requests are:

  • Bound to a single party configured on the API key
  • Restricted by package/template/choice whitelists (if configured)
  • Rate-limited per endpoint
  • Audit-logged with operation, status, duration, and IP

Authentication ​

Include the API key in the X-API-Key header:

X-API-Key: cwp_a1b2c3d4e5f6...

Obtain a key from your instance operator — keys are created in the admin panel under Scoped API Endpoints and shown only once at creation.


Endpoints ​

Query Contracts ​

POST /api/proxy/query

Query active contracts visible to the bound party.

bash
curl -X POST https://your-vault/api/proxy/query \
  -H "X-API-Key: cwp_your_key" \
  -H "Content-Type: application/json" \
  -d '{"templateId": "abc123...#DeFi:Position", "filter": {}}'
json
// Request
{
  "templateId": "abc123...#DeFi:Position",
  "filter": { "owner": "party::..." }
}

// Response
{
  "success": true,
  "data": [
    {
      "contractId": "00abc...",
      "templateId": "abc123...#DeFi:Position",
      "payload": { "owner": "party::...", "shares": "100.0" }
    }
  ]
}
FieldTypeRequiredDescription
templateIdstringYesFully qualified template ID (packageId#Module:Template)
filterobjectNoPayload field filters

Create Contract ​

POST /api/proxy/create

Create a new contract instance.

bash
curl -X POST https://your-vault/api/proxy/create \
  -H "X-API-Key: cwp_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "templateId": "abc123...#Orders:LimitOrder",
    "payload": {
      "trader": "party::...",
      "inputToken": "ETH",
      "outputToken": "USDC",
      "inputAmount": "1.0"
    }
  }'
json
// Response
{
  "success": true,
  "data": { "contractId": "00def..." }
}
FieldTypeRequiredDescription
templateIdstringYesFully qualified template ID
payloadobjectYesContract create arguments

Exercise Choice ​

POST /api/proxy/exercise

Execute a choice on an existing contract.

bash
curl -X POST https://your-vault/api/proxy/exercise \
  -H "X-API-Key: cwp_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "contractId": "00abc...",
    "templateId": "abc123...#Orders:LimitOrder",
    "choice": "Fill",
    "argument": { "filler": "party::...", "fillAmount": "1.0" }
  }'
json
// Response
{
  "success": true,
  "data": { "exerciseResult": { "outputAmount": "3000.0" } }
}
FieldTypeRequiredDescription
contractIdstringYesTarget contract ID
templateIdstringYesFully qualified template ID
choicestringYesChoice name to exercise
argumentobjectNoChoice arguments (default {})

Transfer CC (Amulet) ​

POST /api/proxy/cc-transfer

Transfer Canton Coin (CC) to a receiver using TransferPreapproval. The sender is locked to the API key's bound party — you cannot transfer as another party. The receiver must have a TransferPreapproval created (set up during user onboarding or via admin).

bash
curl -X POST https://your-vault/api/proxy/cc-transfer \
  -H "X-API-Key: cwp_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "receiverParty": "alice::1220abc...",
    "amount": "10.0",
    "description": "Payment for services"
  }'
json
// Response
{
  "success": true,
  "data": {
    "amount": "10.0",
    "receiverParty": "alice::1220abc...",
    "senderParty": "bob::1220def...",
    "deduplicationId": "proxy-cc-..."
  }
}
FieldTypeRequiredDescription
receiverPartystringYesReceiver's full party ID
amountstringYesCC amount to transfer
descriptionstringNoOptional transfer description

Prerequisites:

  • The receiver must have a TransferPreapproval contract (created during onboarding or via admin panel)
  • The sender (API key's bound party) must have sufficient CC balance

How it works: Internally uses the Splice wallet API's TransferPreapproval_Send mechanism. The receiver pre-consented when their preapproval was created — no accept step is needed. This works on both devnet and production.


Access Control ​

Proxy requests are validated against the endpoint's configuration:

  1. API key lookup — key is SHA-256 hashed and matched against stored endpoints
  2. Enabled check — endpoint must be enabled
  3. Rate limit — requests in the last minute are counted against the configured limit
  4. Package/template whitelist — if allowed_packages or allowed_templates is set, the template's package prefix must match
  5. Choice whitelist — for exercise requests, if allowed_choices is set, the choice must be listed

If no restrictions are configured, all templates and choices are allowed.


Error Responses ​

StatusMeaning
400Missing required fields
401Missing or invalid API key
403Template or choice not allowed for this endpoint
429Rate limit exceeded
500Canton ledger error

Template ID Format ​

Template IDs follow the format {packageId}#{moduleName}:{templateName}:

abc123def456...#DeFi:Position
abc123def456...#Finance.Orders:LimitOrder

The package ID is the hex hash returned when uploading a DAR file.


Example: Trading Bot ​

python
import requests

API_KEY = "cwp_a1b2c3d4..."
BASE_URL = "https://your-vault.example.com"
TEMPLATE = "abc123...#Trading:Order"

headers = {
    "X-API-Key": API_KEY,
    "Content-Type": "application/json"
}

# Query open orders
orders = requests.post(f"{BASE_URL}/api/proxy/query", headers=headers, json={
    "templateId": TEMPLATE
}).json()["data"]

# Cancel an order
for order in orders:
    requests.post(f"{BASE_URL}/api/proxy/exercise", headers=headers, json={
        "contractId": order["contractId"],
        "templateId": TEMPLATE,
        "choice": "Cancel",
        "argument": {}
    })

Next Steps ​

Enterprise-grade multi-chain wallet infrastructure.