# Transfers Guide This guide explains how to move funds with the Customer API. It covers: - Internal book transfers between bank accounts - USDC transfers to cryptocurrency addresses ## Prerequisites - A Meow account with enabled bank accounts - API key permissions: - Book transfers: `accounts:read` and `transfers:book:write` - USDC transfers: `accounts:read`, `accounts:payment-networks`, and `transfers:usdc:write` - A cryptocurrency contact for USDC transfers (see [Cryptocurrency Contact Management Guide](/guides/contacts)) ## Authentication Overview The headers you send depend on the type of API key: - **Entity API keys** scope all requests to a single entity. No `x-entity-id` header is required and you can only move funds between accounts that belong to that entity. - **Global API keys** can access multiple entities, but every request must include an `x-entity-id` header that identifies the source entity for the request. Use `GET /v1/api-keys/accessible-entities` to discover which entities you can access. When booking transfers, the destination account can belong to any other entity you have access to, as long as the accounts remain compatible. > **Tip:** Regardless of the key type, book transfers can only be created between accounts that share the same `bankProductType`. ## Book Transfers Book transfers move funds internally between two accounts you control. The source account is chosen by the path parameter, and the destination is provided in the request body. ### Workflow with Entity API Keys 1. **List accounts** to find eligible source and destination accounts: ```bash curl -X GET "https://api.meow.com/v1/accounts" \ -H "x-api-key: YOUR_ENTITY_API_KEY" ``` Record each account’s `accountId` and `bankProductType`. You must choose a destination account with the same `bankProductType` as the source. 2. **Create the book transfer**: ```bash curl -X POST "https://api.meow.com/v1/accounts/{source_account_id}/book" \ -H "x-api-key: YOUR_ENTITY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount": "250.00", "to_account_id": "63fe8c62-58db-4a48-a42d-625b79a7f3fe", "idempotency_key": "book-transfer-20240318-001", "description": "Move excess cash to interest account" }' ``` Replace `{source_account_id}` and `to_account_id` with the account IDs you gathered. The `idempotency_key` must be unique per transfer attempt. Example response: ```json { "id": "bt_9f0a6c32", "amount": "250.00", "description": "Move excess cash to interest account", "created_time": 1718132817, "transfer_type": "BOOK", "to_account_id": "63fe8c62-58db-4a48-a42d-625b79a7f3fe" } ``` ### Workflow with Global API Keys 1. **Discover accessible entities**: ```bash curl -X GET "https://api.meow.com/v1/api-keys/accessible-entities" \ -H "x-api-key: YOUR_GLOBAL_API_KEY" ``` Use the returned IDs to decide which entity you are operating on. 2. **List accounts for a specific entity**: ```bash curl -X GET "https://api.meow.com/v1/accounts" \ -H "x-api-key: YOUR_GLOBAL_API_KEY" \ -H "x-entity-id: ENTITY_ID" ``` Locate source accounts within the selected entity that share the same `bankProductType` as potential destination accounts. Repeat this call for each entity you have access to so you can identify compatible cross-entity pairs. 3. **Create the book transfer** using the source entity header: ```bash curl -X POST "https://api.meow.com/v1/accounts/{source_account_id}/book" \ -H "x-api-key: YOUR_GLOBAL_API_KEY" \ -H "x-entity-id: ENTITY_ID" \ -H "Content-Type: application/json" \ -d '{ "amount": "500.00", "to_account_id": "9de5402c-493d-419e-afce-87d2c02e8d09", "idempotency_key": "bt-entity-456-20240318", "description": "Sweep to payroll" }' ``` The `x-entity-id` value must match the source account’s entity. As long as you have access, the destination account can belong to a different entity that shares the same `bankProductType`. ### Book Transfer Tips - Pick a fresh `idempotency_key` for each attempt so retries do not create duplicate transfers. - Verify both accounts are active, denominated in the same currency, and share a `bankProductType` even when they belong to different entities. - Transfers fail if the destination account’s `bankProductType` differs from the source. - API-based transfers are blocked when Security Policy Spend controls are enabled for the entity; adjust the policy or rely on the dashboard instead. ## USDC Transfers USDC transfers send funds from a checking account to a cryptocurrency contact. ### Step 1: List Accounts ```bash curl -X GET "https://api.meow.com/v1/accounts" \ -H "x-api-key: YOUR_API_KEY" \ -H "x-entity-id: ENTITY_ID_IF_GLOBAL" ``` Example response: ```json { "accounts": [ { "depositAccount": { "accountId": "acct_123456789", "accountType": "CHECKING", "productName": "Business Checking", "bankProductType": "Grasshopper", "status": "OPEN", "currency": { "currencyCode": "USD" }, "accountNumberDisplay": "1234" } } ] } ``` ### Step 2: Verify USDC Support ```bash curl -X GET "https://api.meow.com/v1/accounts/{account_id}/payment-networks" \ -H "x-api-key: YOUR_API_KEY" \ -H "x-entity-id: ENTITY_ID_IF_GLOBAL" ``` Look for payment networks with `"type": "USDC"` and `"transferOut": true` to confirm the account can originate USDC transfers on the listed blockchains. ### Step 3: Create the USDC Transaction ```bash curl -X POST "https://api.meow.com/v1/accounts/{account_id}/usdc" \ -H "x-api-key: YOUR_API_KEY" \ -H "x-entity-id: ENTITY_ID_IF_GLOBAL" \ -H "Content-Type: application/json" \ -d '{ "amount": "100.00", "static_memo_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "internal_note": "Payment for treats", "emails": ["simba@tiger.com"] }' ``` Example response: ```json { "id": "tx_987654321", "status": "processing", "amount": "100.00", "internal_note": "Payment for treats", "created_time": 1634567890, "transaction_type": "USDC", "destination_address": "0x1234567890abcdef1234567890abcdef12345678", "destination_payment_rail": "ethereum", "destination_address_nickname": "Vendor Wallet" } ``` ### Transaction Status Possible statuses after submission: - `pending` – Awaiting processing - `processing` – In progress - `sent` – Successfully transmitted to the blockchain - `error` – Encountered an issue - `canceled` – Canceled by the user or system - `void` – Reversed before settlement ## Checking Transfer Status After initiating a transfer, use the corresponding GET endpoint with the transfer ID returned from the create call to check its current status. ### ACH Transfers Use the `id` from the create ACH response (e.g. `ach_...`) or the transaction group ID (e.g. `withdrawal_ach_...`) from a transaction listing: ```bash curl -X GET "https://api.meow.com/v1/accounts/{account_id}/achs/{ach_transfer_id}" \ -H "x-api-key: YOUR_API_KEY" \ -H "x-entity-id: ENTITY_ID_IF_GLOBAL" ``` ### Wire Transfers Use the transaction group ID for the wire transfer: ```bash curl -X GET "https://api.meow.com/v1/accounts/{account_id}/wires/{wire_transfer_id}" \ -H "x-api-key: YOUR_API_KEY" \ -H "x-entity-id: ENTITY_ID_IF_GLOBAL" ``` ### USDC Transactions Use the `id` from the create USDC response: ```bash curl -X GET "https://api.meow.com/v1/accounts/{account_id}/transactions/{transaction_id}" \ -H "x-api-key: YOUR_API_KEY" \ -H "x-entity-id: ENTITY_ID_IF_GLOBAL" ``` > **Note:** These GET endpoints return details for both incoming and outgoing transfers. For example, you can retrieve details of an incoming ACH deposit using the same endpoint used to check the status of an outgoing ACH transfer you initiated. ### Best Practices - **Verify recipients**: Confirm cryptocurrency addresses and contact static memos before initiating transfers. - **Use meaningful references**: Populate `description` (book transfers) or `internal_note` (USDC transfers) with reconciliation-friendly values. - **Start small**: Send a nominal amount when onboarding a new recipient. - **Protect secrets**: Keep API keys and transaction data out of unsecured channels. - **Monitor statuses**: Follow up with support if a transfer remains in `error`. ## Support If you need help or have questions: - Email: support@meow.com - Support Portal: https://support.meow.com - API Status: https://status.meow.com