# Compass API - LLM-Optimized Documentation > **Purpose**: This document provides comprehensive API documentation optimized for Large Language Models (LLMs) to understand and generate code for Compass API integrations. ## Overview Compass is a non-custodial DeFi infrastructure API that enables wallets, payment platforms, and fintechs to offer yield, lending, and trading features through a single SDK. ### Base URLs - **Production**: `https://api.compasslabs.ai` - **Staging**: `https://staging.api.compasslabs.ai` ### Authentication All requests require an API key in the header: ``` x-api-key: YOUR_API_KEY ``` --- ## Core Concepts ### Product Accounts Compass uses isolated smart contract accounts for each product type: - **Earn Account**: For yield-generating deposits (vaults, Aave, Morpho, Pendle) - **Borrow Account**: For borrowing against collateral (coming soon) - **Trade Account**: For trading operations (coming soon) Accounts are deterministic - the same user wallet + account type always maps to the same smart contract address. ### Non-Custodial Design - Compass never holds user funds or private keys - API returns unsigned transactions or EIP-712 typed data for signing - Funds flow directly between user wallets, protocols, and fee recipients ### Gas Sponsorship - Users can interact with DeFi without holding ETH - Platform sponsors gas by having a "sender" broadcast and pay for transactions - User (owner) signs EIP-712 typed data off-chain ### Embedded Fees - Platforms can monetize by adding fees to transactions - Fee types: PERCENTAGE, FIXED, PERFORMANCE (percentage of yield) - Fees are collected atomically in the same transaction --- ## API Endpoints Reference ### Account Management #### Get or Create Earn Account ``` POST /v2/earn/account ``` **Request Body:** ```json { "chain_id": 1, "owner": "0x...", "sender": "0x..." } ``` **Parameters:** - `chain_id` (integer, required): Blockchain network ID (1=Ethereum, 42161=Arbitrum, 8453=Base) - `owner` (string, required): User's wallet address that owns the account - `sender` (string, optional): Address that will broadcast transactions. If provided, returns EIP-712 typed data for gas sponsorship. If omitted, owner broadcasts their own transactions. **Response:** ```json { "account_address": "0x...", "transaction": { ... } | null, "typed_data": { ... } | null, "is_deployed": true } ``` **Notes:** - Account addresses are deterministic - same owner always gets same account address - If account not deployed, response includes deployment transaction - With sender: returns `typed_data` for owner to sign - Without sender: returns `transaction` for owner to broadcast --- ### Deposit Operations #### Deposit to Vault/Protocol ``` POST /v2/earn/deposit ``` **Request Body:** ```json { "chain_id": 1, "owner": "0x...", "sender": "0x...", "pool": "0x...", "amount": "1000000000", "fee": { "fee_recipient": "0x...", "fee_denomination": "PERCENTAGE", "fee_value": "100" } } ``` **Parameters:** - `chain_id` (integer, required): Network ID - `owner` (string, required): User's wallet address - `sender` (string, optional): For gas sponsorship - `pool` (string, required): Vault or pool address to deposit into - `amount` (string, required): Amount in base units (e.g., "1000000" for 1 USDC) - `fee` (object, optional): Fee configuration - `fee_recipient`: Address to receive fees - `fee_denomination`: "PERCENTAGE" | "FIXED" | "PERFORMANCE" - `fee_value`: Fee amount in basis points (100 = 1%) or fixed amount **Response:** ```json { "transaction": { ... } | null, "typed_data": { ... } | null } ``` **Deposit Flow:** 1. Funds move from user's wallet to their Earn Account 2. Earn Account deposits into the specified vault/protocol 3. User receives yield-bearing tokens/position 4. If fee configured, fee is deducted during the transaction --- #### Deposit to Aave ``` POST /v2/earn/deposit/aave ``` **Request Body:** ```json { "chain_id": 1, "owner": "0x...", "sender": "0x...", "pool": "aave_v3", "token": "0x...", "amount": "1000000000" } ``` **Additional Parameters:** - `pool` (string, required): Aave pool identifier (e.g., "aave_v3") - `token` (string, required): Token address to deposit --- #### Deposit to Pendle ``` POST /v2/earn/deposit/pendle ``` **Request Body:** ```json { "chain_id": 1, "owner": "0x...", "sender": "0x...", "market": "0x...", "token_in": "0x...", "amount": "1000000000", "slippage": "0.01" } ``` **Additional Parameters:** - `market` (string, required): Pendle market address - `token_in` (string, required): Input token address - `slippage` (string, optional): Slippage tolerance (default "0.01" = 1%) --- ### Withdrawal Operations #### Withdraw from Vault/Protocol ``` POST /v2/earn/withdraw ``` **Request Body:** ```json { "chain_id": 1, "owner": "0x...", "sender": "0x...", "pool": "0x...", "amount": "1000000000", "fee": { "fee_recipient": "0x...", "fee_denomination": "PERFORMANCE", "fee_value": "2000" } } ``` **Parameters:** - Same as deposit, plus: - `amount` (string, required): Amount of shares/tokens to withdraw, or "max" for full withdrawal **Performance Fee Example:** - User deposited 10,000 USDC - Position grew to 10,500 USDC (500 USDC profit) - Performance fee of 20% (fee_value: "2000") - User receives: 10,400 USDC - Fee recipient receives: 100 USDC (20% of 500 profit) --- #### Withdraw from Aave ``` POST /v2/earn/withdraw/aave ``` #### Withdraw from Pendle ``` POST /v2/earn/withdraw/pendle ``` --- ### Position Queries #### Get User Positions ``` GET /v2/earn/positions ``` **Query Parameters:** - `chain_id` (integer, required): Network ID - `owner` (string, required): User's wallet address **Response:** ```json { "positions": [ { "pool": "0x...", "pool_name": "USDC Vault", "protocol": "erc4626", "underlying_token": "0x...", "underlying_symbol": "USDC", "shares": "1000000000", "underlying_value": "1050000000", "apy": "0.05" } ], "total_value_usd": "1050.00" } ``` --- #### Get Aave Positions ``` GET /v2/earn/positions/aave ``` #### Get Pendle Positions ``` GET /v2/earn/positions/pendle ``` --- ### Vault Discovery #### List Available Vaults ``` GET /v2/earn/vaults ``` **Query Parameters:** - `chain_id` (integer, required): Network ID - `protocol` (string, optional): Filter by protocol ("erc4626", "aave_v3", "morpho", "pendle") **Response:** ```json { "vaults": [ { "address": "0x...", "name": "USDC Vault", "protocol": "erc4626", "underlying_token": "0x...", "underlying_symbol": "USDC", "apy": "0.05", "tvl": "10000000000000" } ] } ``` --- #### Get Aave Markets ``` GET /v2/earn/markets/aave ``` #### Get Pendle Markets ``` GET /v2/earn/markets/pendle ``` --- ### Transaction Bundling #### Bundle Multiple Actions ``` POST /v2/earn/bundle ``` **Request Body:** ```json { "chain_id": 1, "owner": "0x...", "sender": "0x...", "actions": [ { "action_type": "V2_SWAP", "token_in": "0x...", "token_out": "0x...", "amount": "1000000000", "slippage": "0.01" }, { "action_type": "V2_MANAGE", "manage_type": "DEPOSIT", "pool": "0x...", "amount": "max" } ] } ``` **Action Types:** - `V2_SWAP`: Swap tokens within the Earn Account - `V2_MANAGE`: Deposit or withdraw from vaults/protocols **V2_SWAP Parameters:** - `token_in`: Source token address - `token_out`: Destination token address - `amount`: Amount to swap - `slippage`: Slippage tolerance **V2_MANAGE Parameters:** - `manage_type`: "DEPOSIT" | "WITHDRAW" - `pool`: Vault/pool address - `amount`: Amount or "max" **Use Cases:** - Swap ETH to USDC and deposit to vault in one transaction - Withdraw from one vault and deposit to another - Rebalance positions atomically --- ### Gas Sponsorship #### Prepare Gas-Sponsored Transaction ``` POST /v2/gas_sponsorship/prepare ``` **Request Body:** ```json { "chain_id": 1, "typed_data": { ... }, "signature": "0x..." } ``` **Parameters:** - `chain_id` (integer, required): Network ID - `typed_data` (object, required): The EIP-712 typed data returned from deposit/withdraw endpoints - `signature` (string, required): Owner's signature of the typed data **Response:** ```json { "transaction": { "to": "0x...", "data": "0x...", "value": "0", "gas": "200000" } } ``` **Gas Sponsorship Flow:** 1. Call deposit/withdraw with `sender` parameter 2. Receive `typed_data` in response 3. Owner signs typed data off-chain (EIP-712) 4. Call `/gas_sponsorship/prepare` with typed data + signature 5. Sender broadcasts the returned transaction and pays gas --- ### Bridging (USDC Cross-Chain) #### Initiate Bridge ``` POST /v2/bridge/initiate ``` **Request Body:** ```json { "source_chain_id": 1, "destination_chain_id": 42161, "owner": "0x...", "amount": "1000000000", "recipient": "0x..." } ``` **Parameters:** - `source_chain_id`: Origin network - `destination_chain_id`: Target network - `owner`: User's wallet on source chain - `amount`: USDC amount in base units - `recipient` (optional): Recipient on destination chain (defaults to owner) **Supported Routes:** - Ethereum (1) ↔ Arbitrum (42161) - Ethereum (1) ↔ Base (8453) - Arbitrum (42161) ↔ Base (8453) --- #### Get Bridge Status ``` GET /v2/bridge/status ``` **Query Parameters:** - `source_chain_id`: Origin network - `transaction_hash`: Bridge initiation tx hash --- ### Swaps #### Execute Swap ``` POST /v2/earn/swap ``` **Request Body:** ```json { "chain_id": 1, "owner": "0x...", "sender": "0x...", "token_in": "0x...", "token_out": "0x...", "amount": "1000000000", "slippage": "0.01" } ``` Swaps occur within the user's Earn Account using 1inch aggregation. --- #### Get Swap Quote ``` GET /v2/earn/swap/quote ``` **Query Parameters:** - `chain_id`: Network ID - `token_in`: Source token - `token_out`: Destination token - `amount`: Amount to swap --- ## Common Workflows ### Workflow 1: Basic Deposit with Gas Sponsorship ```python # 1. Get/create user's Earn Account account_response = POST /v2/earn/account { "chain_id": 1, "owner": user_wallet, "sender": platform_wallet } # 2. If account not deployed, have owner sign deployment if not account_response.is_deployed: signature = owner_signs(account_response.typed_data) deploy_tx = POST /v2/gas_sponsorship/prepare { "chain_id": 1, "typed_data": account_response.typed_data, "signature": signature } sender_broadcasts(deploy_tx.transaction) # 3. Request deposit with gas sponsorship deposit_response = POST /v2/earn/deposit { "chain_id": 1, "owner": user_wallet, "sender": platform_wallet, "pool": vault_address, "amount": "1000000000" } # 4. Owner signs the typed data signature = owner_signs(deposit_response.typed_data) # 5. Prepare gas-sponsored transaction tx = POST /v2/gas_sponsorship/prepare { "chain_id": 1, "typed_data": deposit_response.typed_data, "signature": signature } # 6. Sender broadcasts and pays gas sender_broadcasts(tx.transaction) ``` ### Workflow 2: Deposit Without Gas Sponsorship ```python # 1. Get/create account (no sender = owner broadcasts) account_response = POST /v2/earn/account { "chain_id": 1, "owner": user_wallet } # 2. If account not deployed, owner broadcasts deployment if not account_response.is_deployed: owner_broadcasts(account_response.transaction) # 3. Request deposit deposit_response = POST /v2/earn/deposit { "chain_id": 1, "owner": user_wallet, "pool": vault_address, "amount": "1000000000" } # 4. Owner broadcasts deposit transaction owner_broadcasts(deposit_response.transaction) ``` ### Workflow 3: Withdraw with Performance Fee ```python # 1. Get user positions to find pool positions = GET /v2/earn/positions?chain_id=1&owner={user_wallet} # 2. Request withdrawal with 20% performance fee withdraw_response = POST /v2/earn/withdraw { "chain_id": 1, "owner": user_wallet, "sender": platform_wallet, "pool": positions.positions[0].pool, "amount": "max", "fee": { "fee_recipient": platform_fee_address, "fee_denomination": "PERFORMANCE", "fee_value": "2000" # 20% in basis points } } # 3. Complete gas sponsorship flow signature = owner_signs(withdraw_response.typed_data) tx = POST /v2/gas_sponsorship/prepare { ... } sender_broadcasts(tx.transaction) ``` ### Workflow 4: Swap and Deposit Bundle ```python # User has ETH but wants to deposit USDC into vault bundle_response = POST /v2/earn/bundle { "chain_id": 1, "owner": user_wallet, "sender": platform_wallet, "actions": [ { "action_type": "V2_SWAP", "token_in": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", # ETH "token_out": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", # USDC "amount": "1000000000000000000", # 1 ETH "slippage": "0.01" }, { "action_type": "V2_MANAGE", "manage_type": "DEPOSIT", "pool": usdc_vault_address, "amount": "max" # Deposit all USDC from swap } ] } # Complete with gas sponsorship or direct broadcast ``` ### Workflow 5: Cross-Chain Bridge ```python # 1. Initiate bridge from Ethereum to Arbitrum bridge_response = POST /v2/bridge/initiate { "source_chain_id": 1, "destination_chain_id": 42161, "owner": user_wallet, "amount": "1000000000" # 1000 USDC } # 2. User signs and broadcasts on source chain owner_broadcasts(bridge_response.transaction) # 3. Poll for completion while True: status = GET /v2/bridge/status?source_chain_id=1&transaction_hash={tx_hash} if status.status == "completed": break sleep(30) # Funds arrive on destination chain automatically via CCTP ``` --- ## Chain IDs Reference | Network | Chain ID | |---------|----------| | Ethereum Mainnet | 1 | | Arbitrum One | 42161 | | Base | 8453 | --- ## Token Addresses (Common) ### Ethereum (Chain ID: 1) - ETH: `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` - WETH: `0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2` - USDC: `0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48` - USDT: `0xdAC17F958D2ee523a2206206994597C13D831ec7` - DAI: `0x6B175474E89094C44Da98b954EescdeCB5BE3e` ### Arbitrum (Chain ID: 42161) - ETH: `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` - WETH: `0x82aF49447D8a07e3bd95BD0d56f35241523fBab1` - USDC: `0xaf88d065e77c8cC2239327C5EDb3A432268e5831` - USDT: `0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9` ### Base (Chain ID: 8453) - ETH: `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` - WETH: `0x4200000000000000000000000000000000000006` - USDC: `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` --- ## Error Handling ### Common Error Responses ```json { "error": "INSUFFICIENT_BALANCE", "message": "User has insufficient balance for this operation", "details": { "required": "1000000000", "available": "500000000" } } ``` ### Error Codes - `INSUFFICIENT_BALANCE`: User lacks required token balance - `ACCOUNT_NOT_DEPLOYED`: Earn Account needs deployment first - `INVALID_POOL`: Pool address not supported - `SLIPPAGE_EXCEEDED`: Price moved beyond slippage tolerance - `INVALID_CHAIN`: Chain ID not supported - `UNAUTHORIZED`: Invalid or missing API key --- ## Rate Limits - Default: 100 requests per minute per API key - Contact support for higher limits --- ## SDK Examples ### TypeScript SDK ```typescript import { CompassClient } from '@compass-labs/sdk'; const client = new CompassClient({ apiKey: 'YOUR_API_KEY', baseUrl: 'https://api.compasslabs.ai' }); // Get account const account = await client.earn.getAccount({ chainId: 1, owner: '0x...', sender: '0x...' }); // Deposit const deposit = await client.earn.deposit({ chainId: 1, owner: '0x...', sender: '0x...', pool: '0x...', amount: '1000000000' }); // Sign and submit const signature = await signer.signTypedData(deposit.typedData); const tx = await client.gasSponsorship.prepare({ chainId: 1, typedData: deposit.typedData, signature }); await sender.sendTransaction(tx.transaction); ``` ### Python SDK ```python from compass_sdk import CompassClient client = CompassClient( api_key="YOUR_API_KEY", base_url="https://api.compasslabs.ai" ) # Get account account = client.earn.get_account( chain_id=1, owner="0x...", sender="0x..." ) # Deposit deposit = client.earn.deposit( chain_id=1, owner="0x...", sender="0x...", pool="0x...", amount="1000000000" ) # Sign and submit signature = signer.sign_typed_data(deposit.typed_data) tx = client.gas_sponsorship.prepare( chain_id=1, typed_data=deposit.typed_data, signature=signature ) sender.send_transaction(tx.transaction) ``` --- ## Support - **Documentation**: https://docs.compasslabs.ai - **Discord**: https://discord.com/invite/ujetyJJPYr - **Email**: support@compasslabs.ai