---
name: copperco
description: Use when building integrations with Copper's cryptocurrency custody
  and trading platform. Reach for this skill when creating orders (deposits,
  withdrawals, trades), managing portfolios and wallets, handling approvals and
  signing workflows, setting up webhooks for event notifications, or managing
  lending operations.
metadata:
  mintlify-proj: copperco
  version: "1.0"
---

# Copper API Skill

## Product Summary

Copper is a cryptocurrency custody and trading platform with a REST API for programmatic access. Use the Copper API to create and manage orders (deposits, withdrawals, trades, settlements), fetch balances and transaction history, manage portfolios and wallets, handle multi-signature approvals, integrate with exchanges via ClearLoop, and receive real-time event notifications via webhooks.

**Key files and endpoints:**
- Base URL: `https://api.copper.co/platform` (production) or `https://api.stage.copper.co/platform` (staging)
- Authentication: HMAC-SHA256 signature with API key and secret
- Core entities: Organization → Portfolio (Account) → Wallet → Order
- OpenAPI spec and Postman collection available at https://developer.copper.co/api-reference/getting-started

## When to Use

Reach for this skill when:
- Creating or managing orders: deposits, withdrawals, buy/sell, multi-withdrawals, smart contract calls, staking
- Fetching balances, wallet details, or transaction history
- Approving orders that require co-signatures or master password
- Setting up webhooks to receive real-time notifications (order status, member changes, API key events)
- Managing portfolios, creating wallets, or validating crypto addresses
- Integrating with ClearLoop for exchange delegation and settlements
- Handling lending operations (create loans, approve, accept terms, manage collateral)
- Performing dry-run validation before submitting orders
- Generating reports (balance, orders, staking, lending)

## Quick Reference

### Authentication Headers (Required for Every Request)

| Header | Value |
|--------|-------|
| `Authorization` | `ApiKey {API_KEY}` |
| `X-Signature` | HMAC-SHA256 hex digest of timestamp + method + path + body |
| `X-Timestamp` | Current Unix timestamp in milliseconds |
| `Content-Type` | `application/json` |

### Signature Generation Steps

1. Concatenate: `{timestamp}{METHOD}{/platform/path}{body}`
2. Sign with API secret using HMAC-SHA256
3. Encode result as hexadecimal
4. Include in `X-Signature` header

### Core Entities

| Entity | Description | Key Fields |
|--------|-------------|-----------|
| **Portfolio** | Account/subaccount (custody, trading, trading-vault, external, clearloop) | `portfolioId`, `portfolioType` |
| **Wallet** | Currency balance within a portfolio | `walletId`, `currency`, `balance`, `available`, `reserve` |
| **Order** | Transaction (deposit, withdraw, buy, sell, multi-withdraw, smart-call, etc.) | `orderId`, `orderType`, `status`, `amount`, `baseCurrency` |
| **Address** | Whitelisted crypto address in address book | `cryptoAddressId`, `address`, `currency`, `name` |

### Order Types

`deposit`, `withdraw`, `multi-withdraw`, `buy`, `sell`, `wallet-message`, `cross-chain-deposit`, `cross-chain-withdraw`, `earn-reward`, `claim-shared-reward`, `smart-call`, `multi-smart-call`

### Order Status Lifecycle

**Initial states:** `new` → `waiting-funds` → `reserving` → `reserved` → `queued` → `validating-funds` → `working`

**Approval states:** `waiting-approve` → `co-sign-require` → `approved` → `processing`

**Terminal states:** `executed`, `canceled`, `rejected`, `declined`, `error`, `blocked`, `suspended`, `liquidated`

### Common API Endpoints

| Method | Endpoint | Purpose |
|--------|----------|---------|
| `POST` | `/orders` | Create order |
| `POST` | `/dry-run-orders` | Validate order before submission |
| `GET` | `/orders` | Fetch orders with filters |
| `GET` | `/orders/{orderId}` | Get order details |
| `PATCH` | `/orders/{orderId}` | Approve/co-sign order |
| `PATCH` | `/orders/{orderId}` | Start signing (crypto signature) |
| `GET` | `/wallets` | Fetch balances |
| `GET` | `/portfolios` | List portfolios |
| `POST` | `/crypto-addresses` | Add address to address book |
| `GET` | `/crypto-addresses` | List whitelisted addresses |

