Medici Protocol

Quickstart

Your first API call in 5 minutes.

Prerequisites

Dev credentials — These examples use the dev environment well-known credentials. For production, use your own Keycloak client secret and token.

Step 1: Get a Keycloak Token

The Medici protocol uses Keycloak for identity. Every API call needs a Bearer token. Request one with the client_credentials grant:

# Request a service-account token (RS256 JWT, 5-minute expiry)
TOKEN=$(curl -s -X POST \
  "https://keycloak.dev.medici.loan/realms/AppUser/protocol/openid-connect/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=medici-app" \
  -d "client_secret=" \
  | jq -r '.access_token')

# Verify the token
echo "Token length: ${#TOKEN} chars"
echo "Token preview: ${TOKEN:0:50}..."

# Decode the payload (middle segment) to inspect claims
echo "$TOKEN" | cut -d. -f2 | base64 -d 2>/dev/null | jq
Token expiry: RS256 tokens live 5 minutes. The Ledger Service auto-refreshes, but if you are calling Canton directly you must refresh before expiry.

Step 2: Health Check

Verify the Ledger Service is up and connected to Canton:

curl -s "https://canton.dev.medici.loan/api/v1/health" | jq

# Expected response:
# {
#   "status": "ok",
#   "canton": "connected",
#   "uptime": "12s"
# }

If you are using the Ledger Service (recommended), check its health endpoint:

# Ledger Service health (if running locally)
curl -s "http://localhost:8080/api/v1/health" | jq

Step 3: Read Active Contracts

Query active contracts on the Canton ledger. This example reads PublishedPrice contracts (the public price feed):

# Via Ledger Service (recommended — simpler, handles Canton quirks)
curl -s \
  -H "Authorization: Bearer $TOKEN" \
  "http://localhost:8080/api/v1/contracts/OptionIndex.Oracle/PublishedPrice" \
  | jq

# Direct Canton query (advanced — raw /v2/state/active-contracts)
curl -s -X POST \
  "https://canton.dev.medici.loan/v2/state/active-contracts" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "activeAtOffset": "",
    "templateIds": ["#option-index-tracker-v3:OptionIndex.Oracle:PublishedPrice"],
    "includeCreatedEventBlob": false
  }' | jq
Package ID note: The package reference uses the upgrade-transparent package-name form (#option-index-tracker-v3), not a content hash. This ensures the reference never goes stale across DAR rebuilds.

Step 4: Submit a Command (Optional)

Create a SplitRequest to split collateral into P and N tokens (requires a funded party on the ledger):

# Via Ledger Service — see /api/ for the full submit schema
curl -s -X POST \
  "http://localhost:8080/api/v1/commands/submit" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "templateId": "OptionIndex.Core.SplitRequest",
    "payload": {
      "depositor": "",
      "vaultAdmin": "",
      "amount": "100.0",
      "strike": "50.0",
      "maturity": "2027-01-01T00:00:00Z",
      "ticker": "BTC/USDC",
      "baseAsset": "ETH",
      "quoteAsset": "USDC",
      "oracle": "",
      "admin": "",
      "settlementDelaySeconds": "0",
      "refCid": null
    }
  }' | jq

Next Steps

TopicPage
Understand authentication in depthAuthentication
Full API reference (all 13 endpoints)Ledger Service API
Template field-by-field referenceDAML Templates
How the system fits togetherArchitecture
Learn the concepts behind the protocolLearn
Strategies and intent-based tradingStrategy Engine