> ## Documentation Index
> Fetch the complete documentation index at: https://developers.circle.com/llms.txt
> Use this file to discover all available pages before exploring further.

# How-to: Migrate from transactions V1 to V2

> Update your CPN integration 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:

* 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.

Depending on the blockchain, there are additional differences:

<Tabs>
  <Tab title="EVM chains">
    * Before initiating a transaction, the sender wallet must grant the
      [`Permit2` contract](https://docs.uniswap.org/contracts/permit2/overview) a
      USDC allowance.
    * 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.
  </Tab>

  <Tab title="Solana">
    * In the signing process, instead of deserializing and signing the
      `messageToBeSigned` field, you would need to use the
      `encodedMessageToBeSigned` field. Please refer to [How-to: Create an Onchain
      Transaction](/cpn/guides/transactions/create-an-onchain-txn) for more
      information on how to sign the transaction in V2.
  </Tab>
</Tabs>

This guide provides information on how to migrate your existing integration from
Transactions V1 to V2 on EVM. On Solana, you would follow a similar process with
some differences in the signing process.

## Prerequisites

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
* (EVM chains only) Granted a USDC allowance to the `Permit2` contract. See
  [How-to: Grant USDC Allowance to Permit2](/cpn/guides/transactions/grant-usdc-allowance-to-permit2)
  for more information.

> **Note:** This guide provides API requests in cURL format, along with example
> responses.

## Steps

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

### Step 1. Create a quote

Use the [create a quote](/api-reference/cpn/cpn-platform/create-quotes) endpoint
to create a quote with the `transactionVersion` parameter set to `VERSION_2`.
When checking limits beforehand, call the
[list routes](/api-reference/cpn/cpn-platform/list-routes) endpoint with
`transactionVersion=VERSION_2` so returned crypto min limits include the
chain-specific fee buffer.

```shell theme={null}
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 theme={null}
{
  "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"
    }
  ]
}
```

> **Note:** The quote returned from this step must follow the Transactions V2
> workflow, you can't switch from V2 back to V1 without first recreating the
> quote.

### Step 2. Create a V2 transaction

You would then follow the same payment API workflow as before, create a payment
from the [create a payment](/api-reference/cpn/cpn-platform/create-payment)
endpoint. After your payment is in the `CRYPTO_FUNDS_PENDING` state, initiate
the transaction using the
[create a transaction V2](/api-reference/cpn/cpn-platform/create-transaction-v2)
endpoint.

```shell theme={null}
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 theme={null}
{
  "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": {}
  }
}
```

### Step 3. Sign and submit the transaction

From the response in the previous step, extract the `messageToBeSigned` field.
You must sign this data using [EIP-712](https://eips.ethereum.org/EIPS/eip-712)
typed data signing from your sender wallet. Once signed, you should submit it to
the
[submit transaction V2](/api-reference/cpn/cpn-platform/submit-transaction-v2)
endpoint. The following is an example request:

```shell theme={null}
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"
}
'
```

<Note>
  **Note:** For Solana, follow the steps in [How-to: Create an Onchain
  Transaction](/cpn/guides/transactions/create-an-onchain-txn) to sign the
  transaction. You would submit the signed transaction in the same way as for
  EVM.
</Note>

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.
