diff --git a/Cargo.lock b/Cargo.lock
index c2d2eb3e9644614e29b268c32940ed63781a9176..58b8b222cce469558c263b432d1afcd3466cc194 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -899,6 +899,7 @@ dependencies = [
  "pallet-xcm-benchmarks 7.0.0",
  "pallet-xcm-bridge-hub-router 0.5.0",
  "parachains-common 7.0.0",
+ "parachains-runtimes-test-utils 7.0.0",
  "parity-scale-codec",
  "polkadot-parachain-primitives 6.0.0",
  "polkadot-runtime-common 7.0.0",
@@ -1036,6 +1037,7 @@ dependencies = [
  "pallet-xcm-benchmarks 7.0.0",
  "pallet-xcm-bridge-hub-router 0.5.0",
  "parachains-common 7.0.0",
+ "parachains-runtimes-test-utils 7.0.0",
  "parity-scale-codec",
  "polkadot-parachain-primitives 6.0.0",
  "polkadot-runtime-common 7.0.0",
@@ -1077,6 +1079,7 @@ dependencies = [
  "frame-support 28.0.0",
  "frame-system 28.0.0",
  "hex-literal",
+ "pallet-asset-conversion 10.0.0",
  "pallet-assets 29.1.0",
  "pallet-balances 28.0.0",
  "pallet-collator-selection 9.0.0",
@@ -1094,6 +1097,7 @@ dependencies = [
  "staging-xcm-builder 7.0.0",
  "staging-xcm-executor 7.0.0",
  "substrate-wasm-builder 17.0.0",
+ "xcm-runtime-apis 0.1.0",
 ]
 
 [[package]]
@@ -2578,6 +2582,7 @@ dependencies = [
  "pallet-xcm-benchmarks 7.0.0",
  "pallet-xcm-bridge-hub 0.2.0",
  "parachains-common 7.0.0",
+ "parachains-runtimes-test-utils 7.0.0",
  "parity-scale-codec",
  "polkadot-parachain-primitives 6.0.0",
  "polkadot-runtime-common 7.0.0",
@@ -2815,6 +2820,7 @@ dependencies = [
  "pallet-xcm-benchmarks 7.0.0",
  "pallet-xcm-bridge-hub 0.2.0",
  "parachains-common 7.0.0",
+ "parachains-runtimes-test-utils 7.0.0",
  "parity-scale-codec",
  "polkadot-parachain-primitives 6.0.0",
  "polkadot-runtime-common 7.0.0",
@@ -3550,6 +3556,7 @@ dependencies = [
  "pallet-utility 28.0.0",
  "pallet-xcm 7.0.0",
  "parachains-common 7.0.0",
+ "parachains-runtimes-test-utils 7.0.0",
  "parity-scale-codec",
  "polkadot-parachain-primitives 6.0.0",
  "polkadot-runtime-common 7.0.0",
@@ -3991,6 +3998,7 @@ dependencies = [
  "pallet-xcm 7.0.0",
  "pallet-xcm-benchmarks 7.0.0",
  "parachains-common 7.0.0",
+ "parachains-runtimes-test-utils 7.0.0",
  "parity-scale-codec",
  "polkadot-parachain-primitives 6.0.0",
  "polkadot-runtime-common 7.0.0",
@@ -4090,6 +4098,7 @@ dependencies = [
  "pallet-xcm 7.0.0",
  "pallet-xcm-benchmarks 7.0.0",
  "parachains-common 7.0.0",
+ "parachains-runtimes-test-utils 7.0.0",
  "parity-scale-codec",
  "polkadot-parachain-primitives 6.0.0",
  "polkadot-runtime-common 7.0.0",
@@ -16165,6 +16174,7 @@ dependencies = [
  "pallet-session 28.0.0",
  "pallet-timestamp 27.0.0",
  "pallet-xcm 7.0.0",
+ "parachains-common 7.0.0",
  "parity-scale-codec",
  "polkadot-parachain-primitives 6.0.0",
  "sp-consensus-aura 0.32.0",
@@ -16176,6 +16186,7 @@ dependencies = [
  "staging-xcm 7.0.0",
  "staging-xcm-executor 7.0.0",
  "substrate-wasm-builder 17.0.0",
+ "xcm-runtime-apis 0.1.0",
 ]
 
 [[package]]
@@ -16574,6 +16585,7 @@ dependencies = [
  "pallet-xcm 7.0.0",
  "pallet-xcm-benchmarks 7.0.0",
  "parachains-common 7.0.0",
+ "parachains-runtimes-test-utils 7.0.0",
  "parity-scale-codec",
  "polkadot-parachain-primitives 6.0.0",
  "polkadot-runtime-common 7.0.0",
@@ -16675,6 +16687,7 @@ dependencies = [
  "pallet-xcm 7.0.0",
  "pallet-xcm-benchmarks 7.0.0",
  "parachains-common 7.0.0",
+ "parachains-runtimes-test-utils 7.0.0",
  "parity-scale-codec",
  "polkadot-parachain-primitives 6.0.0",
  "polkadot-runtime-common 7.0.0",
diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml
index 42adaba7a27c50f1e3157c6b9a70d662e627ae90..bfe8ed8697588b9572b7cb6ea3a8dd1f1a519afe 100644
--- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml
+++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml
@@ -99,6 +99,7 @@ snowbridge-router-primitives = { workspace = true }
 
 [dev-dependencies]
 asset-test-utils = { workspace = true, default-features = true }
+parachains-runtimes-test-utils = { workspace = true, default-features = true }
 
 [build-dependencies]
 substrate-wasm-builder = { optional = true, workspace = true, default-features = true }
diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs
index bc48c2d805fdb177fc19e32c2af85a0782d9111d..b6f3ccd3901bcf5f196f06bbb2dd94179d91dd28 100644
--- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs
+++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs
@@ -1415,37 +1415,31 @@ impl_runtime_apis! {
 			// We accept the native token to pay fees.
 			let mut acceptable_assets = vec![AssetId(native_token.clone())];
 			// We also accept all assets in a pool with the native token.
-			let assets_in_pool_with_native = assets_common::get_assets_in_pool_with::<
-				Runtime,
-				xcm::v5::Location
-			>(&native_token).map_err(|()| XcmPaymentApiError::VersionedConversionFailed)?.into_iter();
-			acceptable_assets.extend(assets_in_pool_with_native);
+			acceptable_assets.extend(
+				assets_common::PoolAdapter::<Runtime>::get_assets_in_pool_with(native_token)
+				.map_err(|()| XcmPaymentApiError::VersionedConversionFailed)?
+			);
 			PolkadotXcm::query_acceptable_payment_assets(xcm_version, acceptable_assets)
 		}
 
 		fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result<u128, XcmPaymentApiError> {
 			let native_asset = xcm_config::TokenLocation::get();
 			let fee_in_native = WeightToFee::weight_to_fee(&weight);
-			match asset.try_as::<AssetId>() {
+			let latest_asset_id: Result<AssetId, ()> = asset.clone().try_into();
+			match latest_asset_id {
 				Ok(asset_id) if asset_id.0 == native_asset => {
 					// for native token
 					Ok(fee_in_native)
 				},
 				Ok(asset_id) => {
-					let assets_in_pool_with_this_asset: Vec<_> = assets_common::get_assets_in_pool_with::<
-						Runtime,
-						xcm::v5::Location
-					>(&asset_id.0).map_err(|()| XcmPaymentApiError::VersionedConversionFailed)?;
-					if assets_in_pool_with_this_asset
-						.into_iter()
-						.map(|asset_id| asset_id.0)
-						.any(|location| location == native_asset) {
-						pallet_asset_conversion::Pallet::<Runtime>::quote_price_tokens_for_exact_tokens(
-							asset_id.clone().0,
+					// Try to get current price of `asset_id` in `native_asset`.
+					if let Ok(Some(swapped_in_native)) = assets_common::PoolAdapter::<Runtime>::quote_price_tokens_for_exact_tokens(
+							asset_id.0.clone(),
 							native_asset,
 							fee_in_native,
 							true, // We include the fee.
-						).ok_or(XcmPaymentApiError::AssetNotFound)
+						) {
+						Ok(swapped_in_native)
 					} else {
 						log::trace!(target: "xcm::xcm_runtime_apis", "query_weight_to_asset_fee - unhandled asset_id: {asset_id:?}!");
 						Err(XcmPaymentApiError::AssetNotFound)
diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs
index 5da8b45417a3baafdccf3eab73ddb3f5224a2fb2..d056405adff8d2763ed5b8900f4150d8bdd09383 100644
--- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs
+++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs
@@ -24,10 +24,10 @@ use asset_hub_rococo_runtime::{
 		ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger, LocationToAccountId, StakingPot,
 		TokenLocation, TrustBackedAssetsPalletLocation, XcmConfig,
 	},
-	AllPalletsWithoutSystem, AssetConversion, AssetDeposit, Assets, Balances, CollatorSelection,
-	ExistentialDeposit, ForeignAssets, ForeignAssetsInstance, MetadataDepositBase,
-	MetadataDepositPerByte, ParachainSystem, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin,
-	SessionKeys, TrustBackedAssetsInstance, XcmpQueue,
+	AllPalletsWithoutSystem, AssetConversion, AssetDeposit, Assets, Balances, Block,
+	CollatorSelection, ExistentialDeposit, ForeignAssets, ForeignAssetsInstance,
+	MetadataDepositBase, MetadataDepositPerByte, ParachainSystem, Runtime, RuntimeCall,
+	RuntimeEvent, RuntimeOrigin, SessionKeys, TrustBackedAssetsInstance, XcmpQueue,
 };
 use asset_test_utils::{
 	test_cases_over_bridge::TestBridgingConfig, CollatorSessionKey, CollatorSessionKeys,
@@ -1471,3 +1471,19 @@ fn location_conversion_works() {
 		assert_eq!(got, expected, "{}", tc.description);
 	}
 }
+
+#[test]
+fn xcm_payment_api_works() {
+	parachains_runtimes_test_utils::test_cases::xcm_payment_api_with_native_token_works::<
+		Runtime,
+		RuntimeCall,
+		RuntimeOrigin,
+		Block,
+	>();
+	asset_test_utils::test_cases::xcm_payment_api_with_pools_works::<
+		Runtime,
+		RuntimeCall,
+		RuntimeOrigin,
+		Block,
+	>();
+}
diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml
index d5eaa43ab83449254962b295d2b6a4a413257582..a3eaebb591536255f2e711a2d1d26e39dd77fd6c 100644
--- a/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml
+++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml
@@ -101,6 +101,7 @@ snowbridge-router-primitives = { workspace = true }
 
 [dev-dependencies]
 asset-test-utils = { workspace = true, default-features = true }
+parachains-runtimes-test-utils = { workspace = true, default-features = true }
 
 [build-dependencies]
 substrate-wasm-builder = { optional = true, workspace = true, default-features = true }
diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs
index cafea3b6ff8bb626c4e798b8c1ef41154b5024a6..f20b6b1fece081e86335dd3334a9436714d6bca7 100644
--- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs
+++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs
@@ -1528,38 +1528,31 @@ impl_runtime_apis! {
 			// We accept the native token to pay fees.
 			let mut acceptable_assets = vec![AssetId(native_token.clone())];
 			// We also accept all assets in a pool with the native token.
-			let assets_in_pool_with_native = assets_common::get_assets_in_pool_with::<
-				Runtime,
-				xcm::v5::Location
-			>(&native_token).map_err(|()| XcmPaymentApiError::VersionedConversionFailed)?.into_iter();
-			acceptable_assets.extend(assets_in_pool_with_native);
+			acceptable_assets.extend(
+				assets_common::PoolAdapter::<Runtime>::get_assets_in_pool_with(native_token)
+				.map_err(|()| XcmPaymentApiError::VersionedConversionFailed)?
+			);
 			PolkadotXcm::query_acceptable_payment_assets(xcm_version, acceptable_assets)
 		}
 
 		fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result<u128, XcmPaymentApiError> {
 			let native_asset = xcm_config::WestendLocation::get();
 			let fee_in_native = WeightToFee::weight_to_fee(&weight);
-			match asset.try_as::<AssetId>() {
+			let latest_asset_id: Result<AssetId, ()> = asset.clone().try_into();
+			match latest_asset_id {
 				Ok(asset_id) if asset_id.0 == native_asset => {
 					// for native asset
 					Ok(fee_in_native)
 				},
 				Ok(asset_id) => {
-					// We recognize assets in a pool with the native one.
-					let assets_in_pool_with_this_asset: Vec<_> = assets_common::get_assets_in_pool_with::<
-						Runtime,
-						xcm::v5::Location
-					>(&asset_id.0).map_err(|()| XcmPaymentApiError::VersionedConversionFailed)?;
-					if assets_in_pool_with_this_asset
-						.into_iter()
-						.map(|asset_id| asset_id.0)
-						.any(|location| location == native_asset) {
-						pallet_asset_conversion::Pallet::<Runtime>::quote_price_tokens_for_exact_tokens(
-							asset_id.clone().0,
+					// Try to get current price of `asset_id` in `native_asset`.
+					if let Ok(Some(swapped_in_native)) = assets_common::PoolAdapter::<Runtime>::quote_price_tokens_for_exact_tokens(
+							asset_id.0.clone(),
 							native_asset,
 							fee_in_native,
 							true, // We include the fee.
-						).ok_or(XcmPaymentApiError::AssetNotFound)
+						) {
+						Ok(swapped_in_native)
 					} else {
 						log::trace!(target: "xcm::xcm_runtime_apis", "query_weight_to_asset_fee - unhandled asset_id: {asset_id:?}!");
 						Err(XcmPaymentApiError::AssetNotFound)
diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs
index 5d0f843554a11572b21a67037f3dcf088039a823..109a5dd2c029594e187f902f768d2e502bb39565 100644
--- a/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs
+++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs
@@ -24,7 +24,7 @@ use asset_hub_westend_runtime::{
 		ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger, LocationToAccountId, StakingPot,
 		TrustBackedAssetsPalletLocation, WestendLocation, XcmConfig,
 	},
-	AllPalletsWithoutSystem, Assets, Balances, ExistentialDeposit, ForeignAssets,
+	AllPalletsWithoutSystem, Assets, Balances, Block, ExistentialDeposit, ForeignAssets,
 	ForeignAssetsInstance, MetadataDepositBase, MetadataDepositPerByte, ParachainSystem,
 	PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, SessionKeys,
 	TrustBackedAssetsInstance, XcmpQueue,
@@ -1446,3 +1446,19 @@ fn location_conversion_works() {
 		assert_eq!(got, expected, "{}", tc.description);
 	}
 }
+
+#[test]
+fn xcm_payment_api_works() {
+	parachains_runtimes_test_utils::test_cases::xcm_payment_api_with_native_token_works::<
+		Runtime,
+		RuntimeCall,
+		RuntimeOrigin,
+		Block,
+	>();
+	asset_test_utils::test_cases::xcm_payment_api_with_pools_works::<
+		Runtime,
+		RuntimeCall,
+		RuntimeOrigin,
+		Block,
+	>();
+}
diff --git a/cumulus/parachains/runtimes/assets/common/src/lib.rs b/cumulus/parachains/runtimes/assets/common/src/lib.rs
index 1d2d45b42c5d02779be9e25f8bae63d4a9195519..25c2df6b68d16c9eb282b564e8b7a4acf23f9e3a 100644
--- a/cumulus/parachains/runtimes/assets/common/src/lib.rs
+++ b/cumulus/parachains/runtimes/assets/common/src/lib.rs
@@ -28,7 +28,7 @@ extern crate alloc;
 use crate::matching::{LocalLocationPattern, ParentLocation};
 use alloc::vec::Vec;
 use codec::{Decode, EncodeLike};
-use core::cmp::PartialEq;
+use core::{cmp::PartialEq, marker::PhantomData};
 use frame_support::traits::{Equals, EverythingBut};
 use parachains_common::{AssetIdForTrustBackedAssets, CollectionId, ItemId};
 use sp_runtime::traits::TryConvertInto;
@@ -137,24 +137,62 @@ pub type PoolAssetsConvertedConcreteId<PoolAssetsPalletLocation, Balance> =
 		TryConvertInto,
 	>;
 
-/// Returns an iterator of all assets in a pool with `asset`.
-///
-/// Should only be used in runtime APIs since it iterates over the whole
-/// `pallet_asset_conversion::Pools` map.
-///
-/// It takes in any version of an XCM Location but always returns the latest one.
-/// This is to allow some margin of migrating the pools when updating the XCM version.
-///
-/// An error of type `()` is returned if the version conversion fails for XCM locations.
-/// This error should be mapped by the caller to a more descriptive one.
-pub fn get_assets_in_pool_with<
-	Runtime: pallet_asset_conversion::Config<PoolId = (L, L)>,
-	L: TryInto<Location> + Clone + Decode + EncodeLike + PartialEq,
->(
-	asset: &L,
-) -> Result<Vec<AssetId>, ()> {
-	pallet_asset_conversion::Pools::<Runtime>::iter_keys()
-		.filter_map(|(asset_1, asset_2)| {
+/// Adapter implementation for accessing pools (`pallet_asset_conversion`) that uses `AssetKind` as
+/// a `xcm::v*` which could be different from the `xcm::latest`.
+pub struct PoolAdapter<Runtime>(PhantomData<Runtime>);
+impl<
+		Runtime: pallet_asset_conversion::Config<PoolId = (L, L), AssetKind = L>,
+		L: TryFrom<Location> + TryInto<Location> + Clone + Decode + EncodeLike + PartialEq,
+	> PoolAdapter<Runtime>
+{
+	/// Returns a vector of all assets in a pool with `asset`.
+	///
+	/// Should only be used in runtime APIs since it iterates over the whole
+	/// `pallet_asset_conversion::Pools` map.
+	///
+	/// It takes in any version of an XCM Location but always returns the latest one.
+	/// This is to allow some margin of migrating the pools when updating the XCM version.
+	///
+	/// An error of type `()` is returned if the version conversion fails for XCM locations.
+	/// This error should be mapped by the caller to a more descriptive one.
+	pub fn get_assets_in_pool_with(asset: Location) -> Result<Vec<AssetId>, ()> {
+		// convert latest to the `L` version.
+		let asset: L = asset.try_into().map_err(|_| ())?;
+		Self::iter_assets_in_pool_with(&asset)
+			.map(|location| {
+				// convert `L` to the latest `AssetId`
+				location.try_into().map_err(|_| ()).map(AssetId)
+			})
+			.collect::<Result<Vec<_>, _>>()
+	}
+
+	/// Provides a current prices. Wrapper over
+	/// `pallet_asset_conversion::Pallet::<T>::quote_price_tokens_for_exact_tokens`.
+	///
+	/// An error of type `()` is returned if the version conversion fails for XCM locations.
+	/// This error should be mapped by the caller to a more descriptive one.
+	pub fn quote_price_tokens_for_exact_tokens(
+		asset_1: Location,
+		asset_2: Location,
+		amount: Runtime::Balance,
+		include_fees: bool,
+	) -> Result<Option<Runtime::Balance>, ()> {
+		// Convert latest to the `L` version.
+		let asset_1: L = asset_1.try_into().map_err(|_| ())?;
+		let asset_2: L = asset_2.try_into().map_err(|_| ())?;
+
+		// Quote swap price.
+		Ok(pallet_asset_conversion::Pallet::<Runtime>::quote_price_tokens_for_exact_tokens(
+			asset_1,
+			asset_2,
+			amount,
+			include_fees,
+		))
+	}
+
+	/// Helper function for filtering pool.
+	pub fn iter_assets_in_pool_with(asset: &L) -> impl Iterator<Item = L> + '_ {
+		pallet_asset_conversion::Pools::<Runtime>::iter_keys().filter_map(|(asset_1, asset_2)| {
 			if asset_1 == *asset {
 				Some(asset_2)
 			} else if asset_2 == *asset {
@@ -163,8 +201,7 @@ pub fn get_assets_in_pool_with<
 				None
 			}
 		})
-		.map(|location| location.try_into().map_err(|_| ()).map(AssetId))
-		.collect::<Result<Vec<_>, _>>()
+	}
 }
 
 #[cfg(test)]
diff --git a/cumulus/parachains/runtimes/assets/test-utils/Cargo.toml b/cumulus/parachains/runtimes/assets/test-utils/Cargo.toml
index 529d6460fc4e46b6a7d04ae77c01f7135f6eed9d..f6b3c13e8102257e79023b2d8055f871538638ae 100644
--- a/cumulus/parachains/runtimes/assets/test-utils/Cargo.toml
+++ b/cumulus/parachains/runtimes/assets/test-utils/Cargo.toml
@@ -16,6 +16,7 @@ codec = { features = ["derive", "max-encoded-len"], workspace = true }
 frame-support = { workspace = true }
 frame-system = { workspace = true }
 pallet-assets = { workspace = true }
+pallet-asset-conversion = { workspace = true }
 pallet-balances = { workspace = true }
 pallet-timestamp = { workspace = true }
 pallet-session = { workspace = true }
@@ -36,6 +37,7 @@ xcm = { workspace = true }
 xcm-builder = { workspace = true }
 xcm-executor = { workspace = true }
 pallet-xcm = { workspace = true }
+xcm-runtime-apis = { workspace = true }
 
 # Bridges
 pallet-xcm-bridge-hub-router = { workspace = true }
@@ -55,6 +57,7 @@ std = [
 	"cumulus-primitives-core/std",
 	"frame-support/std",
 	"frame-system/std",
+	"pallet-asset-conversion/std",
 	"pallet-assets/std",
 	"pallet-balances/std",
 	"pallet-collator-selection/std",
@@ -69,5 +72,6 @@ std = [
 	"sp-runtime/std",
 	"xcm-builder/std",
 	"xcm-executor/std",
+	"xcm-runtime-apis/std",
 	"xcm/std",
 ]
diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs
index 8dc720e2775300910e820d5ade327b30b5099917..aeacc1a5471e4a0b3774f7a6080f37704b6432d8 100644
--- a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs
+++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs
@@ -34,11 +34,14 @@ use parachains_runtimes_test_utils::{
 	CollatorSessionKeys, ExtBuilder, SlotDurations, ValidatorIdOf, XcmReceivedFrom,
 };
 use sp_runtime::{
-	traits::{MaybeEquivalence, StaticLookup, Zero},
+	traits::{Block as BlockT, MaybeEquivalence, StaticLookup, Zero},
 	DispatchError, Saturating,
 };
 use xcm::{latest::prelude::*, VersionedAssets};
 use xcm_executor::{traits::ConvertLocation, XcmExecutor};
+use xcm_runtime_apis::fees::{
+	runtime_decl_for_xcm_payment_api::XcmPaymentApiV1, Error as XcmPaymentApiError,
+};
 
 type RuntimeHelper<Runtime, AllPalletsWithoutSystem = ()> =
 	parachains_runtimes_test_utils::RuntimeHelper<Runtime, AllPalletsWithoutSystem>;
@@ -1584,3 +1587,108 @@ pub fn reserve_transfer_native_asset_to_non_teleport_para_works<
 			);
 		})
 }
+
+pub fn xcm_payment_api_with_pools_works<Runtime, RuntimeCall, RuntimeOrigin, Block>()
+where
+	Runtime: XcmPaymentApiV1<Block>
+		+ frame_system::Config<RuntimeOrigin = RuntimeOrigin, AccountId = AccountId>
+		+ pallet_balances::Config<Balance = u128>
+		+ pallet_session::Config
+		+ pallet_xcm::Config
+		+ parachain_info::Config
+		+ pallet_collator_selection::Config
+		+ cumulus_pallet_parachain_system::Config
+		+ cumulus_pallet_xcmp_queue::Config
+		+ pallet_timestamp::Config
+		+ pallet_assets::Config<
+			pallet_assets::Instance1,
+			AssetId = u32,
+			Balance = <Runtime as pallet_balances::Config>::Balance,
+		> + pallet_asset_conversion::Config<
+			AssetKind = xcm::v5::Location,
+			Balance = <Runtime as pallet_balances::Config>::Balance,
+		>,
+	ValidatorIdOf<Runtime>: From<AccountIdOf<Runtime>>,
+	RuntimeOrigin: OriginTrait<AccountId = <Runtime as frame_system::Config>::AccountId>,
+	<<Runtime as frame_system::Config>::Lookup as StaticLookup>::Source:
+		From<<Runtime as frame_system::Config>::AccountId>,
+	Block: BlockT,
+{
+	use xcm::prelude::*;
+
+	ExtBuilder::<Runtime>::default().build().execute_with(|| {
+		let test_account = AccountId::from([0u8; 32]);
+		let transfer_amount = 100u128;
+		let xcm_to_weigh = Xcm::<RuntimeCall>::builder_unsafe()
+			.withdraw_asset((Here, transfer_amount))
+			.buy_execution((Here, transfer_amount), Unlimited)
+			.deposit_asset(AllCounted(1), [1u8; 32])
+			.build();
+		let versioned_xcm_to_weigh = VersionedXcm::from(xcm_to_weigh.clone().into());
+
+		let xcm_weight = Runtime::query_xcm_weight(versioned_xcm_to_weigh);
+		assert!(xcm_weight.is_ok());
+		let native_token: Location = Parent.into();
+		let native_token_versioned = VersionedAssetId::from(AssetId(native_token.clone()));
+		let execution_fees =
+			Runtime::query_weight_to_asset_fee(xcm_weight.unwrap(), native_token_versioned);
+		assert!(execution_fees.is_ok());
+
+		// We need some balance to create an asset.
+		assert_ok!(
+			pallet_balances::Pallet::<Runtime>::mint_into(&test_account, 3_000_000_000_000,)
+		);
+
+		// Now we try to use an asset that's not in a pool.
+		let asset_id = 1984u32; // USDT.
+		let asset_not_in_pool: Location =
+			(PalletInstance(50), GeneralIndex(asset_id.into())).into();
+		assert_ok!(pallet_assets::Pallet::<Runtime, pallet_assets::Instance1>::create(
+			RuntimeOrigin::signed(test_account.clone()),
+			asset_id.into(),
+			test_account.clone().into(),
+			1000
+		));
+		let execution_fees = Runtime::query_weight_to_asset_fee(
+			xcm_weight.unwrap(),
+			asset_not_in_pool.clone().into(),
+		);
+		assert_eq!(execution_fees, Err(XcmPaymentApiError::AssetNotFound));
+
+		// We add it to a pool with native.
+		assert_ok!(pallet_asset_conversion::Pallet::<Runtime>::create_pool(
+			RuntimeOrigin::signed(test_account.clone()),
+			native_token.clone().try_into().unwrap(),
+			asset_not_in_pool.clone().try_into().unwrap()
+		));
+		let execution_fees = Runtime::query_weight_to_asset_fee(
+			xcm_weight.unwrap(),
+			asset_not_in_pool.clone().into(),
+		);
+		// Still not enough because it doesn't have any liquidity.
+		assert_eq!(execution_fees, Err(XcmPaymentApiError::AssetNotFound));
+
+		// We mint some of the asset...
+		assert_ok!(pallet_assets::Pallet::<Runtime, pallet_assets::Instance1>::mint(
+			RuntimeOrigin::signed(test_account.clone()),
+			asset_id.into(),
+			test_account.clone().into(),
+			3_000_000_000_000,
+		));
+		// ...so we can add liquidity to the pool.
+		assert_ok!(pallet_asset_conversion::Pallet::<Runtime>::add_liquidity(
+			RuntimeOrigin::signed(test_account.clone()),
+			native_token.try_into().unwrap(),
+			asset_not_in_pool.clone().try_into().unwrap(),
+			1_000_000_000_000,
+			2_000_000_000_000,
+			0,
+			0,
+			test_account
+		));
+		let execution_fees =
+			Runtime::query_weight_to_asset_fee(xcm_weight.unwrap(), asset_not_in_pool.into());
+		// Now it works!
+		assert_ok!(execution_fees);
+	});
+}
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml
index 4af8a9f4385047ef547d4cb58368e0b9a57d9cf6..3eb06e3a18c18337e122e419717ed720601f48e7 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml
@@ -122,6 +122,7 @@ bridge-hub-test-utils = { workspace = true, default-features = true }
 bridge-runtime-common = { features = ["integrity-test"], workspace = true, default-features = true }
 pallet-bridge-relayers = { features = ["integrity-test"], workspace = true }
 snowbridge-runtime-test-common = { workspace = true, default-features = true }
+parachains-runtimes-test-utils = { workspace = true, default-features = true }
 
 [features]
 default = ["std"]
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs
index 3f3316d0be49cd85e56db7b8b893b936f1bffa90..598afeddb984ce83bc7779688e263067e4e92047 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs
@@ -847,7 +847,8 @@ impl_runtime_apis! {
 		}
 
 		fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result<u128, XcmPaymentApiError> {
-			match asset.try_as::<AssetId>() {
+			let latest_asset_id: Result<AssetId, ()> = asset.clone().try_into();
+			match latest_asset_id {
 				Ok(asset_id) if asset_id.0 == xcm_config::TokenLocation::get() => {
 					// for native token
 					Ok(WeightToFee::weight_to_fee(&weight))
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs
index 6ca858e961d3ea9771a8f5dd98f65c2da850b121..29f9615bff6a8bcef1432be9823e5ef8ca3cc319 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs
@@ -20,9 +20,9 @@ use bp_polkadot_core::Signature;
 use bridge_hub_rococo_runtime::{
 	bridge_common_config, bridge_to_bulletin_config, bridge_to_westend_config,
 	xcm_config::{RelayNetwork, TokenLocation, XcmConfig},
-	AllPalletsWithoutSystem, BridgeRejectObsoleteHeadersAndMessages, Executive, ExistentialDeposit,
-	ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, SessionKeys,
-	TransactionPayment, TxExtension, UncheckedExtrinsic,
+	AllPalletsWithoutSystem, Block, BridgeRejectObsoleteHeadersAndMessages, Executive,
+	ExistentialDeposit, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent,
+	RuntimeOrigin, SessionKeys, TransactionPayment, TxExtension, UncheckedExtrinsic,
 };
 use bridge_hub_test_utils::SlotDurations;
 use codec::{Decode, Encode};
@@ -838,3 +838,13 @@ fn location_conversion_works() {
 		assert_eq!(got, expected, "{}", tc.description);
 	}
 }
+
+#[test]
+fn xcm_payment_api_works() {
+	parachains_runtimes_test_utils::test_cases::xcm_payment_api_with_native_token_works::<
+		Runtime,
+		RuntimeCall,
+		RuntimeOrigin,
+		Block,
+	>();
+}
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/Cargo.toml
index 637e7c71064091c4f2736bf2dfd9c2b25e7201bd..871bf44ec5b2d61d8258db9b4164118ae7e6bc12 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/Cargo.toml
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/Cargo.toml
@@ -121,6 +121,7 @@ bridge-hub-test-utils = { workspace = true, default-features = true }
 bridge-runtime-common = { features = ["integrity-test"], workspace = true, default-features = true }
 pallet-bridge-relayers = { features = ["integrity-test"], workspace = true }
 snowbridge-runtime-test-common = { workspace = true, default-features = true }
+parachains-runtimes-test-utils = { workspace = true, default-features = true }
 
 [features]
 default = ["std"]
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs
index 65e7d291dc3719df0867c41c0346c9a87aa1db6f..ae3dbfa06cba4d2e590c0a5143fffe280039b481 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs
@@ -779,7 +779,8 @@ impl_runtime_apis! {
 		}
 
 		fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result<u128, XcmPaymentApiError> {
-			match asset.try_as::<AssetId>() {
+			let latest_asset_id: Result<AssetId, ()> = asset.clone().try_into();
+			match latest_asset_id {
 				Ok(asset_id) if asset_id.0 == xcm_config::WestendLocation::get() => {
 					// for native token
 					Ok(WeightToFee::weight_to_fee(&weight))
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs
index 84025c4cefeb5915f5004554a65fa6fee30466e9..d7e70ed769b1230fc7875ace85af19412f459827 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs
@@ -27,9 +27,9 @@ use bridge_hub_westend_runtime::{
 	bridge_common_config, bridge_to_rococo_config,
 	bridge_to_rococo_config::RococoGlobalConsensusNetwork,
 	xcm_config::{LocationToAccountId, RelayNetwork, WestendLocation, XcmConfig},
-	AllPalletsWithoutSystem, BridgeRejectObsoleteHeadersAndMessages, Executive, ExistentialDeposit,
-	ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, SessionKeys,
-	TransactionPayment, TxExtension, UncheckedExtrinsic,
+	AllPalletsWithoutSystem, Block, BridgeRejectObsoleteHeadersAndMessages, Executive,
+	ExistentialDeposit, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent,
+	RuntimeOrigin, SessionKeys, TransactionPayment, TxExtension, UncheckedExtrinsic,
 };
 use bridge_to_rococo_config::{
 	BridgeGrandpaRococoInstance, BridgeHubRococoLocation, BridgeParachainRococoInstance,
@@ -525,3 +525,13 @@ fn location_conversion_works() {
 		assert_eq!(got, expected, "{}", tc.description);
 	}
 }
+
+#[test]
+fn xcm_payment_api_works() {
+	parachains_runtimes_test_utils::test_cases::xcm_payment_api_with_native_token_works::<
+		Runtime,
+		RuntimeCall,
+		RuntimeOrigin,
+		Block,
+	>();
+}
diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/Cargo.toml b/cumulus/parachains/runtimes/collectives/collectives-westend/Cargo.toml
index e03fc934ceaf62e6174a6f91c5040ba384549ec4..810abcf572d47b8fbf36d17d1a02840d6165a845 100644
--- a/cumulus/parachains/runtimes/collectives/collectives-westend/Cargo.toml
+++ b/cumulus/parachains/runtimes/collectives/collectives-westend/Cargo.toml
@@ -94,6 +94,7 @@ substrate-wasm-builder = { optional = true, workspace = true, default-features =
 
 [dev-dependencies]
 sp-io = { features = ["std"], workspace = true, default-features = true }
+parachains-runtimes-test-utils = { workspace = true, default-features = true }
 
 [features]
 default = ["std"]
diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs
index 0ee3a40687180b7607a830ea0a000974c7377a49..f4c62f212e8c0ce0543ed8db697e987844c114b5 100644
--- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs
+++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs
@@ -963,7 +963,8 @@ impl_runtime_apis! {
 		}
 
 		fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result<u128, XcmPaymentApiError> {
-			match asset.try_as::<AssetId>() {
+			let latest_asset_id: Result<AssetId, ()> = asset.clone().try_into();
+			match latest_asset_id {
 				Ok(asset_id) if asset_id.0 == xcm_config::WndLocation::get() => {
 					// for native token
 					Ok(WeightToFee::weight_to_fee(&weight))
diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/tests/tests.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/tests/tests.rs
index 7add10559d84de880dbe96117bd70fa6b82e675e..c9191eba49f6a57b6bd05069c6287f024429a527 100644
--- a/cumulus/parachains/runtimes/collectives/collectives-westend/tests/tests.rs
+++ b/cumulus/parachains/runtimes/collectives/collectives-westend/tests/tests.rs
@@ -16,7 +16,9 @@
 
 #![cfg(test)]
 
-use collectives_westend_runtime::xcm_config::LocationToAccountId;
+use collectives_westend_runtime::{
+	xcm_config::LocationToAccountId, Block, Runtime, RuntimeCall, RuntimeOrigin,
+};
 use parachains_common::AccountId;
 use sp_core::crypto::Ss58Codec;
 use xcm::latest::prelude::*;
@@ -132,3 +134,13 @@ fn location_conversion_works() {
 		assert_eq!(got, expected, "{}", tc.description);
 	}
 }
+
+#[test]
+fn xcm_payment_api_works() {
+	parachains_runtimes_test_utils::test_cases::xcm_payment_api_with_native_token_works::<
+		Runtime,
+		RuntimeCall,
+		RuntimeOrigin,
+		Block,
+	>();
+}
diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml b/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml
index a38b7400cfa3e792517019039dc2430a364e7d3d..02807827cf924729134093753dff4bf909d7350f 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml
+++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml
@@ -80,6 +80,9 @@ parachain-info = { workspace = true }
 parachains-common = { workspace = true }
 testnet-parachains-constants = { features = ["rococo"], workspace = true }
 
+[dev-dependencies]
+parachains-runtimes-test-utils = { workspace = true }
+
 [features]
 default = ["std"]
 std = [
@@ -120,6 +123,7 @@ std = [
 	"pallet-xcm/std",
 	"parachain-info/std",
 	"parachains-common/std",
+	"parachains-runtimes-test-utils/std",
 	"polkadot-parachain-primitives/std",
 	"polkadot-runtime-common/std",
 	"rococo-runtime-constants/std",
diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs
index 3f3126b749d8190cb424b6e4a1a515f537c99261..ae3ad93a9e85a06470fa28b08bb2faf32e40cd29 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs
+++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs
@@ -835,7 +835,8 @@ impl_runtime_apis! {
 		}
 
 		fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result<u128, XcmPaymentApiError> {
-			match asset.try_as::<AssetId>() {
+			let latest_asset_id: Result<AssetId, ()> = asset.clone().try_into();
+			match latest_asset_id {
 				Ok(asset_id) if asset_id.0 == xcm_config::RocRelayLocation::get() => {
 					// for native token
 					Ok(WeightToFee::weight_to_fee(&weight))
diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/tests/tests.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/tests/tests.rs
index 2cabce567b6e73a8f833d6922539580e6d23e9f6..89a593ab0f576690186d19584c73b10c49717b7c 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-rococo/tests/tests.rs
+++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/tests/tests.rs
@@ -16,7 +16,9 @@
 
 #![cfg(test)]
 
-use coretime_rococo_runtime::xcm_config::LocationToAccountId;
+use coretime_rococo_runtime::{
+	xcm_config::LocationToAccountId, Block, Runtime, RuntimeCall, RuntimeOrigin,
+};
 use parachains_common::AccountId;
 use sp_core::crypto::Ss58Codec;
 use xcm::latest::prelude::*;
@@ -132,3 +134,13 @@ fn location_conversion_works() {
 		assert_eq!(got, expected, "{}", tc.description);
 	}
 }
+
+#[test]
+fn xcm_payment_api_works() {
+	parachains_runtimes_test_utils::test_cases::xcm_payment_api_with_native_token_works::<
+		Runtime,
+		RuntimeCall,
+		RuntimeOrigin,
+		Block,
+	>();
+}
diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml b/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml
index 149fa5d0b045c22da61def379263bad9d2182b53..34353d312b1fa3b6213e6bbc97250e5096692e6e 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml
+++ b/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml
@@ -80,6 +80,9 @@ parachain-info = { workspace = true }
 parachains-common = { workspace = true }
 testnet-parachains-constants = { features = ["westend"], workspace = true }
 
+[dev-dependencies]
+parachains-runtimes-test-utils = { workspace = true, default-features = true }
+
 [features]
 default = ["std"]
 std = [
diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs
index 098a17cc998419de5894bdb92e085cd3f56f57a9..39ea39f25a8b4fc736dd6e2d7ce5c7a7e6340298 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs
+++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs
@@ -827,7 +827,8 @@ impl_runtime_apis! {
 		}
 
 		fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result<u128, XcmPaymentApiError> {
-			match asset.try_as::<AssetId>() {
+			let latest_asset_id: Result<AssetId, ()> = asset.clone().try_into();
+			match latest_asset_id {
 				Ok(asset_id) if asset_id.0 == xcm_config::TokenRelayLocation::get() => {
 					// for native token
 					Ok(WeightToFee::weight_to_fee(&weight))
diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/tests/tests.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/tests/tests.rs
index e391d71a9ab782e69a0897dc8a7f980190b8c9e1..976ce23d6e8741e351a2a7b075f96ab38000350c 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-westend/tests/tests.rs
+++ b/cumulus/parachains/runtimes/coretime/coretime-westend/tests/tests.rs
@@ -16,7 +16,9 @@
 
 #![cfg(test)]
 
-use coretime_westend_runtime::xcm_config::LocationToAccountId;
+use coretime_westend_runtime::{
+	xcm_config::LocationToAccountId, Block, Runtime, RuntimeCall, RuntimeOrigin,
+};
 use parachains_common::AccountId;
 use sp_core::crypto::Ss58Codec;
 use xcm::latest::prelude::*;
@@ -132,3 +134,13 @@ fn location_conversion_works() {
 		assert_eq!(got, expected, "{}", tc.description);
 	}
 }
+
+#[test]
+fn xcm_payment_api_works() {
+	parachains_runtimes_test_utils::test_cases::xcm_payment_api_with_native_token_works::<
+		Runtime,
+		RuntimeCall,
+		RuntimeOrigin,
+		Block,
+	>();
+}
diff --git a/cumulus/parachains/runtimes/people/people-rococo/Cargo.toml b/cumulus/parachains/runtimes/people/people-rococo/Cargo.toml
index 34458c2352fbd36a1f0bb47655ec1f8648eaefbf..a55143b6207105bafab8b09115fb70893deab052 100644
--- a/cumulus/parachains/runtimes/people/people-rococo/Cargo.toml
+++ b/cumulus/parachains/runtimes/people/people-rococo/Cargo.toml
@@ -77,6 +77,9 @@ parachain-info = { workspace = true }
 parachains-common = { workspace = true }
 testnet-parachains-constants = { features = ["rococo"], workspace = true }
 
+[dev-dependencies]
+parachains-runtimes-test-utils = { workspace = true, default-features = true }
+
 [features]
 default = ["std"]
 std = [
diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs
index 7921030f2bb87ebda18ab412cd7890fde67ff912..dc5f2ac0997c560f75b21a61822ca3ac6d7f7098 100644
--- a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs
+++ b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs
@@ -783,7 +783,8 @@ impl_runtime_apis! {
 		}
 
 		fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result<u128, XcmPaymentApiError> {
-			match asset.try_as::<AssetId>() {
+			let latest_asset_id: Result<AssetId, ()> = asset.clone().try_into();
+			match latest_asset_id {
 				Ok(asset_id) if asset_id.0 == xcm_config::RelayLocation::get() => {
 					// for native token
 					Ok(WeightToFee::weight_to_fee(&weight))
diff --git a/cumulus/parachains/runtimes/people/people-rococo/tests/tests.rs b/cumulus/parachains/runtimes/people/people-rococo/tests/tests.rs
index 3627d9c40ec2b5754553a123fd58c84d33b75d06..00fe7781822ae1cef10258e08c7d1b14be714b32 100644
--- a/cumulus/parachains/runtimes/people/people-rococo/tests/tests.rs
+++ b/cumulus/parachains/runtimes/people/people-rococo/tests/tests.rs
@@ -17,7 +17,9 @@
 #![cfg(test)]
 
 use parachains_common::AccountId;
-use people_rococo_runtime::xcm_config::LocationToAccountId;
+use people_rococo_runtime::{
+	xcm_config::LocationToAccountId, Block, Runtime, RuntimeCall, RuntimeOrigin,
+};
 use sp_core::crypto::Ss58Codec;
 use xcm::latest::prelude::*;
 use xcm_runtime_apis::conversions::LocationToAccountHelper;
@@ -132,3 +134,13 @@ fn location_conversion_works() {
 		assert_eq!(got, expected, "{}", tc.description);
 	}
 }
+
+#[test]
+fn xcm_payment_api_works() {
+	parachains_runtimes_test_utils::test_cases::xcm_payment_api_with_native_token_works::<
+		Runtime,
+		RuntimeCall,
+		RuntimeOrigin,
+		Block,
+	>();
+}
diff --git a/cumulus/parachains/runtimes/people/people-westend/Cargo.toml b/cumulus/parachains/runtimes/people/people-westend/Cargo.toml
index 6840b97d8c3fa82a3ace10c468e885a38f06c2d0..4d66332e96dde163cfb12165ecc3802b44cc8b0e 100644
--- a/cumulus/parachains/runtimes/people/people-westend/Cargo.toml
+++ b/cumulus/parachains/runtimes/people/people-westend/Cargo.toml
@@ -77,6 +77,9 @@ parachain-info = { workspace = true }
 parachains-common = { workspace = true }
 testnet-parachains-constants = { features = ["westend"], workspace = true }
 
+[dev-dependencies]
+parachains-runtimes-test-utils = { workspace = true, default-features = true }
+
 [features]
 default = ["std"]
 std = [
diff --git a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs
index 19a64ab8d6e8fb44429c5782954ab91860aa3198..1b9a3b60a2c465d5f6008cc9b46e4d8fd57ec376 100644
--- a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs
+++ b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs
@@ -781,7 +781,8 @@ impl_runtime_apis! {
 		}
 
 		fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result<u128, XcmPaymentApiError> {
-			match asset.try_as::<AssetId>() {
+			let latest_asset_id: Result<AssetId, ()> = asset.clone().try_into();
+			match latest_asset_id {
 				Ok(asset_id) if asset_id.0 == xcm_config::RelayLocation::get() => {
 					// for native token
 					Ok(WeightToFee::weight_to_fee(&weight))
diff --git a/cumulus/parachains/runtimes/people/people-westend/tests/tests.rs b/cumulus/parachains/runtimes/people/people-westend/tests/tests.rs
index fa9331952b4b53a6012ad72d0d9b1bba2f4afec7..5cefec44b1cddf19ef2c875c86ff478e379d0f0f 100644
--- a/cumulus/parachains/runtimes/people/people-westend/tests/tests.rs
+++ b/cumulus/parachains/runtimes/people/people-westend/tests/tests.rs
@@ -17,7 +17,9 @@
 #![cfg(test)]
 
 use parachains_common::AccountId;
-use people_westend_runtime::xcm_config::LocationToAccountId;
+use people_westend_runtime::{
+	xcm_config::LocationToAccountId, Block, Runtime, RuntimeCall, RuntimeOrigin,
+};
 use sp_core::crypto::Ss58Codec;
 use xcm::latest::prelude::*;
 use xcm_runtime_apis::conversions::LocationToAccountHelper;
@@ -132,3 +134,13 @@ fn location_conversion_works() {
 		assert_eq!(got, expected, "{}", tc.description);
 	}
 }
+
+#[test]
+fn xcm_payment_api_works() {
+	parachains_runtimes_test_utils::test_cases::xcm_payment_api_with_native_token_works::<
+		Runtime,
+		RuntimeCall,
+		RuntimeOrigin,
+		Block,
+	>();
+}
diff --git a/cumulus/parachains/runtimes/test-utils/Cargo.toml b/cumulus/parachains/runtimes/test-utils/Cargo.toml
index 01d7fcc2b5c8b77c7daa90d807634193545e95ec..e9d666617ee2e0b244c196902164149a670355bc 100644
--- a/cumulus/parachains/runtimes/test-utils/Cargo.toml
+++ b/cumulus/parachains/runtimes/test-utils/Cargo.toml
@@ -29,6 +29,7 @@ cumulus-pallet-parachain-system = { workspace = true }
 cumulus-pallet-xcmp-queue = { workspace = true }
 pallet-collator-selection = { workspace = true }
 parachain-info = { workspace = true }
+parachains-common = { workspace = true }
 cumulus-primitives-core = { workspace = true }
 cumulus-primitives-parachain-inherent = { workspace = true }
 cumulus-test-relay-sproof-builder = { workspace = true }
@@ -37,6 +38,7 @@ cumulus-test-relay-sproof-builder = { workspace = true }
 xcm = { workspace = true }
 xcm-executor = { workspace = true }
 pallet-xcm = { workspace = true }
+xcm-runtime-apis = { workspace = true }
 polkadot-parachain-primitives = { workspace = true }
 
 [dev-dependencies]
@@ -62,11 +64,13 @@ std = [
 	"pallet-timestamp/std",
 	"pallet-xcm/std",
 	"parachain-info/std",
+	"parachains-common/std",
 	"polkadot-parachain-primitives/std",
 	"sp-consensus-aura/std",
 	"sp-core/std",
 	"sp-io/std",
 	"sp-runtime/std",
 	"xcm-executor/std",
+	"xcm-runtime-apis/std",
 	"xcm/std",
 ]
diff --git a/cumulus/parachains/runtimes/test-utils/src/test_cases.rs b/cumulus/parachains/runtimes/test-utils/src/test_cases.rs
index a66163154cf696bf4f0708075e9cf853417d4700..6bdf3ef09d1b8c9b345d77e54a084b166d98dc69 100644
--- a/cumulus/parachains/runtimes/test-utils/src/test_cases.rs
+++ b/cumulus/parachains/runtimes/test-utils/src/test_cases.rs
@@ -18,7 +18,15 @@
 
 use crate::{AccountIdOf, CollatorSessionKeys, ExtBuilder, ValidatorIdOf};
 use codec::Encode;
-use frame_support::{assert_ok, traits::Get};
+use frame_support::{
+	assert_ok,
+	traits::{Get, OriginTrait},
+};
+use parachains_common::AccountId;
+use sp_runtime::traits::{Block as BlockT, StaticLookup};
+use xcm_runtime_apis::fees::{
+	runtime_decl_for_xcm_payment_api::XcmPaymentApiV1, Error as XcmPaymentApiError,
+};
 
 type RuntimeHelper<Runtime, AllPalletsWithoutSystem = ()> =
 	crate::RuntimeHelper<Runtime, AllPalletsWithoutSystem>;
@@ -128,3 +136,60 @@ pub fn set_storage_keys_by_governance_works<Runtime>(
 		assert_storage();
 	});
 }
+
+pub fn xcm_payment_api_with_native_token_works<Runtime, RuntimeCall, RuntimeOrigin, Block>()
+where
+	Runtime: XcmPaymentApiV1<Block>
+		+ frame_system::Config<RuntimeOrigin = RuntimeOrigin, AccountId = AccountId>
+		+ pallet_balances::Config<Balance = u128>
+		+ pallet_session::Config
+		+ pallet_xcm::Config
+		+ parachain_info::Config
+		+ pallet_collator_selection::Config
+		+ cumulus_pallet_parachain_system::Config
+		+ cumulus_pallet_xcmp_queue::Config
+		+ pallet_timestamp::Config,
+	ValidatorIdOf<Runtime>: From<AccountIdOf<Runtime>>,
+	RuntimeOrigin: OriginTrait<AccountId = <Runtime as frame_system::Config>::AccountId>,
+	<<Runtime as frame_system::Config>::Lookup as StaticLookup>::Source:
+		From<<Runtime as frame_system::Config>::AccountId>,
+	Block: BlockT,
+{
+	use xcm::prelude::*;
+	ExtBuilder::<Runtime>::default().build().execute_with(|| {
+		let transfer_amount = 100u128;
+		let xcm_to_weigh = Xcm::<RuntimeCall>::builder_unsafe()
+			.withdraw_asset((Here, transfer_amount))
+			.buy_execution((Here, transfer_amount), Unlimited)
+			.deposit_asset(AllCounted(1), [1u8; 32])
+			.build();
+		let versioned_xcm_to_weigh = VersionedXcm::from(xcm_to_weigh.clone().into());
+
+		// We first try calling it with a lower XCM version.
+		let lower_version_xcm_to_weigh =
+			versioned_xcm_to_weigh.clone().into_version(XCM_VERSION - 1).unwrap();
+		let xcm_weight = Runtime::query_xcm_weight(lower_version_xcm_to_weigh);
+		assert!(xcm_weight.is_ok());
+		let native_token: Location = Parent.into();
+		let native_token_versioned = VersionedAssetId::from(AssetId(native_token));
+		let lower_version_native_token =
+			native_token_versioned.clone().into_version(XCM_VERSION - 1).unwrap();
+		let execution_fees =
+			Runtime::query_weight_to_asset_fee(xcm_weight.unwrap(), lower_version_native_token);
+		assert!(execution_fees.is_ok());
+
+		// Now we call it with the latest version.
+		let xcm_weight = Runtime::query_xcm_weight(versioned_xcm_to_weigh);
+		assert!(xcm_weight.is_ok());
+		let execution_fees =
+			Runtime::query_weight_to_asset_fee(xcm_weight.unwrap(), native_token_versioned);
+		assert!(execution_fees.is_ok());
+
+		// If we call it with anything other than the native token it will error.
+		let non_existent_token: Location = Here.into();
+		let non_existent_token_versioned = VersionedAssetId::from(AssetId(non_existent_token));
+		let execution_fees =
+			Runtime::query_weight_to_asset_fee(xcm_weight.unwrap(), non_existent_token_versioned);
+		assert_eq!(execution_fees, Err(XcmPaymentApiError::AssetNotFound));
+	});
+}
diff --git a/polkadot/xcm/xcm-runtime-apis/tests/fee_estimation.rs b/polkadot/xcm/xcm-runtime-apis/tests/fee_estimation.rs
index 2d14b4e571c6724574d0751a12ea1f470c125da5..c3046b134d1fe041fcb770a642104b240d35ef55 100644
--- a/polkadot/xcm/xcm-runtime-apis/tests/fee_estimation.rs
+++ b/polkadot/xcm/xcm-runtime-apis/tests/fee_estimation.rs
@@ -353,3 +353,26 @@ fn dry_run_xcm() {
 		);
 	});
 }
+
+#[test]
+fn calling_payment_api_with_a_lower_version_works() {
+	let transfer_amount = 100u128;
+	let xcm_to_weigh = Xcm::<RuntimeCall>::builder_unsafe()
+		.withdraw_asset((Here, transfer_amount))
+		.buy_execution((Here, transfer_amount), Unlimited)
+		.deposit_asset(AllCounted(1), [1u8; 32])
+		.build();
+	let versioned_xcm_to_weigh = VersionedXcm::from(xcm_to_weigh.clone().into());
+	let lower_version_xcm_to_weigh = versioned_xcm_to_weigh.into_version(XCM_VERSION - 1).unwrap();
+	let client = TestClient;
+	let runtime_api = client.runtime_api();
+	let xcm_weight =
+		runtime_api.query_xcm_weight(H256::zero(), lower_version_xcm_to_weigh).unwrap();
+	assert!(xcm_weight.is_ok());
+	let native_token = VersionedAssetId::from(AssetId(Here.into()));
+	let lower_version_native_token = native_token.into_version(XCM_VERSION - 1).unwrap();
+	let execution_fees = runtime_api
+		.query_weight_to_asset_fee(H256::zero(), xcm_weight.unwrap(), lower_version_native_token)
+		.unwrap();
+	assert!(execution_fees.is_ok());
+}
diff --git a/polkadot/xcm/xcm-runtime-apis/tests/mock.rs b/polkadot/xcm/xcm-runtime-apis/tests/mock.rs
index f0a5be908f693b0cfdc5a41d71559728a06d73fc..fb5d1ae7c0e5ad92a77f201869ac9b4e5da09698 100644
--- a/polkadot/xcm/xcm-runtime-apis/tests/mock.rs
+++ b/polkadot/xcm/xcm-runtime-apis/tests/mock.rs
@@ -453,7 +453,8 @@ sp_api::mock_impl_runtime_apis! {
 		}
 
 		fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result<u128, XcmPaymentApiError> {
-			match asset.try_as::<AssetId>() {
+			let latest_asset_id: Result<AssetId, ()> = asset.clone().try_into();
+			match latest_asset_id {
 				Ok(asset_id) if asset_id.0 == HereLocation::get() => {
 					Ok(WeightToFee::weight_to_fee(&weight))
 				},
diff --git a/prdoc/pr_6459.prdoc b/prdoc/pr_6459.prdoc
new file mode 100644
index 0000000000000000000000000000000000000000..592ba4c6b29d0863405f3d5547ab2ce1040e3dd6
--- /dev/null
+++ b/prdoc/pr_6459.prdoc
@@ -0,0 +1,22 @@
+# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0
+# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json
+
+title: Fix version conversion in XcmPaymentApi::query_weight_to_asset_fee.
+
+doc:
+  - audience: Runtime Dev
+    description: |
+      The `query_weight_to_asset_fee` function of the `XcmPaymentApi` was trying
+      to convert versions in the wrong way.
+      This resulted in all calls made with lower versions failing.
+      The version conversion is now done correctly and these same calls will now succeed.
+
+crates:
+  - name: asset-hub-westend-runtime
+    bump: patch
+  - name: asset-hub-rococo-runtime
+    bump: patch
+  - name: xcm-runtime-apis
+    bump: patch
+  - name: assets-common
+    bump: patch