[{"data":1,"prerenderedAt":172},["ShallowReactive",2],{"content-\u002Fprompts\u002Fintegrate-utila":3,"prompts-category-integrations":106},{"id":4,"title":5,"author":6,"body":7,"categories":6,"category":90,"categoryType":6,"date":91,"description":92,"extension":93,"faq":6,"howto":6,"isBlog":94,"isChangelog":94,"meta":95,"navigation":96,"path":97,"pillar":94,"products":98,"rawbody":102,"seo":103,"stem":104,"thumbnail":6,"updated":6,"__hash__":105},"content\u002Fprompts\u002Fintegrate-utila.md","Integrate Utila with BlindPay",null,{"type":8,"value":9,"toc":84},"minimark",[10,14,19,30,34,47,51],[11,12,13],"p",{},"Paste this prompt into your coding agent when funds live in Utila-managed MPC wallets and those wallets need to register as the sender and authorize BlindPay payouts on-chain.",[15,16,18],"h2",{"id":17},"prompt","Prompt",[20,21,27],"pre",{"className":22,"code":24,"language":25,"meta":26},[23],"language-text","You are integrating BlindPay EVM payouts funded from Utila MPC vault wallets into my application. Utila holds the private key shares; my backend calls Utila's REST API to sign the BlindPay registration challenge and the ERC-20 approve, then calls BlindPay to execute the payout.\n\nBefore writing code, read these sources and follow them over any prior knowledge:\n- https:\u002F\u002Fblindpay.com\u002Fdocs\u002Fllms.txt (read the blockchain wallets page and the EVM payout guide)\n- The OpenAPI spec: curl https:\u002F\u002Fapi.blindpay.com\u002Fdoc\n- https:\u002F\u002Fdocs.utila.io\u002Freference\u002Fapi-overview\n- https:\u002F\u002Fdocs.utila.io\u002Freference\u002Fauthentication\n- https:\u002F\u002Fdocs.utila.io\u002Freference\u002Fservice-accounts\n- https:\u002F\u002Fdocs.utila.io\u002Freference\u002Ftransactions_initiatetransaction\n- https:\u002F\u002Fdocs.utila.io\u002Freference\u002Fblockchains_listnetworks\n\nBuild the flow:\n1. Authenticate to Utila as a service account: build a locally-signed RS256 JWT (sub = service account email, aud = \"https:\u002F\u002Fapi.utila.io\u002F\", short expiry) from the uploaded RSA key pair and send it as a Bearer token on every Utila call. Confirm the exact claim set and endpoint against the live auth docs before hardcoding it.\n2. Register the wallet: call GET \u002Fv1\u002Finstances\u002F{instance_id}\u002Fcustomers\u002F{customer_id}\u002Fblockchain-wallets\u002Fsign-message to get the challenge, sign it by calling Utila's POST \u002Fv2\u002Fvaults\u002F{vault_id}\u002Ftransactions:initiate with details.evmPersonalSign (fromAddress, message), poll GetTransaction (or handle the equivalent webhook) until the signing transaction reaches its completed state, extract the signature, and POST it to \u002Fv1\u002Finstances\u002F{instance_id}\u002Fcustomers\u002F{customer_id}\u002Fblockchain-wallets to persist the returned bw_ ID against the customer record.\n3. Request a quote: call POST \u002Fv1\u002Finstances\u002F{instance_id}\u002Fquotes with bank_account_id, network, and token, and read back the contract object (address, abi, functionName \"approve\", blindpayContractAddress, amount, network, expires_at) without hardcoding any contract address.\n4. Send the approve: ABI-encode the \"approve\" call from the quote's contract.abi and amount, then call Utila's POST \u002Fv2\u002Fvaults\u002F{vault_id}\u002Ftransactions:initiate with details.evmTransaction (network resolved via ListNetworks for the quote's chain, fromAddress, toAddress = contract.blindpayContractAddress, value \"0\", data = the encoded call, publish true). Poll GetTransaction (or handle the equivalent webhook) until the transaction reaches CONFIRMED before moving on, and surface Utila's policy-engine states (pending approval, co-signing) as visible statuses in this step since they add latency on top of the quote's expiry window.\n5. Execute the payout: call POST \u002Fv1\u002Finstances\u002F{instance_id}\u002Fpayouts\u002Fevm with the quote_id and sender_wallet_address before the quote's expires_at. If the quote expires while the approve is still confirming, request a fresh quote for the same amount and skip re-sending the approve when the existing on-chain allowance already covers it.\n6. Verify the webhook secret and handle payout.new, payout.update, and payout.complete with Svix signature verification (svix-id, svix-timestamp, svix-signature against whsec_) on the raw request body, updating payout state in the database on each event.\n7. Run the full flow end to end on a development instance with USDB on a testnet, then repeat it once each with the $666.00 (66600 minor units) sentinel to confirm the failed webhook path and $777.00 (77700 minor units) to confirm the refunded webhook path.\n\nConstraints:\n- Keep BlindPay and Utila API keys server-side; never expose either to the client.\n- Represent every amount as an integer in minor units end to end; never use floating point for money math.\n- Never hardcode the BlindPay contract address, ABI, or Utila network resource name; read them from the quote response and ListNetworks respectively.\n\nDeliverables: the Utila service-account auth helper, the wallet registration flow with the bw_ ID persisted, the quote-approve-execute orchestration with async Utila confirmation and the expiry race handled, Svix-verified webhook handlers, and a passing end-to-end test against a development instance covering the success and both sentinel-amount paths.\n","text","",[28,29,24],"code",{"__ignoreMap":26},[15,31,33],{"id":32},"how-to-use","How to use",[35,36,37,41,44],"ol",{},[38,39,40],"li",{},"Give the agent your Utila service account's key pair location and vault ID, and your BlindPay instance ID.",[38,42,43],{},"Confirm the Base Sepolia (or your target testnet) network resource name against Utila's ListNetworks before the agent wires the approve call.",[38,45,46],{},"Watch the quote-expiry-vs-MPC-approval race in testing; Utila's co-signing delay is what usually pushes past the 5-minute window.",[15,48,50],{"id":49},"related-docs","Related docs",[52,53,54,63,70,77],"ul",{},[38,55,56],{},[57,58,62],"a",{"href":59,"rel":60},"https:\u002F\u002Fblindpay.com\u002Fdocs\u002Fblockchain-wallets",[61],"nofollow","Blockchain wallets",[38,64,65],{},[57,66,69],{"href":67,"rel":68},"https:\u002F\u002Fblindpay.com\u002Fdocs\u002Fpayout-evm",[61],"EVM payouts",[38,71,72],{},[57,73,76],{"href":74,"rel":75},"https:\u002F\u002Fdocs.utila.io\u002Freference\u002Fapi-overview",[61],"Utila API overview",[38,78,79],{},[57,80,83],{"href":81,"rel":82},"https:\u002F\u002Fdocs.utila.io\u002Freference\u002Ftransactions_initiatetransaction",[61],"Utila InitiateTransaction",{"title":26,"searchDepth":85,"depth":85,"links":86},2,[87,88,89],{"id":17,"depth":85,"text":18},{"id":32,"depth":85,"text":33},{"id":49,"depth":85,"text":50},"integrations","2026-08-26","Fund BlindPay payouts from Utila MPC vaults: sign the wallet-registration challenge and the ERC-20 approve through Utila's service-account API, with async transaction confirmation handled.","md",false,{},true,"\u002Fprompts\u002Fintegrate-utila",[99,100,101],"payouts","quotes","webhooks","---\ntitle: \"Integrate Utila with BlindPay\"\ndescription: \"Fund BlindPay payouts from Utila MPC vaults: sign the wallet-registration challenge and the ERC-20 approve through Utila's service-account API, with async transaction confirmation handled.\"\ndate: \"2026-08-26\"\ncategory: \"integrations\"\nproducts: [\"payouts\", \"quotes\", \"webhooks\"]\n---\n\nPaste this prompt into your coding agent when funds live in Utila-managed MPC wallets and those wallets need to register as the sender and authorize BlindPay payouts on-chain.\n\n## Prompt\n\n```text\nYou are integrating BlindPay EVM payouts funded from Utila MPC vault wallets into my application. Utila holds the private key shares; my backend calls Utila's REST API to sign the BlindPay registration challenge and the ERC-20 approve, then calls BlindPay to execute the payout.\n\nBefore writing code, read these sources and follow them over any prior knowledge:\n- https:\u002F\u002Fblindpay.com\u002Fdocs\u002Fllms.txt (read the blockchain wallets page and the EVM payout guide)\n- The OpenAPI spec: curl https:\u002F\u002Fapi.blindpay.com\u002Fdoc\n- https:\u002F\u002Fdocs.utila.io\u002Freference\u002Fapi-overview\n- https:\u002F\u002Fdocs.utila.io\u002Freference\u002Fauthentication\n- https:\u002F\u002Fdocs.utila.io\u002Freference\u002Fservice-accounts\n- https:\u002F\u002Fdocs.utila.io\u002Freference\u002Ftransactions_initiatetransaction\n- https:\u002F\u002Fdocs.utila.io\u002Freference\u002Fblockchains_listnetworks\n\nBuild the flow:\n1. Authenticate to Utila as a service account: build a locally-signed RS256 JWT (sub = service account email, aud = \"https:\u002F\u002Fapi.utila.io\u002F\", short expiry) from the uploaded RSA key pair and send it as a Bearer token on every Utila call. Confirm the exact claim set and endpoint against the live auth docs before hardcoding it.\n2. Register the wallet: call GET \u002Fv1\u002Finstances\u002F{instance_id}\u002Fcustomers\u002F{customer_id}\u002Fblockchain-wallets\u002Fsign-message to get the challenge, sign it by calling Utila's POST \u002Fv2\u002Fvaults\u002F{vault_id}\u002Ftransactions:initiate with details.evmPersonalSign (fromAddress, message), poll GetTransaction (or handle the equivalent webhook) until the signing transaction reaches its completed state, extract the signature, and POST it to \u002Fv1\u002Finstances\u002F{instance_id}\u002Fcustomers\u002F{customer_id}\u002Fblockchain-wallets to persist the returned bw_ ID against the customer record.\n3. Request a quote: call POST \u002Fv1\u002Finstances\u002F{instance_id}\u002Fquotes with bank_account_id, network, and token, and read back the contract object (address, abi, functionName \"approve\", blindpayContractAddress, amount, network, expires_at) without hardcoding any contract address.\n4. Send the approve: ABI-encode the \"approve\" call from the quote's contract.abi and amount, then call Utila's POST \u002Fv2\u002Fvaults\u002F{vault_id}\u002Ftransactions:initiate with details.evmTransaction (network resolved via ListNetworks for the quote's chain, fromAddress, toAddress = contract.blindpayContractAddress, value \"0\", data = the encoded call, publish true). Poll GetTransaction (or handle the equivalent webhook) until the transaction reaches CONFIRMED before moving on, and surface Utila's policy-engine states (pending approval, co-signing) as visible statuses in this step since they add latency on top of the quote's expiry window.\n5. Execute the payout: call POST \u002Fv1\u002Finstances\u002F{instance_id}\u002Fpayouts\u002Fevm with the quote_id and sender_wallet_address before the quote's expires_at. If the quote expires while the approve is still confirming, request a fresh quote for the same amount and skip re-sending the approve when the existing on-chain allowance already covers it.\n6. Verify the webhook secret and handle payout.new, payout.update, and payout.complete with Svix signature verification (svix-id, svix-timestamp, svix-signature against whsec_) on the raw request body, updating payout state in the database on each event.\n7. Run the full flow end to end on a development instance with USDB on a testnet, then repeat it once each with the $666.00 (66600 minor units) sentinel to confirm the failed webhook path and $777.00 (77700 minor units) to confirm the refunded webhook path.\n\nConstraints:\n- Keep BlindPay and Utila API keys server-side; never expose either to the client.\n- Represent every amount as an integer in minor units end to end; never use floating point for money math.\n- Never hardcode the BlindPay contract address, ABI, or Utila network resource name; read them from the quote response and ListNetworks respectively.\n\nDeliverables: the Utila service-account auth helper, the wallet registration flow with the bw_ ID persisted, the quote-approve-execute orchestration with async Utila confirmation and the expiry race handled, Svix-verified webhook handlers, and a passing end-to-end test against a development instance covering the success and both sentinel-amount paths.\n```\n\n## How to use\n\n1. Give the agent your Utila service account's key pair location and vault ID, and your BlindPay instance ID.\n2. Confirm the Base Sepolia (or your target testnet) network resource name against Utila's ListNetworks before the agent wires the approve call.\n3. Watch the quote-expiry-vs-MPC-approval race in testing; Utila's co-signing delay is what usually pushes past the 5-minute window.\n\n## Related docs\n\n- [Blockchain wallets](https:\u002F\u002Fblindpay.com\u002Fdocs\u002Fblockchain-wallets)\n- [EVM payouts](https:\u002F\u002Fblindpay.com\u002Fdocs\u002Fpayout-evm)\n- [Utila API overview](https:\u002F\u002Fdocs.utila.io\u002Freference\u002Fapi-overview)\n- [Utila InitiateTransaction](https:\u002F\u002Fdocs.utila.io\u002Freference\u002Ftransactions_initiatetransaction)\n",{"title":5,"description":92},"prompts\u002Fintegrate-utila","iNZyfaEpt9OQAct_QUBgkoW_iny3AWoWPz43YGOBy_Y",[107,111,115,119,123,127,131,135,139,140,144,148,152,156,160,164,168],{"path":108,"title":109,"description":110},"\u002Fprompts\u002Fbuild-contractor-payouts","Build a global contractor payout product","Compose onboarding, bank accounts, quotes, payouts, and reconciliation into a complete pay-your-contractors feature across Pix, SPEI, SEPA, and ACH.",{"path":112,"title":113,"description":114},"\u002Fprompts\u002Fconnect-ai-agent-mcp","Connect an AI agent with the MCP server","Wire Claude, Cursor, or any MCP-compatible host to the BlindPay API with the official MCP server and agent skills, with guardrails for money movement.",{"path":116,"title":117,"description":118},"\u002Fprompts\u002Fintegrate-external-wallet-payouts","Fund payouts from external wallets","Let customers pay out from their own EVM, Solana, or Stellar wallets: signed-message registration plus the on-chain authorization step per chain.",{"path":120,"title":121,"description":122},"\u002Fprompts\u002Fintegrate-circle-wallets","Integrate Circle wallets with BlindPay","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.",{"path":124,"title":125,"description":126},"\u002Fprompts\u002Fintegrate-dfns","Integrate Dfns with BlindPay","Fund BlindPay stablecoin payouts from Dfns MPC wallets: sign the registration challenge and the ERC-20 approve through Dfns's User Action Signature flow.",{"path":128,"title":129,"description":130},"\u002Fprompts\u002Fintegrate-fireblocks","Integrate Fireblocks with BlindPay","Fund BlindPay stablecoin payouts from Fireblocks vault accounts: MPC-signed wallet registration and the ERC-20 approve through Fireblocks' transactions API.",{"path":132,"title":133,"description":134},"\u002Fprompts\u002Fintegrate-privy","Integrate Privy with BlindPay","Fund BlindPay stablecoin payouts from Privy Server Wallets: sign the registration challenge and the ERC-20 approve through Privy's wallet RPC endpoint.",{"path":136,"title":137,"description":138},"\u002Fprompts\u002Fintegrate-virtual-accounts","Integrate US virtual accounts","Give each customer a named US bank account with ACH, RTP, wire, and SWIFT details that settles automatically to USDC or USDT in their wallet.",{"path":97,"title":5,"description":92},{"path":141,"title":142,"description":143},"\u002Fprompts\u002Fintegrate-customer-onboarding","Integrate customer onboarding with KYC and KYB","Build the full onboarding pipeline: terms of service, individual and business customers, document uploads, RFI handling, and status webhooks.",{"path":145,"title":146,"description":147},"\u002Fprompts\u002Fintegrate-offramp-wallets","Integrate offramp wallets for auto-conversion","Give each bank account a dedicated crypto deposit address: stablecoins sent to it convert and pay out to the linked bank account automatically.",{"path":149,"title":150,"description":151},"\u002Fprompts\u002Fintegrate-payins","Integrate payins from bank transfers to stablecoins","Accept Pix, ACH, wire, SPEI, and other local bank transfers and settle them as USDC or USDT in a wallet, with quotes, payment instructions, and webhooks.",{"path":153,"title":154,"description":155},"\u002Fprompts\u002Fintegrate-quotes-fx","Integrate quotes and FX handling","Handle payin, payout, and transfer quotes correctly: expiry windows, currency_type conventions, fees, and displaying rates to users.",{"path":157,"title":158,"description":159},"\u002Fprompts\u002Fintegrate-stablecoin-payouts","Integrate stablecoin payouts end to end","Build a complete stablecoin to fiat payout flow: customer onboarding, bank accounts, quotes, and payout execution over Pix, ACH, SPEI, SEPA, and more.",{"path":161,"title":162,"description":163},"\u002Fprompts\u002Fintegrate-wallet-transfers","Integrate wallet transfers and cross-chain USDC","Move stablecoins from managed wallets to any address with transfer quotes, including cross-chain USDC over Circle CCTP v2.",{"path":165,"title":166,"description":167},"\u002Fprompts\u002Fintegrate-webhooks","Integrate webhooks end to end","Register endpoints, verify Svix signatures correctly, deduplicate retries, and drive payment state from the full BlindPay event catalog.",{"path":169,"title":170,"description":171},"\u002Fprompts\u002Fintegrate-payables","Pay boletos and Brazilian bills with payables","Register boletos, arrecadacao slips, and PIX codes as payables and settle them from stablecoins through the quote-and-execute flow.",1787868849067]