---
title: "Integrate Circle wallets with BlindPay"
description: "Fund BlindPay payouts from Circle developer-controlled wallets: sign the registration challenge and the ERC-20 approve through Circle's API instead of a browser wallet."
date: "2026-08-26"
category: "integrations"
products: ["payouts", "quotes", "webhooks"]
---

Paste this prompt into your coding agent when your funds live in Circle wallets and you want those wallets to fund BlindPay payouts.

## Prompt

```text
You are integrating BlindPay EVM payouts funded by Circle developer-controlled wallets into my application. My backend already holds funds in Circle wallets and must register one of those wallets with BlindPay, then use Circle's API to sign everything BlindPay's payout flow requires. No browser extension or end-user signing is involved.

Before writing code, read these sources and follow them over any prior knowledge:
- https://blindpay.com/docs/llms.txt (read the blockchain wallets page and the EVM payout guide)
- The OpenAPI spec: curl https://api.blindpay.com/doc
- https://developers.circle.com/api-reference/wallets/developer-controlled-wallets/sign-message
- https://developers.circle.com/api-reference/wallets/developer-controlled-wallets/create-developer-transaction-contract-execution
- https://developers.circle.com/wallets/account-types
- https://developers.circle.com/wallets/webhook-notifications

Build the flow:
1. Confirm which Circle wallet (walletId) will fund payouts, verify it is a developer-controlled wallet and not user-controlled (user-controlled wallets require a client-side PIN session and cannot sign headlessly from this server), and persist that walletId as the configured funding wallet for this integration.
2. Register the wallet with BlindPay: call GET /v1/instances/{instance_id}/customers/{customer_id}/blockchain-wallets/sign-message to get the challenge, sign it by calling Circle's POST /v1/w3s/developer/sign/message with walletId, message (set encodedByHex if the challenge is hex), and a freshly generated entitySecretCiphertext, then POST the returned signature to /v1/instances/{instance_id}/customers/{customer_id}/blockchain-wallets and persist the resulting bw_ ID against the wallet record.
3. Request a payout quote via POST /v1/instances/{instance_id}/quotes with bank_account_id, network, and token, and store the returned quote_id, expires_at, and the contract object (address, abi, functionName, blindpayContractAddress, amount, network) exactly as returned, never hardcoded.
4. Submit the ERC-20 approve through Circle: call POST /v1/w3s/developer/transactions/contractExecution with a fresh idempotencyKey, contractAddress set to the quote's blindpayContractAddress, walletId, entitySecretCiphertext, and either abiFunctionSignature "approve(address,uint256)" with abiParameters built from the quote's abi/amount, or callData if you derive it directly from the quote's abi. Confirm the exact status-polling endpoint in Circle's developer-controlled wallets docs, then track the returned transaction id to a terminal state (COMPLETE or FAILED) by polling that endpoint or handling Circle's webhook notification, and persist the terminal status, including FAILED, DENIED, or CANCELLED outcomes, on the payout record.
5. Once the approve transaction reaches COMPLETE, call POST /v1/instances/{instance_id}/payouts/evm with quote_id and sender_wallet_address before the quote's expires_at. If expires_at passes while the approve transaction is still pending confirmation (an MPC signing and on-chain confirmation delay makes this the likely failure path), re-quote via step 3, check whether the already-approved allowance still covers the new quote's amount, and only resubmit a new approve transaction when it does not.
6. Persist BlindPay's payout.new, payout.update, and payout.complete webhooks (verify svix-id/svix-timestamp/svix-signature against the whsec_ secret over the raw body) into payout status, and store Circle's contractExecution webhook status alongside it so approve-transaction state and payout state are both queryable from one place.
7. Run the full flow end to end on a BlindPay development instance with a Circle testnet wallet on base_sepolia and USDB, including one payout at $666.00 (66600 minor units, forces failed) and one at $777.00 (77700 minor units, forces refunded), and confirm both sentinel outcomes land correctly in your webhook-driven status.

Constraints:
- Keep the BlindPay API key and the Circle API key plus entity secret server-side only; never expose either to a client.
- Represent every amount as an integer in minor units; never use floating point for money math.
- Generate a new entitySecretCiphertext per Circle API call; never reuse one across requests.

Deliverables: wallet registration flow that signs the BlindPay challenge through Circle's sign-message endpoint and persists the bw_ ID, a quote-approve-execute orchestration module that drives Circle's contractExecution call to terminal state before calling BlindPay's execute endpoint, the quote-expiry re-quote-and-reuse-allowance path handled explicitly, and webhook handlers for both BlindPay and Circle wired into one payout status view, tested on a development instance with both sentinel amounts.
```

## How to use

1. Confirm the funding wallet is a Circle developer-controlled wallet before running the prompt; user-controlled wallets cannot sign headlessly.
2. Give the agent your Circle entity secret setup (how entitySecretCiphertext gets generated in your stack) so it wires that into every Circle call, not just the two spelled out here.
3. Run the sentinel-amount tests on a development instance first, and deliberately stall the approve confirmation to verify the quote-expiry re-quote path actually reuses the allowance instead of blindly resubmitting.

## Related docs

- [Blockchain wallets](https://blindpay.com/docs/blockchain-wallets)
- [EVM payouts](https://blindpay.com/docs/payout-evm)
- [Circle developer-controlled wallets sign message](https://developers.circle.com/api-reference/wallets/developer-controlled-wallets/sign-message)
- [Circle developer-controlled wallets contract execution](https://developers.circle.com/api-reference/wallets/developer-controlled-wallets/create-developer-transaction-contract-execution)
