Anchorage Digital Integration
Anchorage Digital is the first federally chartered crypto bank in the US (OCC charter, 2021). For products working with institutional clients or requiring banking-level custody, Anchorage is serious option. No need to build own custodial infrastructure, get separate storage licenses, negotiate with insurers — Anchorage handles all this. API integration allows embedding institutional-grade custody directly into your product.
What Integration Provides
Anchorage provides REST API for managing:
- Custody — asset storage with hardware key isolation (HSM-based, not pure software)
- Transactions — create, sign, and broadcast on-chain transactions via custody pipeline
- Staking — delegation for PoS assets (ETH, SOL, MATIC, ADA and others) with reporting
- Trading — OTC trading desk integration
- Governance — on-chain voting on behalf of custodied assets
API built on REST principles, authentication via JWT + API keys. Sandbox environment available for development.
Integration Architecture
Authentication and Security
Anchorage uses two-level authentication: API key + request signature. Each request must be signed with private key, public counterpart registered in system:
import crypto from "crypto";
interface AnchorageRequestSigner {
apiKeyId: string;
privateKey: string; // PEM format, ECDSA P-256
}
function signRequest(
signer: AnchorageRequestSigner,
method: string,
path: string,
body: object | null,
timestamp: number
): string {
const bodyString = body ? JSON.stringify(body) : "";
const payload = `${timestamp}${method}${path}${bodyString}`;
const sign = crypto.createSign("SHA256");
sign.update(payload);
const signature = sign.sign(signer.privateKey, "base64");
return `Signature keyId="${signer.apiKeyId}",algorithm="ecdsa-p256",signature="${signature}"`;
}
async function anchorageRequest(
signer: AnchorageRequestSigner,
method: string,
path: string,
body?: object
): Promise<Response> {
const timestamp = Math.floor(Date.now() / 1000);
const authHeader = signRequest(signer, method, path, body ?? null, timestamp);
return fetch(`https://api.anchorage.com${path}`, {
method,
headers: {
"Content-Type": "application/json",
"Api-Access-Key": signer.apiKeyId,
"Authorization": authHeader,
"X-Timestamp": String(timestamp),
},
body: body ? JSON.stringify(body) : undefined,
});
}
Transaction Creation and Approval Workflow
Transactions pass through configurable approval workflow. Not simple "send and forget" — depending on vault settings transaction can require confirmation from multiple operators, Anchorage mobile app (out-of-band approval), or auto-execute if passes policy rules.
interface CreateTransactionRequest {
vaultId: string;
assetType: string; // "ETHEREUM", "BITCOIN", "SOLANA" etc
destinationAddress: string;
amount: string; // in base units (wei for ETH)
note?: string;
externalTxId?: string; // your internal ID for idempotency
}
async function createWithdrawal(
signer: AnchorageRequestSigner,
request: CreateTransactionRequest
): Promise<{ transactionId: string; status: string }> {
const response = await anchorageRequest(
signer, "POST", "/v2/transactions", request
);
if (!response.ok) {
const error = await response.json();
throw new Error(`Anchorage API error: ${error.message}`);
}
return response.json();
}
// Polling status — transaction passes through PENDING_APPROVAL → APPROVED → BROADCASTING → DONE
async function waitForTransaction(
signer: AnchorageRequestSigner,
transactionId: string,
timeoutMs = 300_000
): Promise<string> {
const start = Date.now();
while (Date.now() - start < timeoutMs) {
const response = await anchorageRequest(
signer, "GET", `/v2/transactions/${transactionId}`
);
const tx = await response.json();
if (tx.status === "DONE") return tx.txHash;
if (["FAILED", "REJECTED"].includes(tx.status)) {
throw new Error(`Transaction ${tx.status}: ${tx.rejectionReason}`);
}
await new Promise(resolve => setTimeout(resolve, 5000));
}
throw new Error("Transaction polling timeout");
}
Working with Balances and Addresses
Anchorage organizes assets in vaults (logical storages) and wallets (addresses of specific assets within vault). Typically create separate vault for each client:
// Get balance of specific asset in vault
async function getVaultBalance(
signer: AnchorageRequestSigner,
vaultId: string,
assetType: string
): Promise<{ available: string; total: string }> {
const response = await anchorageRequest(
signer, "GET", `/v2/vaults/${vaultId}/assets/${assetType}`
);
const asset = await response.json();
return {
available: asset.availableBalance,
total: asset.totalBalance,
};
}
// Get deposit address for replenishment
async function getDepositAddress(
signer: AnchorageRequestSigner,
vaultId: string,
assetType: string
): Promise<string> {
const response = await anchorageRequest(
signer, "GET", `/v2/vaults/${vaultId}/assets/${assetType}/addresses`
);
const data = await response.json();
return data.addresses[0].address;
}
Typical Integration Scenarios
Exchange / Trading Platform — custody of user assets in Anchorage vaults, withdrawal via Transaction API with approval workflow, deposits via webhook notifications of incoming transactions.
Fund Administrator — create separate vault per fund, staking via Anchorage Earn, reporting via Transaction history API.
Corporate Treasury — manage treasury in multiple assets, automatic rebalancing via API, audit trail for compliance.
Limitations and What to Know
Anchorage is not self-service. Integration starts with enterprise sales process, KYB, contract signing. Sandbox available after initial approval. Pricing negotiated per contract, typically basis points from AUM + fixed transaction fee.
Transaction finality depends on approval policy: if manual approval configured, time from creation to execution can be hours. Need to account for this in UX — user should understand withdrawal isn't instant.
Supported assets constantly expanding, but exotic L2 tokens may be missing. Check current list via /v2/assets endpoint before design.