### Rate Limits

| Limit Type | Threshold | Lockout |
|-----------|-----------|---------|
| IP-based | 30,000 requests per 5 minutes | Until below threshold |
| User + Org | 1,000 requests per 5 minutes | 5 minutes |
| Auth errors | 30 failed attempts per hour | 15 minutes |
| Business errors | 60 requests per 1 minute | 3 minutes |

## Decision Guidance

### When to Use Dry-Run vs. Direct Order Creation

| Scenario | Use Dry-Run | Use Direct Create |
|----------|------------|-------------------|
| Validating order before submission | ✓ | |
| Checking estimated fees and balance impact | ✓ | |
| Testing complex multi-step orders | ✓ | |
| Submitting a known-good order | | ✓ |
| Production order after validation | | ✓ |

### When to Use Service Account vs. User Account API Key

| Use Case | Service Account | User Account |
|----------|-----------------|--------------|
| Automated/scheduled operations | ✓ | |
| Shared team access | ✓ | |
| Personal/one-off integrations | | ✓ |
| Reduced risk of key deactivation | ✓ | |
| Operational continuity | ✓ | |

### Order Approval Workflow: When to Use Each Endpoint

| Scenario | Endpoint | Notes |
|----------|----------|-------|
| Order requires co-signature approval | `PATCH /orders/{orderId}` (co-sign) | Use when `status` is `co-sign-require` |
| Order requires master password | `PATCH /orders/{orderId}` (provide password) | Include SHA-256 hash of withdrawal password |
| Order needs crypto signing | `PATCH /orders/{orderId}` (start signing) | Initiates signing flow; status becomes `part-signed-tx-added` or `full-signed-tx-added` |
| Order is ready to execute | Order auto-processes | Once all approvals and signatures complete |

## Workflow

### Typical Order Creation and Execution Flow

1. **Identify the portfolio and wallet**
   - Call `GET /portfolios` to list available portfolios
   - Call `GET /wallets?portfolioId={id}` to check available balance
   - Verify sufficient funds for the order amount + estimated fees

2. **Validate the order (optional but recommended)**
   - Call `POST /dry-run-orders` with order parameters
   - Review `extra.estimatedFees` to confirm fee structure
   - Check for warnings or validation errors in response

3. **Create the order**
   - Call `POST /orders` with required fields: `portfolioId`, `orderType`, `baseCurrency`, `amount`, `externalOrderId`
   - For withdrawals: include `toCryptoAddressId` or `toAddress`
   - For settlements: include `quoteCurrency`, `toCounterpartyId`, `limitType: "otc"`
   - Store returned `orderId` for tracking

4. **Handle approval workflow (if required)**
   - Poll `GET /orders/{orderId}` to check status
   - If status is `co-sign-require`: call `PATCH /orders/{orderId}` to approve
   - If status is `master-password-required`: call `PATCH /orders/{orderId}` with `masterPassword` (SHA-256 hash)
   - If status is `waiting-approve`: wait for another user to approve

5. **Handle signing (if required)**
   - If status is `part-signed-tx-added` or `full-signed-tx-added`: transaction is ready
   - For Copper Unlimited Online: call `PATCH /orders/{orderId}` (start signing) to initiate signing flow
   - Monitor status until `executed` or terminal state

6. **Verify completion**
   - Poll until status reaches terminal state: `executed`, `canceled`, `rejected`, `error`, etc.
   - Check `extra.transactionId` for blockchain confirmation
   - Use webhooks for real-time notifications instead of polling

### Setting Up Webhooks for Event Notifications

1. **Create webhook subscription**
   - Navigate to Copper Platform UI → Organization Settings → Webhooks
   - Specify webhook URL (must be publicly accessible, respond with 200 OK)
   - Select events to subscribe to (e.g., `order-created`, `order-completed`, `deposit-created`)
   - Choose signature validation: HMAC-SHA256 or ECDSA
   - Optionally filter by portfolio

