Quickstart

Map your first WalletKit transaction intent

This guide walks through the core WalletKit workflow: authenticate, connect a sandbox provider profile, list wallets, and submit a policy-bound transaction intent.

Prerequisites

  • An Alloy API key — request sandbox access
  • A custody provider account for live integration planning, or the sandbox provider profile for docs testing
  • Node.js 18+ or Python 3.9+ (optional — you can use cURL directly)
1

Install the SDK

# No install needed — use cURL directly
export ALLOY_API_KEY="your-sandbox-key"
2

Authenticate

Pass your API key as a Bearer token. The sandbox accepts test keys immediately.

curl -X GET https://sandbox.api.alloy.build/v1/health \
  -H "Authorization: Bearer $ALLOY_API_KEY"

# Response: {"status": "ok", "environment": "sandbox"}
3

Connect a provider

Connect your custody provider profile. In sandbox mode, use type: "sandbox" for a test profile with seeded wallets.

curl -X POST https://sandbox.api.alloy.build/v1/providers/connect \
  -H "Authorization: Bearer $ALLOY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "sandbox",
    "name": "My Sandbox Provider"
  }'
4

List wallets

Fetch wallets across all connected providers through a single, normalized API.

curl -X GET https://sandbox.api.alloy.build/v1/wallets \
  -H "Authorization: Bearer $ALLOY_API_KEY"

# Response:
# {
#   "wallets": [
#     {
#       "id": "wal_sb_001",
#       "name": "USDC Operations",
#       "provider": "sandbox",
#       "assets": [{"symbol": "USDC", "balance": "50000.00"}]
#     }
#   ]
# }
5

Submit a transaction intent

Transaction intents pass through policy and risk evaluation before reaching the provider. The response includes a deterministic status and policy receipt.

curl -X POST https://sandbox.api.alloy.build/v1/wallets/wal_sb_001/transaction-intents \
  -H "Authorization: Bearer $ALLOY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "asset": "USDC",
    "amount": "1000.00",
    "destination": {
      "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18"
    },
    "policy": "standard-transfer",
    "idempotency_key": "inv-2024-0847"
  }'

# Response:
# {
#   "id": "txn_int_a7f3e2",
#   "status": "approved",
#   "policy_receipt": "pk_eval_2024_a7f3",
#   "risk_score": 0.12,
#   "provider_tx_id": "fb_tx_9k2m"
# }

Transaction intent state machine

Every transaction intent follows a deterministic state machine. Your integration only needs to handle these states.

created -> policy_check -> risk_check -> approved -> submitted -> confirmed
Branch: pending_human_approval
Branch: rejected (policy or risk)
Terminal: failed

Verify webhook signatures

Alloy signs webhook payloads with HMAC-SHA256. Always verify before processing.

import crypto from 'crypto';

function verifyWebhook(payload, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}