CPN

How-to: Migrate from Transactions V1 to V2

Transactions V2 allows for a more straightforward integration with CPN compared to Transactions V1. It also provides more powerful onchain settlement primitives, such as auto-acceleration and gas fees that are fixed at quote time. If you have previously integrated with CPN using the Transactions V1 API, you can migrate to Transactions V2 without changes to your wallet infrastructure.

Compared to Transactions V1, Transactions V2 has the following differences:

  • Before initiating a transaction, the sender wallet must grant the Permit2 contract a USDC allowance.
  • When creating the CPN quote, you must set the transactionVersion parameter to VERSION_2.
  • Gas fees are not charged in native tokens, but in USDC. They are determined at quote creation instead of transaction creation in the quote fees field. The gas fee is collected by Circle's payment settlement smart contract during onchain transaction processing.
  • There are separate API endpoints for creating and submitting transactions.
  • When signing the transaction, you no longer need to compose and sign the raw EVM transaction; you only need to sign the EIP-712 typed data provided to you in the messageToBeSigned field and submit the signature.
  • CPN handles the auto-acceleration of the transaction. You no longer need to monitor transaction broadcast status or submit acceleration transactions.

This guide provides information on how to migrate your existing integration from Transactions V1 to V2.

Before you begin, ensure that you have:

  • Obtained an API key for CPN from Circle
  • USDC in your sender wallet
  • cURL installed on your development machine
  • Granted a USDC allowance to the Permit2 contract. See How-to: Grant USDC Allowance to Permit2 for more information.

Use the following steps to create an onchain transaction using Transactions V2.

Use the create a quote endpoint to create a quote with the transactionVersion parameter set to VERSION_2.

Shell
curl --request POST \
  --url https://api.circle.com/v1/cpn/quotes \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer ${YOUR_API_KEY}' \
  --header 'Content-Type: application/json' \
  --data '
{
    "paymentMethodType": "SPEI",
    "senderCountry": "US",
    "destinationCountry": "MX",
    "sourceAmount": {
        "currency": "USDC"
    },
    "destinationAmount": {
        "amount": "200",
        "currency": "MXN"
    },
    "blockchain": "ETH-SEPOLIA",
    "senderType": "INDIVIDUAL",
    "recipientType": "INDIVIDUAL",
    "transactionVersion": "VERSION_2"
}
'

Response

JSON
{
  "data": [
    {
      "id": "2792f4a6-f1bd-4435-b681-1da309122159",
      "paymentMethodType": "SPEI",
      "blockchain": "ETH-SEPOLIA",
      "senderCountry": "US",
      "destinationCountry": "MX",
      "createDate": "2025-09-24T00:01:13.532073875Z",
      "quoteExpireDate": "2025-09-24T00:01:42.502094Z",
      "cryptoFundsSettlementExpireDate": "2025-09-24T01:01:12.502097Z",
      "sourceAmount": {
        "amount": "15.000000",
        "currency": "USDC"
      },
      "destinationAmount": {
        "amount": "252.91",
        "currency": "MXN"
      },
      "fiatSettlementTime": {
        "min": "0",
        "max": "5",
        "unit": "MINUTES"
      },
      "exchangeRate": {
        "rate": "16.860667",
        "pair": "USDC/MXN"
      },
      "fees": {
        "totalAmount": {
          "amount": "1.568971",
          "currency": "USDC"
        },
        "breakdown": [
          {
            "type": "TAX_FEE",
            "amount": {
              "amount": "0.234663",
              "currency": "USDC"
            }
          },
          {
            "type": "BFI_TRANSACTION_FEE",
            "amount": {
              "amount": "0.138037",
              "currency": "USDC"
            }
          },
          {
            "type": "CIRCLE_SERVICE_FEE",
            "amount": {
              "amount": "0.000000",
              "currency": "USDC"
            }
          },
          {
            "type": "BLOCKCHAIN_GAS_FEE",
            "amount": {
              "amount": "1.196271",
              "currency": "USDC"
            }
          }
        ]
      },
      "senderType": "INDIVIDUAL",
      "recipientType": "INDIVIDUAL",
      "certificate": {
        // certificate object
      },
      "quoteOptions": {
        "isFirstParty": false
      },
      "transactionVersion": "VERSION_2"
    }
  ]
}

Initiate the transaction using the create a transaction V2 endpoint.

Shell
curl --request POST \
  --url https://api.circle.com/v2/cpn/payments/:paymentId/transactions \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer ${YOUR_API_KEY}' \
  --header 'Content-Type: application/json' \
  --data '
{
  "idempotencyKey" : "${RANDOM_UUID}"
}
'