2. **Validate incoming webhook signatures**
   - Extract `X-Signature` and `X-Timestamp` headers
   - Concatenate: `{timestamp}{eventId}{full_request_body}`
   - Sign with API secret using HMAC-SHA256
   - Compare generated signature with `X-Signature` header
   - Validate IP address against Copper's webhook IPs (63.33.117.167, 99.80.177.29, 52.215.155.205)

3. **Handle webhook events**
   - Parse event type from `event` field (e.g., `order-created`, `order-completed`)
   - Extract payload data
   - Process asynchronously; respond with 200 OK immediately
   - Implement idempotency using `eventId` to handle retries

## Common Gotchas

- **Numeric precision:** All numeric values are returned as strings to prevent floating-point errors. Parse as strings or use decimal libraries.
- **Timestamps in milliseconds:** All timestamps are Unix epoch in milliseconds, not seconds. Multiply by 1000 if converting from seconds.
- **API key expiration:** Keys are disabled after 6 months of inactivity. Rotate keys periodically and monitor usage.
- **Signature generation errors:** Ensure timestamp is current (within a few seconds), method is uppercase, path includes `/platform` prefix, and body is exact JSON (no extra whitespace).
- **Order status transitions:** Not all status transitions are valid. Attempting to approve an already-executed order will fail. Always check current status before taking action.
- **Insufficient balance:** Orders fail if available balance is less than amount + fees. Use dry-run to estimate fees before creating orders.
- **Address validation:** Always validate crypto addresses before creating withdrawal orders. Use `POST /blockchain/validate-address` to check format.
- **Master password hashing:** Master password must be SHA-256 hashed before sending. Never send plaintext passwords.
- **External order ID uniqueness:** `externalOrderId` must be unique per portfolio. Reusing IDs will cause conflicts.
- **Rate limit lockout:** Once rate limit is exceeded, requests are blocked for the lockout period. Implement exponential backoff and request queuing.
- **Webhook IP validation:** Copper's webhook IPs can change. Don't hardcode them; validate against current list or use signature validation as primary defense.
- **Portfolio type restrictions:** Some operations only work with specific portfolio types (e.g., ClearLoop operations require `clearloop` portfolio type).

## Verification Checklist

Before submitting work with the Copper API:

- [ ] API key and secret are stored securely (environment variables, secrets manager, not in code)
- [ ] Signature generation is correct: timestamp + method + path + body, HMAC-SHA256, hex-encoded
- [ ] All required headers are included: `Authorization`, `X-Signature`, `X-Timestamp`, `Content-Type`
- [ ] Numeric values are handled as strings (no floating-point arithmetic)
- [ ] Timestamps are in milliseconds (not seconds)
- [ ] Order `externalOrderId` is unique per portfolio
- [ ] Dry-run validation passed before creating production orders
- [ ] Sufficient balance exists (including estimated fees) before order creation
- [ ] Crypto addresses are validated before withdrawal orders
- [ ] Master passwords are SHA-256 hashed before sending
- [ ] Webhook URL is publicly accessible and responds with 200 OK
- [ ] Webhook signatures are validated (X-Signature header)
- [ ] Error responses are handled (check `error` and `message` fields)
- [ ] Rate limits are respected (implement backoff and queuing)
- [ ] Service accounts are used for automated integrations (not personal API keys)
- [ ] API key permissions are scoped to minimum required (Trader, Withdrawal Operator, Approver, Loan Manager)

## Resources

**Comprehensive navigation:** https://developer.copper.co/llms.txt

**Critical documentation pages:**
- [API Getting Started](https://developer.copper.co/api-reference/getting-started) — Base URLs, date/time formats, response codes
- [Authentication](https://developer.copper.co/api-reference/authentication) — Signature generation with code examples (Bash, Python, Java, Go, Scala)
- [Create Order](https://developer.copper.co/api-reference/orders/create-order) — Full order creation reference with all parameters and response fields

---

> For additional documentation and navigation, see: https://developer.copper.co/llms.txt