diff --git a/substrate/client/rpc-spec-v2/src/archive/api.rs b/substrate/client/rpc-spec-v2/src/archive/api.rs
new file mode 100644
index 0000000000000000000000000000000000000000..ca94779c887cba2dcfae25eb46113ec343a51746
--- /dev/null
+++ b/substrate/client/rpc-spec-v2/src/archive/api.rs
@@ -0,0 +1,56 @@
+// This file is part of Substrate.
+
+// Copyright (C) Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+//! API trait of the archive methods.
+
+use jsonrpsee::{core::RpcResult, proc_macros::rpc};
+
+#[rpc(client, server)]
+pub trait ArchiveApi<Hash> {
+	/// Retrieves the body (list of transactions) of a given block hash.
+	///
+	/// Returns an array of strings containing the hexadecimal-encoded SCALE-codec-encoded
+	/// transactions in that block. If no block with that hash is found, null.
+	///
+	/// # Unstable
+	///
+	/// This method is unstable and subject to change in the future.
+	#[method(name = "archive_unstable_body")]
+	fn archive_unstable_body(&self, hash: Hash) -> RpcResult<Option<Vec<String>>>;
+
+	/// Get the chain's genesis hash.
+	///
+	/// Returns a string containing the hexadecimal-encoded hash of the genesis block of the chain.
+	///
+	/// # Unstable
+	///
+	/// This method is unstable and subject to change in the future.
+	#[method(name = "archive_unstable_genesisHash")]
+	fn archive_unstable_genesis_hash(&self) -> RpcResult<String>;
+
+	/// Get the block's header.
+	///
+	/// Returns a string containing the hexadecimal-encoded SCALE-codec encoding header of the
+	/// block.
+	///
+	/// # Unstable
+	///
+	/// This method is unstable and subject to change in the future.
+	#[method(name = "archive_unstable_header")]
+	fn archive_unstable_header(&self, hash: Hash) -> RpcResult<Option<String>>;
+}
diff --git a/substrate/client/rpc-spec-v2/src/archive/archive.rs b/substrate/client/rpc-spec-v2/src/archive/archive.rs
new file mode 100644
index 0000000000000000000000000000000000000000..4fb2e5671d30044f6e609f34d5453ffce8005b84
--- /dev/null
+++ b/substrate/client/rpc-spec-v2/src/archive/archive.rs
@@ -0,0 +1,86 @@
+// This file is part of Substrate.
+
+// Copyright (C) Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+//! API implementation for `archive`.
+
+use super::ArchiveApiServer;
+use crate::chain_head::hex_string;
+use codec::Encode;
+use jsonrpsee::core::{async_trait, RpcResult};
+use sc_client_api::{Backend, BlockBackend, BlockchainEvents, ExecutorProvider, StorageProvider};
+use sp_api::CallApiAt;
+use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata};
+use sp_runtime::traits::Block as BlockT;
+use std::{marker::PhantomData, sync::Arc};
+
+/// An API for archive RPC calls.
+pub struct Archive<BE: Backend<Block>, Block: BlockT, Client> {
+	/// Substrate client.
+	client: Arc<Client>,
+	/// The hexadecimal encoded hash of the genesis block.
+	genesis_hash: String,
+	/// Phantom member to pin the block type.
+	_phantom: PhantomData<(Block, BE)>,
+}
+
+impl<BE: Backend<Block>, Block: BlockT, Client> Archive<BE, Block, Client> {
+	/// Create a new [`Archive`].
+	pub fn new<GenesisHash: AsRef<[u8]>>(client: Arc<Client>, genesis_hash: GenesisHash) -> Self {
+		let genesis_hash = hex_string(&genesis_hash.as_ref());
+		Self { client, genesis_hash, _phantom: PhantomData }
+	}
+}
+
+#[async_trait]
+impl<BE, Block, Client> ArchiveApiServer<Block::Hash> for Archive<BE, Block, Client>
+where
+	Block: BlockT + 'static,
+	Block::Header: Unpin,
+	BE: Backend<Block> + 'static,
+	Client: BlockBackend<Block>
+		+ ExecutorProvider<Block>
+		+ HeaderBackend<Block>
+		+ HeaderMetadata<Block, Error = BlockChainError>
+		+ BlockchainEvents<Block>
+		+ CallApiAt<Block>
+		+ StorageProvider<Block, BE>
+		+ 'static,
+{
+	fn archive_unstable_body(&self, hash: Block::Hash) -> RpcResult<Option<Vec<String>>> {
+		let Ok(Some(signed_block)) = self.client.block(hash) else { return Ok(None) };
+
+		let extrinsics = signed_block
+			.block
+			.extrinsics()
+			.iter()
+			.map(|extrinsic| hex_string(&extrinsic.encode()))
+			.collect();
+
+		Ok(Some(extrinsics))
+	}
+
+	fn archive_unstable_genesis_hash(&self) -> RpcResult<String> {
+		Ok(self.genesis_hash.clone())
+	}
+
+	fn archive_unstable_header(&self, hash: Block::Hash) -> RpcResult<Option<String>> {
+		let Ok(Some(header)) = self.client.header(hash) else { return Ok(None) };
+
+		Ok(Some(hex_string(&header.encode())))
+	}
+}
diff --git a/substrate/client/rpc-spec-v2/src/archive/mod.rs b/substrate/client/rpc-spec-v2/src/archive/mod.rs
new file mode 100644
index 0000000000000000000000000000000000000000..767f658ecd7537074be16f9d72db97821f743cca
--- /dev/null
+++ b/substrate/client/rpc-spec-v2/src/archive/mod.rs
@@ -0,0 +1,31 @@
+// This file is part of Substrate.
+
+// Copyright (C) Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+//! Substrate archive API.
+//!
+//! # Note
+//!
+//! Methods are prefixed by `archive`.
+
+#[cfg(test)]
+mod tests;
+
+pub mod api;
+pub mod archive;
+
+pub use api::ArchiveApiServer;
diff --git a/substrate/client/rpc-spec-v2/src/archive/tests.rs b/substrate/client/rpc-spec-v2/src/archive/tests.rs
new file mode 100644
index 0000000000000000000000000000000000000000..bc75fc749acc06f6e9638a0d7ff29696d1f64ee3
--- /dev/null
+++ b/substrate/client/rpc-spec-v2/src/archive/tests.rs
@@ -0,0 +1,113 @@
+// This file is part of Substrate.
+
+// Copyright (C) Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+use crate::chain_head::hex_string;
+
+use super::{archive::Archive, *};
+
+use codec::{Decode, Encode};
+use jsonrpsee::{types::EmptyServerParams as EmptyParams, RpcModule};
+use sc_block_builder::BlockBuilderProvider;
+
+use sp_consensus::BlockOrigin;
+use std::sync::Arc;
+use substrate_test_runtime_client::{
+	prelude::*, runtime, Backend, BlockBuilderExt, Client, ClientBlockImportExt,
+};
+
+const CHAIN_GENESIS: [u8; 32] = [0; 32];
+const INVALID_HASH: [u8; 32] = [1; 32];
+
+type Header = substrate_test_runtime_client::runtime::Header;
+type Block = substrate_test_runtime_client::runtime::Block;
+
+fn setup_api() -> (Arc<Client<Backend>>, RpcModule<Archive<Backend, Block, Client<Backend>>>) {
+	let builder = TestClientBuilder::new();
+	let client = Arc::new(builder.build());
+
+	let api = Archive::new(client.clone(), CHAIN_GENESIS).into_rpc();
+
+	(client, api)
+}
+
+#[tokio::test]
+async fn archive_genesis() {
+	let (_client, api) = setup_api();
+
+	let genesis: String =
+		api.call("archive_unstable_genesisHash", EmptyParams::new()).await.unwrap();
+	assert_eq!(genesis, hex_string(&CHAIN_GENESIS));
+}
+
+#[tokio::test]
+async fn archive_body() {
+	let (mut client, api) = setup_api();
+
+	// Invalid block hash.
+	let invalid_hash = hex_string(&INVALID_HASH);
+	let res: Option<Vec<String>> = api.call("archive_unstable_body", [invalid_hash]).await.unwrap();
+	assert!(res.is_none());
+
+	// Import a new block with an extrinsic.
+	let mut builder = client.new_block(Default::default()).unwrap();
+	builder
+		.push_transfer(runtime::Transfer {
+			from: AccountKeyring::Alice.into(),
+			to: AccountKeyring::Ferdie.into(),
+			amount: 42,
+			nonce: 0,
+		})
+		.unwrap();
+	let block = builder.build().unwrap().block;
+	let block_hash = format!("{:?}", block.header.hash());
+	client.import(BlockOrigin::Own, block.clone()).await.unwrap();
+
+	let expected_tx = hex_string(&block.extrinsics[0].encode());
+
+	let body: Vec<String> = api.call("archive_unstable_body", [block_hash]).await.unwrap();
+	assert_eq!(vec![expected_tx], body);
+}
+
+#[tokio::test]
+async fn archive_header() {
+	let (mut client, api) = setup_api();
+
+	// Invalid block hash.
+	let invalid_hash = hex_string(&INVALID_HASH);
+	let res: Option<String> = api.call("archive_unstable_header", [invalid_hash]).await.unwrap();
+	assert!(res.is_none());
+
+	// Import a new block with an extrinsic.
+	let mut builder = client.new_block(Default::default()).unwrap();
+	builder
+		.push_transfer(runtime::Transfer {
+			from: AccountKeyring::Alice.into(),
+			to: AccountKeyring::Ferdie.into(),
+			amount: 42,
+			nonce: 0,
+		})
+		.unwrap();
+	let block = builder.build().unwrap().block;
+	let block_hash = format!("{:?}", block.header.hash());
+	client.import(BlockOrigin::Own, block.clone()).await.unwrap();
+
+	let header: String = api.call("archive_unstable_header", [block_hash]).await.unwrap();
+	let bytes = array_bytes::hex2bytes(&header).unwrap();
+	let header: Header = Decode::decode(&mut &bytes[..]).unwrap();
+	assert_eq!(header, block.header);
+}
diff --git a/substrate/client/rpc-spec-v2/src/lib.rs b/substrate/client/rpc-spec-v2/src/lib.rs
index 7c22ef5d523189f5a2d49b150c786976bf64c5a8..9a455c5984a5f758c7b0b274cdf0c89be2685163 100644
--- a/substrate/client/rpc-spec-v2/src/lib.rs
+++ b/substrate/client/rpc-spec-v2/src/lib.rs
@@ -23,6 +23,7 @@
 #![warn(missing_docs)]
 #![deny(unused_crate_dependencies)]
 
+pub mod archive;
 pub mod chain_head;
 pub mod chain_spec;
 pub mod transaction;