Response

JSON
{
  "data": {
    "id": "dbc27d23-cd4f-447e-855e-349cb2853d23",
    "status": "CREATED",
    "paymentId": "49d4231e-6c4f-319e-946d-ed8c8bab5abc",
    "expireDate": "2025-09-08T20:02:06.651391Z",
    "blockchain": "ETH-SEPOLIA",
    "senderAddress": "0x1234567890123456789012345678901234567890",
    "destinationAddress": "0x0000000000000000000000000000000000000001",
    "amount": {
      "amount": "15.000000",
      "currency": "USDC"
    },
    "messageType": "PAYMENT_SETTLEMENT_CONTRACT_V1_0_PAYMENT_INTENT",
    "messageToBeSigned": {
      "domain": {
        "name": "Permit2",
        "chainId": "11155111",
        "verifyingContract": "0x000000000022D473030F116dDEE9F6B43aC78BA3"
      },
      "message": {
        "permitted": {
          "token": "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
          "amount": "14174474"
        },
        "spender": "0xe2B17D0C1736dc7C462ABc4233C91BDb9F27DD1d",
        "nonce": "25668617285137697861288274946631174355105919960416755114569514179393151588120",
        "deadline": "1757362866",
        "witness": {
          "from": "0x1234567890123456789012345678901234567890",
          "to": "0x0000000000000000000000000000000000000001",
          "value": 14174474,
          "validAfter": "1757358106",
          "validBefore": "1757361726",
          "nonce": "0x38bfec2b230187932870d575132e8ae1f83b34c10e3bf6d64c377f0c13245718",
          "beneficiary": "0x4f1c3a0359A7fAd8Fa8E9E872F7C06dAd97C91Fd",
          "maxFee": "0",
          "attester": "0x768919ef04853b5fd444ccff48cea154768a0291",
          "requirePayeeSign": false
        }
      },
      "primaryType": "PermitWitnessTransferFrom",
      "types": {
        "EIP712Domain": [
          {
            "name": "name",
            "type": "string"
          },
          {
            "name": "chainId",
            "type": "uint256"
          },
          {
            "name": "verifyingContract",
            "type": "address"
          }
        ],
        "PermitWitnessTransferFrom": [
          {
            "name": "permitted",
            "type": "TokenPermissions"
          },
          {
            "name": "spender",
            "type": "address"
          },
          {
            "name": "nonce",
            "type": "uint256"
          },
          {
            "name": "deadline",
            "type": "uint256"
          },
          {
            "name": "witness",
            "type": "PaymentIntent"
          }
        ],
        "TokenPermissions": [
          {
            "name": "token",
            "type": "address"
          },
          {
            "name": "amount",
            "type": "uint256"
          }
        ],
        "PaymentIntent": [
          {
            "name": "from",
            "type": "address"
          },
          {
            "name": "to",
            "type": "address"
          },
          {
            "name": "value",
            "type": "uint256"
          },
          {
            "name": "validAfter",
            "type": "uint256"
          },
          {
            "name": "validBefore",
            "type": "uint256"
          },
          {
            "name": "nonce",
            "type": "bytes32"
          },
          {
            "name": "beneficiary",
            "type": "address"
          },
          {
            "name": "maxFee",
            "type": "uint256"
          },
          {
            "name": "requirePayeeSign",
            "type": "bool"
          },
          {
            "name": "attester",
            "type": "address"
          }
        ]
      }
    },
    "metadata": {}
  }
}

From the response in the previous step, extract the messageToBeSigned field. You must sign this data using EIP-712 typed data signing from your sender wallet. Once signed, you should submit it to the submit transaction V2 endpoint. The following is an example request:

Shell
curl --request POST \
  --url https://api.circle.com/v2/cpn/payments/:paymentId/transactions/:transactionId/submit \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer ${YOUR_API_KEY}' \
  --header 'Content-type: application/json' \
  --data '
{
  "signedTransaction": "0x12b5fb72e99f9bb0300d2eb66a6d89dd5a667f43669893cf14bfcc390754dcb61b69f92cba598ec83a184e11c97e3bb9964a2bfd7a09688eee63f586ad9ccae21c"
}
'

After the transaction is submitted, CPN is responsible for broadcasting the transaction to the blockchain. You will be notified by webhooks when events related to the transaction occur. Unlike Transaction V1, you don't need to actively monitor the transaction or manually accelerate it. CPN monitors the transaction and automatically accelerates it if necessary.

Did this page help you?
© 2023-2025 Circle Technology Services, LLC. All rights reserved.