diff --git a/api/Cargo.toml b/api/Cargo.toml
index ec834e38c..6a576bd9a 100644
--- a/api/Cargo.toml
+++ b/api/Cargo.toml
@@ -10,6 +10,7 @@ grin_chain = { path = "../chain" }
 grin_pool = { path = "../pool" }
 grin_store = { path = "../store" }
 grin_util = { path = "../util" }
+grin_p2p = { path = "../p2p" }
 hyper = "~0.10.6"
 slog = { version = "^2.0.12", features = ["max_level_trace", "release_max_level_trace"] }
 iron = "~0.5.1"
diff --git a/api/src/handlers.rs b/api/src/handlers.rs
index f077c38b2..3754894ae 100644
--- a/api/src/handlers.rs
+++ b/api/src/handlers.rs
@@ -27,6 +27,7 @@ use chain;
 use core::core::Transaction;
 use core::ser;
 use pool;
+use p2p;
 use rest::*;
 use util::secp::pedersen::Commitment;
 use types::*;
@@ -146,6 +147,32 @@ impl Handler for SumTreeHandler {
 	}
 }
 
+pub struct PeersAllHandler {
+	pub peer_store: Arc<p2p::PeerStore>,
+}
+
+impl Handler for PeersAllHandler {
+	fn handle(&self, _req: &mut Request) -> IronResult<Response> {
+		let peers = &self.peer_store.all_peers();
+		json_response(&peers)
+	}
+}
+
+pub struct PeersConnectedHandler {
+	pub p2p_server: Arc<p2p::Server>,
+}
+
+impl Handler for PeersConnectedHandler {
+	fn handle(&self, _req: &mut Request) -> IronResult<Response> {
+		let mut peers = vec![];
+		for p in &self.p2p_server.all_peers() {
+			let peer_info = p.info.clone();
+			peers.push(peer_info);
+		}
+		json_response(&peers)
+	}
+}
+
 // Chain handler. Get the head details.
 // GET /v1/chain
 pub struct ChainHandler {
@@ -251,6 +278,8 @@ pub fn start_rest_apis<T>(
 	addr: String,
 	chain: Arc<chain::Chain>,
 	tx_pool: Arc<RwLock<pool::TransactionPool<T>>>,
+	p2p_server: Arc<p2p::Server>,
+	peer_store: Arc<p2p::PeerStore>,
 ) where
 	T: pool::BlockChain + Send + Sync + 'static,
 {
@@ -271,13 +300,21 @@ pub fn start_rest_apis<T>(
 		let pool_push_handler = PoolPushHandler {
 			tx_pool: tx_pool.clone(),
 		};
+		let peers_all_handler = PeersAllHandler {
+			peer_store: peer_store.clone(),
+		};
+		let peers_connected_handler = PeersConnectedHandler {
+			p2p_server: p2p_server.clone(),
+		};
 
 		let router = router!(
 			chain_tip: get "/chain" => chain_tip_handler,
 			chain_utxos: get "/chain/utxos" => utxo_handler,
 			sumtree_roots: get "/sumtrees/*" => sumtree_handler,
-      pool_info: get "/pool" => pool_info_handler,
-      pool_push: post "/pool/push" => pool_push_handler,
+			pool_info: get "/pool" => pool_info_handler,
+			pool_push: post "/pool/push" => pool_push_handler,
+			peers_all: get "/peers/all" => peers_all_handler,
+			peers_connected: get "/peers/connected" => peers_connected_handler,
 		);
 
 		let mut apis = ApiServer::new("/v1".to_string());
diff --git a/api/src/lib.rs b/api/src/lib.rs
index 4afd613b9..fbf0c13f7 100644
--- a/api/src/lib.rs
+++ b/api/src/lib.rs
@@ -15,6 +15,7 @@
 extern crate grin_chain as chain;
 extern crate grin_core as core;
 extern crate grin_pool as pool;
+extern crate grin_p2p as p2p;
 extern crate grin_store as store;
 extern crate grin_util as util;
 
diff --git a/grin/src/server.rs b/grin/src/server.rs
index a32f842ae..d73b86102 100644
--- a/grin/src/server.rs
+++ b/grin/src/server.rs
@@ -150,6 +150,8 @@ impl Server {
 			config.api_http_addr.clone(),
 			shared_chain.clone(),
 			tx_pool.clone(),
+			p2p_server.clone(),
+			peer_store.clone(),
 		);
 
 		warn!(LOGGER, "Grin server started.");
diff --git a/p2p/src/server.rs b/p2p/src/server.rs
index 1667a50d1..2023c9b31 100644
--- a/p2p/src/server.rs
+++ b/p2p/src/server.rs
@@ -207,6 +207,10 @@ impl Server {
 		addr.ip() == self.config.host && addr.port() == self.config.port
 	}
 
+	pub fn all_peers(&self) -> Vec<Arc<Peer>> {
+		self.peers.read().unwrap().clone()
+	}
+
 	/// Get a peer we're connected to by address.
 	pub fn get_peer(&self, addr: SocketAddr) -> Option<Arc<Peer>> {
 		for p in self.peers.read().unwrap().deref() {
diff --git a/p2p/src/store.rs b/p2p/src/store.rs
index bc7f64722..91d77e08a 100644
--- a/p2p/src/store.rs
+++ b/p2p/src/store.rs
@@ -28,16 +28,16 @@ const PEER_PREFIX: u8 = 'p' as u8;
 
 /// Types of messages
 enum_from_primitive! {
-  #[derive(Debug, Clone, Copy, PartialEq)]
-  pub enum State {
-	Healthy,
-	Banned,
-	Defunct,
-  }
+	#[derive(Debug, Clone, Copy, PartialEq, Serialize)]
+	pub enum State {
+		Healthy,
+		Banned,
+		Defunct,
+	}
 }
 
 /// Data stored for any given peer we've encountered.
-#[derive(Debug)]
+#[derive(Debug, Serialize)]
 pub struct PeerData {
 	/// Network address of the peer.
 	pub addr: SocketAddr,
@@ -129,6 +129,17 @@ impl PeerStore {
 		peers
 	}
 
+	/// List all known peers (for the /v1/peers api endpoint)
+	pub fn all_peers(&self) -> Vec<PeerData> {
+		let peers_iter = self.db
+			.iter::<PeerData>(&to_key(PEER_PREFIX, &mut "".to_string().into_bytes()));
+			let mut peers = vec![];
+			for p in peers_iter {
+				peers.push(p);
+			}
+			peers
+	}
+
 	/// Convenience method to load a peer data, update its status and save it
 	/// back.
 	pub fn update_state(&self, peer_addr: SocketAddr, new_state: State) -> Result<(), Error> {
diff --git a/p2p/src/types.rs b/p2p/src/types.rs
index 7c7942088..8dc5276e8 100644
--- a/p2p/src/types.rs
+++ b/p2p/src/types.rs
@@ -100,7 +100,7 @@ bitflags! {
 }
 
 /// General information about a connected peer that's useful to other modules.
-#[derive(Debug)]
+#[derive(Clone, Debug, Serialize)]
 pub struct PeerInfo {
 	pub capabilities: Capabilities,
 	pub user_agent: String,