diff --git a/Cargo.lock b/Cargo.lock
index e0a7710d..3e6508d3 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -398,6 +398,29 @@ name = "dtoa"
 version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "easy-jsonrpc"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "easy-jsonrpc-proc-macro 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "jsonrpc-core 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "easy-jsonrpc-proc-macro"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "encode_unicode"
 version = "0.3.5"
@@ -530,7 +553,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 [[package]]
 name = "grin_api"
 version = "1.1.0"
-source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#fd077a489d7dd1a465dcf231eddc9fcd30c4ba43"
+source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#1b3eaba3025f92770ba468de9e77ebd1e4a660cd"
 dependencies = [
  "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -563,6 +586,7 @@ dependencies = [
 name = "grin_apiwallet"
 version = "1.1.0"
 dependencies = [
+ "easy-jsonrpc 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "grin_api 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)",
@@ -570,17 +594,20 @@ dependencies = [
  "grin_core 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)",
  "grin_keychain 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)",
  "grin_libwallet 1.1.0",
+ "grin_refwallet 1.1.0",
  "grin_store 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)",
  "grin_util 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)",
  "grin_wallet_config 1.1.0",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "uuid 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "grin_chain"
 version = "1.1.0"
-source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#fd077a489d7dd1a465dcf231eddc9fcd30c4ba43"
+source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#1b3eaba3025f92770ba468de9e77ebd1e4a660cd"
 dependencies = [
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -603,7 +630,7 @@ dependencies = [
 [[package]]
 name = "grin_core"
 version = "1.1.0"
-source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#fd077a489d7dd1a465dcf231eddc9fcd30c4ba43"
+source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#1b3eaba3025f92770ba468de9e77ebd1e4a660cd"
 dependencies = [
  "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -629,7 +656,7 @@ dependencies = [
 [[package]]
 name = "grin_keychain"
 version = "1.1.0"
-source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#fd077a489d7dd1a465dcf231eddc9fcd30c4ba43"
+source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#1b3eaba3025f92770ba468de9e77ebd1e4a660cd"
 dependencies = [
  "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -672,7 +699,7 @@ dependencies = [
 [[package]]
 name = "grin_p2p"
 version = "1.1.0"
-source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#fd077a489d7dd1a465dcf231eddc9fcd30c4ba43"
+source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#1b3eaba3025f92770ba468de9e77ebd1e4a660cd"
 dependencies = [
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -692,7 +719,7 @@ dependencies = [
 [[package]]
 name = "grin_pool"
 version = "1.1.0"
-source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#fd077a489d7dd1a465dcf231eddc9fcd30c4ba43"
+source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#1b3eaba3025f92770ba468de9e77ebd1e4a660cd"
 dependencies = [
  "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
  "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -759,7 +786,7 @@ dependencies = [
 [[package]]
 name = "grin_store"
 version = "1.1.0"
-source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#fd077a489d7dd1a465dcf231eddc9fcd30c4ba43"
+source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#1b3eaba3025f92770ba468de9e77ebd1e4a660cd"
 dependencies = [
  "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "croaring 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -779,7 +806,7 @@ dependencies = [
 [[package]]
 name = "grin_util"
 version = "1.1.0"
-source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#fd077a489d7dd1a465dcf231eddc9fcd30c4ba43"
+source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#1b3eaba3025f92770ba468de9e77ebd1e4a660cd"
 dependencies = [
  "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -853,6 +880,14 @@ dependencies = [
  "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "heck"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "hmac"
 version = "0.6.3"
@@ -958,6 +993,18 @@ name = "itoa"
 version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "jsonrpc-core"
+version = "10.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "kernel32-sys"
 version = "0.2.2"
@@ -1782,6 +1829,14 @@ dependencies = [
  "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "remove_dir_all"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "ring"
 version = "0.13.5"
@@ -2035,6 +2090,19 @@ dependencies = [
  "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "tempfile"
+version = "3.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)",
+ "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "term"
 version = "0.5.1"
@@ -2375,6 +2443,11 @@ dependencies = [
  "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "unicode-segmentation"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "unicode-width"
 version = "0.1.5"
@@ -2622,6 +2695,8 @@ dependencies = [
 "checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90"
 "checksum dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901"
 "checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd"
+"checksum easy-jsonrpc 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2f0d8eaadf5a9ed73697761ad586140c40aa0837fb5b141a2b04ee9c07eacbfe"
+"checksum easy-jsonrpc-proc-macro 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b50f53cc7025979b06da8fde906f948f0fa4665bf840043f4de1e25acee53c97"
 "checksum encode_unicode 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "90b2c9496c001e8cb61827acdefad780795c42264c137744cae6f7d9e3450abd"
 "checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180"
 "checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38"
@@ -2649,6 +2724,7 @@ dependencies = [
 "checksum grin_store 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)" = "<none>"
 "checksum grin_util 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)" = "<none>"
 "checksum h2 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ddb2b25a33e231484694267af28fec74ac63b5ccf51ee2065a5e313b834d836e"
+"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
 "checksum hmac 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "733e1b3ac906631ca01ebb577e9bb0f5e37a454032b9036b5eaea4013ed6f99a"
 "checksum http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "fe67e3678f2827030e89cc4b9e7ecd16d52f132c0b940ab5005f88e821500f6a"
 "checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83"
@@ -2659,6 +2735,7 @@ dependencies = [
 "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d"
 "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08"
 "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
+"checksum jsonrpc-core 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dc15eef5f8b6bef5ac5f7440a957ff95d036e2f98706947741bfc93d1976db4c"
 "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
 "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
 "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
@@ -2750,6 +2827,7 @@ dependencies = [
 "checksum redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe5204c3a17e97dde73f285d49be585df59ed84b50a872baf416e73b62c3828"
 "checksum regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53ee8cfdddb2e0291adfb9f13d31d3bbe0a03c9a402c01b1e24188d86c35b24f"
 "checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861"
+"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5"
 "checksum ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2c4db68a2e35f3497146b7e4563df7d4773a2433230c5e4b448328e31740458a"
 "checksum ripemd160 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "482aa56cc68aaeccdaaff1cc5a72c247da8bbad3beb174ca5741f274c22883fb"
 "checksum rpassword 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d37473170aedbe66ffa3ad3726939ba677d83c646ad4fd99e5b4bc38712f45ec"
@@ -2784,6 +2862,7 @@ dependencies = [
 "checksum supercow 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "171758edb47aa306a78dfa4ab9aeb5167405bd4e3dc2b64e88f6a84bbe98bd63"
 "checksum syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)" = "525bd55255f03c816e5d7f615587bd13030c7103354fadb104993dcee6a788ec"
 "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
+"checksum tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b86c784c88d98c801132806dadd3819ed29d8600836c4088e855cdf3e178ed8a"
 "checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561"
 "checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f"
 "checksum terminfo 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8e51065bafd2abe106b6036483b69d1741f4a1ec56ce8a2378de341637de689e"
@@ -2817,6 +2896,7 @@ dependencies = [
 "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
 "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
 "checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426"
+"checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1"
 "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
 "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
 "checksum unsafe-any 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f30360d7979f5e9c6e6cea48af192ea8fab4afb3cf72597154b8f08935bc9c7f"
diff --git a/apiwallet/Cargo.toml b/apiwallet/Cargo.toml
index 236b0208..a9a33833 100644
--- a/apiwallet/Cargo.toml
+++ b/apiwallet/Cargo.toml
@@ -15,6 +15,7 @@ failure = "0.1"
 failure_derive = "0.1"
 log = "0.4"
 uuid = { version = "0.6", features = ["serde", "v4"] }
+easy-jsonrpc = "0.4.1"
 
 grin_libwallet = { path = "../libwallet", version = "1.1.0" }
 grin_wallet_config = { path = "../config", version = "1.1.0" }
@@ -25,3 +26,8 @@ grin_chain = { git = "https://github.com/mimblewimble/grin", branch = "milestone
 grin_util = { git = "https://github.com/mimblewimble/grin", branch = "milestone/1.1.0" }
 grin_api = { git = "https://github.com/mimblewimble/grin", branch = "milestone/1.1.0" }
 grin_store = { git = "https://github.com/mimblewimble/grin", branch = "milestone/1.1.0" }
+
+[dev-dependencies]
+grin_refwallet = { path = "../refwallet", version = "1.1.0" }
+serde_json = "1"
+tempfile = "3.0.7"
diff --git a/apiwallet/src/api.rs b/apiwallet/src/api.rs
index a9141683..8f6307e9 100644
--- a/apiwallet/src/api.rs
+++ b/apiwallet/src/api.rs
@@ -37,19 +37,495 @@ use uuid::Uuid;
 use crate::core::core::hash::Hashed;
 use crate::core::core::Transaction;
 use crate::core::ser;
-use crate::libwallet::internal::{keys, tx, updater};
 use crate::keychain::{Identifier, Keychain};
+use crate::libwallet::internal::{keys, tx, updater};
 use crate::libwallet::slate::Slate;
 use crate::libwallet::types::{
 	AcctPathMapping, BlockFees, CbData, NodeClient, OutputData, OutputLockFn, TxLogEntry,
 	TxLogEntryType, TxWrapper, WalletBackend, WalletInfo,
 };
+use crate::libwallet::{Error, ErrorKind};
 use crate::util;
 use crate::util::secp::{pedersen, ContextFlag, Secp256k1};
-use crate::libwallet::{Error, ErrorKind};
+use easy_jsonrpc;
 
 const USER_MESSAGE_MAX_LEN: usize = 256;
 
+/// Public definition used to generate jsonrpc api for APIOwner.
+#[easy_jsonrpc::rpc]
+pub trait OwnerApi {
+	/**
+	Networked version of [APIOwner::accounts](struct.APIOwner.html#method.accounts).
+
+	# Json rpc example
+
+	```
+	# grin_apiwallet::doctest_helper_json_rpc_owner_assert_response!(
+	{
+		"jsonrpc": "2.0",
+		"method": "accounts",
+		"params": [],
+		"id": 1
+	},
+	{
+		"jsonrpc": "2.0",
+		"result": {
+			"Ok": [
+				{
+					"label": "default",
+					"path": "0200000000000000000000000000000000"
+				}
+			]
+		},
+		"id": 1
+	}
+	# );
+	```
+	 */
+	fn accounts(&self) -> Result<Vec<AcctPathMapping>, ErrorKind>;
+
+	/**
+	Networked version of [APIOwner::create_account_path](struct.APIOwner.html#method.create_account_path).
+
+	# Json rpc example
+
+	```
+	# grin_apiwallet::doctest_helper_json_rpc_owner_assert_response!(
+	{
+		"jsonrpc": "2.0",
+		"method": "create_account_path",
+		"params": ["account1"],
+		"id": 1
+	},
+	{
+		"jsonrpc": "2.0",
+		"result": {
+			"Ok": "0200000001000000000000000000000000"
+		},
+		"id": 1
+	}
+	# );
+	```
+	 */
+	fn create_account_path(&self, label: &String) -> Result<Identifier, ErrorKind>;
+
+	/**
+	Networked version of [APIOwner::set_active_account](struct.APIOwner.html#method.set_active_account).
+
+	# Json rpc example
+
+	```
+	# grin_apiwallet::doctest_helper_json_rpc_owner_assert_response!(
+	{
+		"jsonrpc": "2.0",
+		"method": "set_active_account",
+		"params": ["default"],
+		"id": 1
+	},
+	{
+		"jsonrpc": "2.0",
+		"result": {
+			"Ok": null
+		},
+		"id": 1
+	}
+	# );
+	```
+	 */
+	fn set_active_account(&self, label: &String) -> Result<(), ErrorKind>;
+
+	/**
+	Networked version of [APIOwner::retrieve_outputs](struct.APIOwner.html#method.retrieve_outputs).
+
+
+	```
+	# grin_apiwallet::doctest_helper_json_rpc_owner_assert_response!(
+	{
+		"jsonrpc": "2.0",
+		"method": "retrieve_outputs",
+		"params": [false, false, null],
+		"id": 1
+	},
+	{
+		"jsonrpc": "2.0",
+		"result": {
+			"Err": {
+				"CallbackImpl": "Error opening wallet"
+			}
+		},
+		"id": 1
+	}
+	# );
+	```
+	 */
+	fn retrieve_outputs(
+		&self,
+		include_spent: bool,
+		refresh_from_node: bool,
+		tx_id: Option<u32>,
+	) -> Result<(bool, Vec<(OutputData, pedersen::Commitment)>), ErrorKind>;
+
+	/**
+	Networked version of [APIOwner::retrieve_txs](struct.APIOwner.html#method.retrieve_txs).
+
+
+	```
+	# grin_apiwallet::doctest_helper_json_rpc_owner_assert_response!(
+	{
+		"jsonrpc": "2.0",
+		"method": "retrieve_txs",
+		"params": [false, null, null],
+		"id": 1
+	},
+	{
+		"jsonrpc": "2.0",
+		"result": {
+			"Err": {
+				"CallbackImpl": "Error opening wallet"
+			}
+		},
+		"id": 1
+	}
+	# );
+	```
+	 */
+	fn retrieve_txs(
+		&self,
+		refresh_from_node: bool,
+		tx_id: Option<u32>,
+		tx_slate_id: Option<Uuid>,
+	) -> Result<(bool, Vec<TxLogEntry>), ErrorKind>;
+
+	/**
+	Networked version of [APIOwner::retrieve_summary_info](struct.APIOwner.html#method.retrieve_summary_info).
+
+
+	```
+	# grin_apiwallet::doctest_helper_json_rpc_owner_assert_response!(
+	{
+		"jsonrpc": "2.0",
+		"method": "retrieve_summary_info",
+		"params": [false, 1],
+		"id": 1
+	},
+	{
+		"jsonrpc": "2.0",
+		"result": {
+			"Err": {
+				"CallbackImpl": "Error opening wallet"
+			}
+		},
+		"id": 1
+	}
+	# );
+	```
+	 */
+	fn retrieve_summary_info(
+		&self,
+		refresh_from_node: bool,
+		minimum_confirmations: u64,
+	) -> Result<(bool, WalletInfo), ErrorKind>;
+
+	/**
+	Networked version of [APIOwner::estimate_initiate_tx](struct.APIOwner.html#method.estimate_initiate_tx).
+
+
+	```
+	# grin_apiwallet::doctest_helper_json_rpc_owner_assert_response!(
+	{
+		"jsonrpc": "2.0",
+		"method": "estimate_initiate_tx",
+		"params": [null, 0, 0, 10, 0, false],
+		"id": 1
+	},
+	{
+		"jsonrpc": "2.0",
+		"result": {
+			"Err": {
+				"CallbackImpl": "Error opening wallet"
+			}
+		},
+		"id": 1
+	}
+	# );
+	```
+	 */
+	fn estimate_initiate_tx(
+		&self,
+		src_acct_name: Option<String>,
+		amount: u64,
+		minimum_confirmations: u64,
+		max_outputs: usize,
+		num_change_outputs: usize,
+		selection_strategy_is_use_all: bool,
+	) -> Result<(/* total */ u64, /* fee */ u64), ErrorKind>;
+
+	/**
+	Networked version of [APIOwner::finalize_tx](struct.APIOwner.html#method.finalize_tx).
+
+
+	```
+	# grin_apiwallet::doctest_helper_json_rpc_owner_assert_response!(
+	{
+		"jsonrpc": "2.0",
+		"method": "finalize_tx",
+		"params": [{
+			"amount": 0,
+			"fee": 0,
+			"height": 0,
+			"id": "414bad48-3386-4fa7-8483-72384c886ba3",
+			"lock_height": 0,
+			"num_participants": 2,
+			"participant_data": [],
+			"tx": {
+				"body": {
+					"inputs": [],
+					"kernels": [],
+					"outputs": []
+				},
+				"offset": "0000000000000000000000000000000000000000000000000000000000000000"
+			},
+			"version": 1
+		}],
+		"id": 1
+	},
+	{
+		"jsonrpc": "2.0",
+		"result": {
+			"Err": {
+				"CallbackImpl": "Error opening wallet"
+			}
+		},
+		"id": 1
+	}
+	# );
+	```
+	 */
+	fn finalize_tx(&self, slate: Slate) -> Result<Slate, ErrorKind>;
+
+	/**
+	Networked version of [APIOwner::cancel_tx](struct.APIOwner.html#method.cancel_tx).
+
+
+	```
+	# grin_apiwallet::doctest_helper_json_rpc_owner_assert_response!(
+	{
+		"jsonrpc": "2.0",
+		"method": "cancel_tx",
+		"params": [null, null],
+		"id": 1
+	},
+	{
+		"jsonrpc": "2.0",
+		"result": {
+			"Err": {
+				"CallbackImpl": "Error opening wallet"
+			}
+		},
+		"id": 1
+	}
+	# );
+	```
+	 */
+	fn cancel_tx(&self, tx_id: Option<u32>, tx_slate_id: Option<Uuid>) -> Result<(), ErrorKind>;
+
+	/**
+	Networked version of [APIOwner::get_stored_tx](struct.APIOwner.html#method.get_stored_tx).
+
+
+	```
+	# grin_apiwallet::doctest_helper_json_rpc_owner_assert_response!(
+	{
+		"jsonrpc": "2.0",
+		"method": "get_stored_tx",
+		"params": [
+			{
+				"amount_credited": 0,
+				"amount_debited": 0,
+				"confirmation_ts": null,
+				"confirmed": false,
+				"creation_ts": "2019-03-05T20:49:59.444095Z",
+				"fee": null,
+				"id": 10,
+				"messages": null,
+				"num_inputs": 0,
+				"num_outputs": 0,
+				"parent_key_id": "0000000000000000000000000000000000",
+				"stored_tx": null,
+				"tx_slate_id": null,
+				"tx_type": "TxReceived"
+			}
+		],
+		"id": 1
+	},
+	{
+		"jsonrpc": "2.0",
+		"result": {
+			"Ok": null
+		},
+		"id": 1
+	}
+	# );
+	```
+	 */
+	fn get_stored_tx(&self, entry: &TxLogEntry) -> Result<Option<Transaction>, ErrorKind>;
+
+	/**
+	Networked version of [APIOwner::post_tx](struct.APIOwner.html#method.post_tx).
+
+	```no_run
+    # // This test currently fails on travis
+	# grin_apiwallet::doctest_helper_json_rpc_owner_assert_response!(
+	{
+		"jsonrpc": "2.0",
+		"method": "post_tx",
+		"params": [
+			{
+				"body": {
+					"inputs": [],
+					"kernels": [],
+					"outputs": []
+				},
+				"offset": "0000000000000000000000000000000000000000000000000000000000000000"
+			},
+			false
+		],
+		"id": 1
+	},
+	{
+		"jsonrpc": "2.0",
+		"result": {
+			"Err": {
+				"ClientCallback": "Posting transaction to node: Request error: Cannot make request: an error occurred trying to connect: Connection refused (os error 61)"
+			}
+		},
+		"id": 1
+	}
+	# );
+	```
+	 */
+	fn post_tx(&self, tx: &Transaction, fluff: bool) -> Result<(), ErrorKind>;
+
+	/**
+	Networked version of [APIOwner::verify_slate_messages](struct.APIOwner.html#method.verify_slate_messages).
+
+
+	```
+	# grin_apiwallet::doctest_helper_json_rpc_owner_assert_response!(
+	{
+		"jsonrpc": "2.0",
+		"method": "verify_slate_messages",
+		"params": [{
+			"amount": 0,
+			"fee": 0,
+			"height": 0,
+			"id": "414bad48-3386-4fa7-8483-72384c886ba3",
+			"lock_height": 0,
+			"num_participants": 2,
+			"participant_data": [],
+			"tx": {
+				"body": {
+					"inputs": [],
+					"kernels": [],
+					"outputs": []
+				},
+				"offset": "0000000000000000000000000000000000000000000000000000000000000000"
+			},
+			"version": 1
+		}],
+		"id": 1
+	},
+	{
+		"jsonrpc": "2.0",
+		"result": {
+			 "Ok": null
+		},
+		"id": 1
+	}
+	# );
+	```
+	 */
+	fn verify_slate_messages(&self, slate: &Slate) -> Result<(), ErrorKind>;
+
+	/**
+	Networked version of [APIOwner::restore](struct.APIOwner.html#method.restore).
+
+
+	```
+	# grin_apiwallet::doctest_helper_json_rpc_owner_assert_response!(
+	{
+		"jsonrpc": "2.0",
+		"method": "restore",
+		"params": [],
+		"id": 1
+	},
+	{
+		"jsonrpc": "2.0",
+		"result": {
+			"Err": {
+				"CallbackImpl": "Error opening wallet"
+			}
+		},
+		"id": 1
+	}
+	# );
+	```
+	 */
+	fn restore(&self) -> Result<(), ErrorKind>;
+
+	/**
+	Networked version of [APIOwner::check_repair](struct.APIOwner.html#method.check_repair).
+
+
+	```
+	# grin_apiwallet::doctest_helper_json_rpc_owner_assert_response!(
+	{
+		"jsonrpc": "2.0",
+		"method": "check_repair",
+		"params": [false],
+		"id": 1
+	},
+	{
+		"jsonrpc": "2.0",
+		"result": {
+			"Err": {
+				"CallbackImpl": "Error opening wallet"
+			}
+		},
+		"id": 1
+	}
+	# );
+	```
+	 */
+	fn check_repair(&self, delete_unconfirmed: bool) -> Result<(), ErrorKind>;
+
+	/**
+	Networked version of [APIOwner::node_height](struct.APIOwner.html#method.node_height).
+
+
+	```
+	# grin_apiwallet::doctest_helper_json_rpc_owner_assert_response!(
+	{
+		"jsonrpc": "2.0",
+		"method": "node_height",
+		"params": [],
+		"id": 1
+	},
+	{
+		"jsonrpc": "2.0",
+		"result": {
+			"Err": {
+				"CallbackImpl": "Error opening wallet"
+			}
+		},
+		"id": 1
+	}
+	# );
+	```
+	 */
+	fn node_height(&self) -> Result<(u64, bool), ErrorKind>;
+}
+
 /// Functions intended for use by the owner (e.g. master seed holder) of the wallet.
 pub struct APIOwner<W: ?Sized, C, K>
 where
@@ -83,7 +559,7 @@ where
 	/// [`WalletBackend`](../types/trait.WalletBackend.html) trait.
 	///
 	/// # Returns
-	/// * An instance of the OwnerAPI holding a reference to the provided wallet
+	/// * An instance of the OwnerApi holding a reference to the provided wallet
 	///
 	/// # Example
 	/// ``` ignore
@@ -494,7 +970,7 @@ where
 	/// ```
 
 	pub fn retrieve_summary_info(
-		&mut self,
+		&self,
 		refresh_from_node: bool,
 		minimum_confirmations: u64,
 	) -> Result<(bool, WalletInfo), Error> {
@@ -619,7 +1095,7 @@ where
 	/// ```
 
 	pub fn initiate_tx(
-		&mut self,
+		&self,
 		src_acct_name: Option<&str>,
 		amount: u64,
 		minimum_confirmations: u64,
@@ -706,7 +1182,7 @@ where
 	/// * Total amount to be locked.
 	/// * Transaction fee
 	pub fn estimate_initiate_tx(
-		&mut self,
+		&self,
 		src_acct_name: Option<&str>,
 		amount: u64,
 		minimum_confirmations: u64,
@@ -745,7 +1221,7 @@ where
 
 	/// Lock outputs associated with a given slate/transaction
 	pub fn tx_lock_outputs(
-		&mut self,
+		&self,
 		slate: &Slate,
 		mut lock_fn: OutputLockFn<W, C, K>,
 	) -> Result<(), Error> {
@@ -759,7 +1235,7 @@ where
 	/// sender as well as the private file generate on the first send step.
 	/// Builds the complete transaction and sends it to a grin node for
 	/// propagation.
-	pub fn finalize_tx(&mut self, slate: &mut Slate) -> Result<(), Error> {
+	pub fn finalize_tx(&self, slate: &mut Slate) -> Result<(), Error> {
 		let mut w = self.wallet.lock();
 		w.open_with_credentials()?;
 		let context = w.get_private_context(slate.id.as_bytes())?;
@@ -780,11 +1256,7 @@ where
 	/// output if you're recipient), and unlock all locked outputs associated
 	/// with the transaction used when a transaction is created but never
 	/// posted
-	pub fn cancel_tx(
-		&mut self,
-		tx_id: Option<u32>,
-		tx_slate_id: Option<Uuid>,
-	) -> Result<(), Error> {
+	pub fn cancel_tx(&self, tx_id: Option<u32>, tx_slate_id: Option<Uuid>) -> Result<(), Error> {
 		let mut w = self.wallet.lock();
 		w.open_with_credentials()?;
 		let parent_key_id = w.parent_key_id();
@@ -826,14 +1298,14 @@ where
 	}
 
 	/// Verifies all messages in the slate match their public keys
-	pub fn verify_slate_messages(&mut self, slate: &Slate) -> Result<(), Error> {
+	pub fn verify_slate_messages(&self, slate: &Slate) -> Result<(), Error> {
 		let secp = Secp256k1::with_caps(ContextFlag::VerifyOnly);
 		slate.verify_messages(&secp)?;
 		Ok(())
 	}
 
 	/// Attempt to restore contents of wallet
-	pub fn restore(&mut self) -> Result<(), Error> {
+	pub fn restore(&self) -> Result<(), Error> {
 		let mut w = self.wallet.lock();
 		w.open_with_credentials()?;
 		w.restore()?;
@@ -842,7 +1314,7 @@ where
 	}
 
 	/// Attempt to check and fix the contents of the wallet
-	pub fn check_repair(&mut self, delete_unconfirmed: bool) -> Result<(), Error> {
+	pub fn check_repair(&self, delete_unconfirmed: bool) -> Result<(), Error> {
 		let mut w = self.wallet.lock();
 		w.open_with_credentials()?;
 		self.update_outputs(&mut w, true);
@@ -852,7 +1324,7 @@ where
 	}
 
 	/// Retrieve current height from node
-	pub fn node_height(&mut self) -> Result<(u64, bool), Error> {
+	pub fn node_height(&self) -> Result<(u64, bool), Error> {
 		let res = {
 			let mut w = self.wallet.lock();
 			w.open_with_credentials()?;
@@ -881,6 +1353,241 @@ where
 	}
 }
 
+impl<W: ?Sized, C, K> OwnerApi for APIOwner<W, C, K>
+where
+	W: WalletBackend<C, K>,
+	C: NodeClient,
+	K: Keychain,
+{
+	fn accounts(&self) -> Result<Vec<AcctPathMapping>, ErrorKind> {
+		APIOwner::accounts(self).map_err(|e| e.kind())
+	}
+
+	fn create_account_path(&self, label: &String) -> Result<Identifier, ErrorKind> {
+		APIOwner::create_account_path(self, label).map_err(|e| e.kind())
+	}
+
+	fn set_active_account(&self, label: &String) -> Result<(), ErrorKind> {
+		APIOwner::set_active_account(self, label).map_err(|e| e.kind())
+	}
+
+	fn retrieve_outputs(
+		&self,
+		include_spent: bool,
+		refresh_from_node: bool,
+		tx_id: Option<u32>,
+	) -> Result<(bool, Vec<(OutputData, pedersen::Commitment)>), ErrorKind> {
+		APIOwner::retrieve_outputs(self, include_spent, refresh_from_node, tx_id)
+			.map_err(|e| e.kind())
+	}
+
+	fn retrieve_txs(
+		&self,
+		refresh_from_node: bool,
+		tx_id: Option<u32>,
+		tx_slate_id: Option<Uuid>,
+	) -> Result<(bool, Vec<TxLogEntry>), ErrorKind> {
+		APIOwner::retrieve_txs(self, refresh_from_node, tx_id, tx_slate_id).map_err(|e| e.kind())
+	}
+
+	fn retrieve_summary_info(
+		&self,
+		refresh_from_node: bool,
+		minimum_confirmations: u64,
+	) -> Result<(bool, WalletInfo), ErrorKind> {
+		APIOwner::retrieve_summary_info(self, refresh_from_node, minimum_confirmations)
+			.map_err(|e| e.kind())
+	}
+
+	fn estimate_initiate_tx(
+		&self,
+		src_acct_name: Option<String>,
+		amount: u64,
+		minimum_confirmations: u64,
+		max_outputs: usize,
+		num_change_outputs: usize,
+		selection_strategy_is_use_all: bool,
+	) -> Result<(/* total */ u64, /* fee */ u64), ErrorKind> {
+		APIOwner::estimate_initiate_tx(
+			self,
+			src_acct_name.as_ref().map(String::as_str),
+			amount,
+			minimum_confirmations,
+			max_outputs,
+			num_change_outputs,
+			selection_strategy_is_use_all,
+		)
+		.map_err(|e| e.kind())
+	}
+
+	fn finalize_tx(&self, mut slate: Slate) -> Result<Slate, ErrorKind> {
+		APIOwner::finalize_tx(self, &mut slate).map_err(|e| e.kind())?;
+		Ok(slate)
+	}
+
+	fn cancel_tx(&self, tx_id: Option<u32>, tx_slate_id: Option<Uuid>) -> Result<(), ErrorKind> {
+		APIOwner::cancel_tx(self, tx_id, tx_slate_id).map_err(|e| e.kind())
+	}
+
+	fn get_stored_tx(&self, entry: &TxLogEntry) -> Result<Option<Transaction>, ErrorKind> {
+		APIOwner::get_stored_tx(self, entry).map_err(|e| e.kind())
+	}
+
+	fn post_tx(&self, tx: &Transaction, fluff: bool) -> Result<(), ErrorKind> {
+		APIOwner::post_tx(self, tx, fluff).map_err(|e| e.kind())
+	}
+
+	fn verify_slate_messages(&self, slate: &Slate) -> Result<(), ErrorKind> {
+		APIOwner::verify_slate_messages(self, slate).map_err(|e| e.kind())
+	}
+
+	fn restore(&self) -> Result<(), ErrorKind> {
+		APIOwner::restore(self).map_err(|e| e.kind())
+	}
+
+	fn check_repair(&self, delete_unconfirmed: bool) -> Result<(), ErrorKind> {
+		APIOwner::check_repair(self, delete_unconfirmed).map_err(|e| e.kind())
+	}
+
+	fn node_height(&self) -> Result<(u64, bool), ErrorKind> {
+		APIOwner::node_height(self).map_err(|e| e.kind())
+	}
+}
+
+/// Public definition used to generate jsonrpc api for APIForeign.
+#[easy_jsonrpc::rpc]
+pub trait ForeignApi {
+	/**
+	Networked version of [APIForeign::build_coinbase](struct.APIForeign.html#method.build_coinbase).
+
+	# Json rpc example
+
+	```
+	# grin_apiwallet::doctest_helper_json_rpc_foreign_assert_response!(
+	{
+		"jsonrpc": "2.0",
+		"method": "build_coinbase",
+		"params": [
+            {
+                "fees": 0,
+            	"height": 0,
+                "key_id": null
+            }
+        ],
+		"id": 1
+	},
+	{
+		"jsonrpc": "2.0",
+		"result": {
+            "Err": {
+                "CallbackImpl": "Error opening wallet"
+            }
+		},
+		"id": 1
+	}
+	# );
+	```
+	 */
+	fn build_coinbase(&self, block_fees: &BlockFees) -> Result<CbData, ErrorKind>;
+
+	/**
+	Networked version of [APIForeign::verify_slate_messages](struct.APIForeign.html#method.verify_slate_messages).
+
+	# Json rpc example
+
+	```
+	# grin_apiwallet::doctest_helper_json_rpc_foreign_assert_response!(
+	{
+		"jsonrpc": "2.0",
+		"method": "verify_slate_messages",
+		"params": [
+            {
+    			"amount": 0,
+    			"fee": 0,
+    			"height": 0,
+    			"id": "414bad48-3386-4fa7-8483-72384c886ba3",
+    			"lock_height": 0,
+    			"num_participants": 2,
+    			"participant_data": [],
+    			"tx": {
+    				"body": {
+    					"inputs": [],
+    					"kernels": [],
+    					"outputs": []
+    				},
+    				"offset": "0000000000000000000000000000000000000000000000000000000000000000"
+    			},
+    			"version": 1
+		    }
+        ],
+		"id": 1
+	},
+	{
+		"jsonrpc": "2.0",
+		"result": {
+            "Ok": null
+		},
+		"id": 1
+	}
+	# );
+	```
+	 */
+	fn verify_slate_messages(&self, slate: &Slate) -> Result<(), ErrorKind>;
+
+	/**
+	Networked version of [APIForeign::receive_tx](struct.APIForeign.html#method.receive_tx).
+
+	# Json rpc example
+
+	```
+	# grin_apiwallet::doctest_helper_json_rpc_foreign_assert_response!(
+	{
+		"jsonrpc": "2.0",
+		"method": "receive_tx",
+		"params": [
+            {
+    			"amount": 0,
+    			"fee": 0,
+    			"height": 0,
+    			"id": "414bad48-3386-4fa7-8483-72384c886ba3",
+    			"lock_height": 0,
+    			"num_participants": 2,
+    			"participant_data": [],
+    			"tx": {
+    				"body": {
+    					"inputs": [],
+    					"kernels": [],
+    					"outputs": []
+    				},
+    				"offset": "0000000000000000000000000000000000000000000000000000000000000000"
+    			},
+    			"version": 1
+		    },
+            null,
+            null
+        ],
+		"id": 1
+	},
+	{
+		"jsonrpc": "2.0",
+		"result": {
+            "Err": {
+                "CallbackImpl": "Error opening wallet"
+            }
+		},
+		"id": 1
+	}
+	# );
+	```
+	 */
+	fn receive_tx(
+		&self,
+		slate: Slate,
+		dest_acct_name: Option<String>,
+		message: Option<String>,
+	) -> Result<Slate, ErrorKind>;
+}
+
 /// Wrapper around external API functions, intended to communicate
 /// with other parties
 pub struct APIForeign<W: ?Sized, C, K>
@@ -912,7 +1619,7 @@ where
 	}
 
 	/// Build a new (potential) coinbase transaction in the wallet
-	pub fn build_coinbase(&mut self, block_fees: &BlockFees) -> Result<CbData, Error> {
+	pub fn build_coinbase(&self, block_fees: &BlockFees) -> Result<CbData, Error> {
 		let mut w = self.wallet.lock();
 		w.open_with_credentials()?;
 		let res = updater::build_coinbase(&mut *w, block_fees);
@@ -921,7 +1628,7 @@ where
 	}
 
 	/// Verifies all messages in the slate match their public keys
-	pub fn verify_slate_messages(&mut self, slate: &Slate) -> Result<(), Error> {
+	pub fn verify_slate_messages(&self, slate: &Slate) -> Result<(), Error> {
 		let secp = Secp256k1::with_caps(ContextFlag::VerifyOnly);
 		slate.verify_messages(&secp)?;
 		Ok(())
@@ -929,7 +1636,7 @@ where
 
 	/// Receive a transaction from a sender
 	pub fn receive_tx(
-		&mut self,
+		&self,
 		slate: &mut Slate,
 		dest_acct_name: Option<&str>,
 		message: Option<String>,
@@ -970,3 +1677,146 @@ where
 		Ok(())
 	}
 }
+
+impl<W: ?Sized, C, K> ForeignApi for APIForeign<W, C, K>
+where
+	W: WalletBackend<C, K>,
+	C: NodeClient,
+	K: Keychain,
+{
+	fn build_coinbase(&self, block_fees: &BlockFees) -> Result<CbData, ErrorKind> {
+		APIForeign::build_coinbase(self, block_fees).map_err(|e| e.kind())
+	}
+
+	fn verify_slate_messages(&self, slate: &Slate) -> Result<(), ErrorKind> {
+		APIForeign::verify_slate_messages(self, slate).map_err(|e| e.kind())
+	}
+
+	fn receive_tx(
+		&self,
+		mut slate: Slate,
+		dest_acct_name: Option<String>,
+		message: Option<String>,
+	) -> Result<Slate, ErrorKind> {
+		APIForeign::receive_tx(
+			self,
+			&mut slate,
+			dest_acct_name.as_ref().map(String::as_str),
+			message,
+		)
+		.map_err(|e| e.kind())?;
+		Ok(slate)
+	}
+}
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! doctest_helper_json_rpc_owner_assert_response {
+	($request:tt, $expected_response:tt) => {
+		// create temporary wallet, run jsonrpc request on owner api of wallet, delete wallet, return
+		// json response.
+		// In order to prevent leaking tempdirs, This function should not panic.
+		fn rpc_owner_result(
+			request: serde_json::Value,
+		) -> Result<Option<serde_json::Value>, String> {
+			use easy_jsonrpc::Handler;
+			use grin_apiwallet::api::{APIOwner, OwnerApi};
+			use grin_keychain::ExtKeychain;
+			use grin_refwallet::{HTTPNodeClient, LMDBBackend, WalletBackend};
+			use grin_util::Mutex;
+			use grin_wallet_config::WalletConfig;
+			use serde_json;
+			use std::sync::Arc;
+			use tempfile::tempdir;
+
+			let dir = tempdir().map_err(|e| format!("{:#?}", e))?;
+				{
+				let mut wallet_config = WalletConfig::default();
+				wallet_config.data_file_dir = dir
+					.path()
+					.to_str()
+					.ok_or("Failed to convert tmpdir path to string.".to_owned())?
+					.to_owned();
+				let node_client =
+					HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None);
+				let wallet: Arc<Mutex<WalletBackend<HTTPNodeClient, ExtKeychain>>> =
+					Arc::new(Mutex::new(
+						LMDBBackend::new(wallet_config.clone(), "", node_client)
+							.map_err(|e| format!("{:#?}", e))?,
+					));
+				let api_owner = APIOwner::new(wallet);
+				let owner_api = &api_owner as &dyn OwnerApi;
+				Ok(owner_api.handle_request(request))
+				}
+			}
+
+		let response = rpc_owner_result(serde_json::json!($request))
+			.unwrap()
+			.unwrap();
+		let expected_response = serde_json::json!($expected_response);
+
+		if response != expected_response {
+			panic!(
+				"(left != right) \nleft: {}\nright: {}",
+				serde_json::to_string_pretty(&response).unwrap(),
+				serde_json::to_string_pretty(&expected_response).unwrap()
+				);
+			}
+	};
+}
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! doctest_helper_json_rpc_foreign_assert_response {
+	($request:tt, $expected_response:tt) => {
+		// create temporary wallet, run jsonrpc request on api of wallet, delete wallet, return
+		// json response.
+		// In order to prevent leaking tempdirs, This function should not panic.
+		fn rpc_owner_result(
+			request: serde_json::Value,
+		) -> Result<Option<serde_json::Value>, String> {
+			use easy_jsonrpc::Handler;
+			use grin_apiwallet::api::{APIForeign, ForeignApi};
+			use grin_keychain::ExtKeychain;
+			use grin_refwallet::{HTTPNodeClient, LMDBBackend, WalletBackend};
+			use grin_util::Mutex;
+			use grin_wallet_config::WalletConfig;
+			use serde_json;
+			use std::sync::Arc;
+			use tempfile::tempdir;
+
+			let dir = tempdir().map_err(|e| format!("{:#?}", e))?;
+				{
+				let mut wallet_config = WalletConfig::default();
+				wallet_config.data_file_dir = dir
+					.path()
+					.to_str()
+					.ok_or("Failed to convert tmpdir path to string.".to_owned())?
+					.to_owned();
+				let node_client =
+					HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None);
+				let wallet: Arc<Mutex<WalletBackend<HTTPNodeClient, ExtKeychain>>> =
+					Arc::new(Mutex::new(
+						LMDBBackend::new(wallet_config.clone(), "", node_client)
+							.map_err(|e| format!("{:#?}", e))?,
+					));
+				let api_foreign = *APIForeign::new(wallet);
+				let foreign_api = &api_foreign as &dyn ForeignApi;
+				Ok(foreign_api.handle_request(request))
+				}
+			}
+
+		let response = rpc_owner_result(serde_json::json!($request))
+			.unwrap()
+			.unwrap();
+		let expected_response = serde_json::json!($expected_response);
+
+		if response != expected_response {
+			panic!(
+				"(left != right) \nleft: {}\nright: {}",
+				serde_json::to_string_pretty(&response).unwrap(),
+				serde_json::to_string_pretty(&expected_response).unwrap()
+				);
+			}
+	};
+}
diff --git a/libwallet/src/error.rs b/libwallet/src/error.rs
index e0f51c6a..b7855a1f 100644
--- a/libwallet/src/error.rs
+++ b/libwallet/src/error.rs
@@ -30,7 +30,7 @@ pub struct Error {
 }
 
 /// Wallet errors, mostly wrappers around underlying crypto or I/O errors.
-#[derive(Clone, Eq, PartialEq, Debug, Fail)]
+#[derive(Clone, Eq, PartialEq, Debug, Fail, Serialize, Deserialize)]
 pub enum ErrorKind {
 	/// Not enough funds
 	#[fail(
diff --git a/refwallet/src/controller.rs b/refwallet/src/controller.rs
index ca96498b..e49fa731 100644
--- a/refwallet/src/controller.rs
+++ b/refwallet/src/controller.rs
@@ -18,10 +18,10 @@
 use crate::adapters::util::get_versioned_slate;
 use crate::adapters::{FileWalletCommAdapter, HTTPWalletCommAdapter, KeybaseWalletCommAdapter};
 use crate::api::{ApiServer, BasicAuthMiddleware, Handler, ResponseFuture, Router, TLSConfig};
+use crate::apiwallet::api::{APIForeign, APIOwner};
 use crate::core::core;
 use crate::core::core::Transaction;
 use crate::keychain::Keychain;
-use crate::apiwallet::api::{APIForeign, APIOwner};
 use crate::libwallet::slate::{Slate, VersionedSlate};
 use crate::libwallet::types::{
 	CbData, NodeClient, OutputData, SendTXArgs, TxLogEntry, WalletBackend, WalletInfo,
@@ -271,7 +271,7 @@ where
 	pub fn retrieve_summary_info(
 		&self,
 		req: &Request<Body>,
-		mut api: APIOwner<T, C, K>,
+		api: APIOwner<T, C, K>,
 	) -> Result<(bool, WalletInfo), Error> {
 		let mut minimum_confirmations = 1; // TODO - default needed here
 		let params = parse_params(req);
@@ -289,7 +289,7 @@ where
 	pub fn node_height(
 		&self,
 		_req: &Request<Body>,
-		mut api: APIOwner<T, C, K>,
+		api: APIOwner<T, C, K>,
 	) -> Result<(u64, bool), Error> {
 		api.node_height()
 	}
@@ -319,7 +319,7 @@ where
 	pub fn issue_send_tx(
 		&self,
 		req: Request<Body>,
-		mut api: APIOwner<T, C, K>,
+		api: APIOwner<T, C, K>,
 	) -> Box<dyn Future<Item = Slate, Error = Error> + Send> {
 		Box::new(parse_body(req).and_then(move |args: SendTXArgs| {
 			let result = api.initiate_tx(
@@ -382,7 +382,7 @@ where
 	pub fn finalize_tx(
 		&self,
 		req: Request<Body>,
-		mut api: APIOwner<T, C, K>,
+		api: APIOwner<T, C, K>,
 	) -> Box<dyn Future<Item = Slate, Error = Error> + Send> {
 		Box::new(
 			parse_body(req).and_then(move |mut slate| match api.finalize_tx(&mut slate) {
@@ -398,7 +398,7 @@ where
 	pub fn cancel_tx(
 		&self,
 		req: Request<Body>,
-		mut api: APIOwner<T, C, K>,
+		api: APIOwner<T, C, K>,
 	) -> Box<dyn Future<Item = (), Error = Error> + Send> {
 		let params = parse_params(&req);
 		if let Some(id_string) = params.get("id") {
@@ -652,7 +652,7 @@ where
 	fn build_coinbase(
 		&self,
 		req: Request<Body>,
-		mut api: APIForeign<T, C, K>,
+		api: APIForeign<T, C, K>,
 	) -> Box<dyn Future<Item = CbData, Error = Error> + Send> {
 		Box::new(parse_body(req).and_then(move |block_fees| api.build_coinbase(&block_fees)))
 	}
@@ -660,7 +660,7 @@ where
 	fn receive_tx(
 		&self,
 		req: Request<Body>,
-		mut api: APIForeign<T, C, K>,
+		api: APIForeign<T, C, K>,
 	) -> Box<dyn Future<Item = VersionedSlate, Error = Error> + Send> {
 		Box::new(parse_body(req).and_then(
 			//TODO: No way to insert a message from the params