diff --git a/Cargo.lock b/Cargo.lock
index 63f1899d9c834631838369629c9b9d5fd7154e99..178d543d7e8199397d27ee2d277da01c625d5640 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -229,12 +229,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "dubp-documents"
-version = "0.10.0-b1"
+version = "0.11.0"
 dependencies = [
  "base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "base64 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "dup-crypto 0.4.0-b1",
+ "dup-crypto 0.5.0",
  "pest 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "pest_derive 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -248,14 +248,14 @@ name = "duniter-blockchain"
 version = "0.1.0-a0.1"
 dependencies = [
  "dirs 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "dubp-documents 0.10.0-b1",
+ "dubp-documents 0.11.0",
  "duniter-conf 0.1.0-a0.1",
  "duniter-dal 0.1.0-a0.1",
  "duniter-message 0.1.0-a0.1",
  "duniter-module 0.1.0-a0.1",
  "duniter-network 0.1.0-a0.1",
- "dup-crypto 0.4.0-b1",
- "durs-network-documents 0.2.0-b1",
+ "dup-crypto 0.5.0",
+ "durs-network-documents 0.3.0",
  "durs-wot 0.8.0-a0.9",
  "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -272,9 +272,9 @@ name = "duniter-conf"
 version = "0.1.0-a0.1"
 dependencies = [
  "dirs 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "dubp-documents 0.10.0-b1",
+ "dubp-documents 0.11.0",
  "duniter-module 0.1.0-a0.1",
- "dup-crypto 0.4.0-b1",
+ "dup-crypto 0.5.0",
  "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.78 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -291,8 +291,8 @@ dependencies = [
  "duniter-message 0.1.0-a0.1",
  "duniter-module 0.1.0-a0.1",
  "duniter-network 0.1.0-a0.1",
- "dup-crypto 0.4.0-b1",
- "durs-network-documents 0.2.0-b1",
+ "dup-crypto 0.5.0",
+ "durs-network-documents 0.3.0",
  "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log-panics 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.78 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -307,10 +307,10 @@ dependencies = [
 name = "duniter-dal"
 version = "0.1.0-a0.1"
 dependencies = [
- "dubp-documents 0.10.0-b1",
+ "dubp-documents 0.11.0",
  "duniter-module 0.1.0-a0.1",
  "duniter-network 0.1.0-a0.1",
- "dup-crypto 0.4.0-b1",
+ "dup-crypto 0.5.0",
  "durs-wot 0.8.0-a0.9",
  "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustbreak 2.0.0-rc3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -323,12 +323,12 @@ dependencies = [
 name = "duniter-message"
 version = "0.1.0-a0.1"
 dependencies = [
- "dubp-documents 0.10.0-b1",
+ "dubp-documents 0.11.0",
  "duniter-dal 0.1.0-a0.1",
  "duniter-module 0.1.0-a0.1",
  "duniter-network 0.1.0-a0.1",
- "dup-crypto 0.4.0-b1",
- "durs-network-documents 0.2.0-b1",
+ "dup-crypto 0.5.0",
+ "durs-network-documents 0.3.0",
  "serde 1.0.78 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -338,9 +338,9 @@ dependencies = [
 name = "duniter-module"
 version = "0.1.0-a0.1"
 dependencies = [
- "dubp-documents 0.10.0-b1",
- "dup-crypto 0.4.0-b1",
- "durs-network-documents 0.2.0-b1",
+ "dubp-documents 0.11.0",
+ "dup-crypto 0.5.0",
+ "durs-network-documents 0.3.0",
  "serde 1.0.78 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -351,10 +351,10 @@ dependencies = [
 name = "duniter-network"
 version = "0.1.0-a0.1"
 dependencies = [
- "dubp-documents 0.10.0-b1",
+ "dubp-documents 0.11.0",
  "duniter-module 0.1.0-a0.1",
- "dup-crypto 0.4.0-b1",
- "durs-network-documents 0.2.0-b1",
+ "dup-crypto 0.5.0",
+ "durs-network-documents 0.3.0",
  "serde 1.0.78 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -364,14 +364,14 @@ dependencies = [
 name = "duniter-tui"
 version = "0.1.0-a0.1"
 dependencies = [
- "dubp-documents 0.10.0-b1",
+ "dubp-documents 0.11.0",
  "duniter-conf 0.1.0-a0.1",
  "duniter-dal 0.1.0-a0.1",
  "duniter-message 0.1.0-a0.1",
  "duniter-module 0.1.0-a0.1",
  "duniter-network 0.1.0-a0.1",
- "dup-crypto 0.4.0-b1",
- "durs-network-documents 0.2.0-b1",
+ "dup-crypto 0.5.0",
+ "durs-network-documents 0.3.0",
  "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.78 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -382,7 +382,7 @@ dependencies = [
 
 [[package]]
 name = "dup-crypto"
-version = "0.4.0-b1"
+version = "0.5.0"
 dependencies = [
  "base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -406,12 +406,12 @@ dependencies = [
 
 [[package]]
 name = "durs-network-documents"
-version = "0.2.0-b1"
+version = "0.3.0"
 dependencies = [
  "base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bincode 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "dubp-documents 0.10.0-b1",
- "dup-crypto 0.4.0-b1",
+ "dubp-documents 0.11.0",
+ "dup-crypto 0.5.0",
  "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "pest 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "pest_derive 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -437,13 +437,13 @@ name = "durs-ws2p"
 version = "0.1.0-a0.1"
 dependencies = [
  "bincode 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "dubp-documents 0.10.0-b1",
+ "dubp-documents 0.11.0",
  "duniter-conf 0.1.0-a0.1",
  "duniter-message 0.1.0-a0.1",
  "duniter-module 0.1.0-a0.1",
  "duniter-network 0.1.0-a0.1",
- "dup-crypto 0.4.0-b1",
- "durs-network-documents 0.2.0-b1",
+ "dup-crypto 0.5.0",
+ "durs-network-documents 0.3.0",
  "durs-ws2p-messages 0.1.0-a0.1",
  "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.78 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -457,9 +457,9 @@ version = "0.1.0-a0.1"
 dependencies = [
  "bincode 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "dubp-documents 0.10.0-b1",
- "dup-crypto 0.4.0-b1",
- "durs-network-documents 0.2.0-b1",
+ "dubp-documents 0.11.0",
+ "dup-crypto 0.5.0",
+ "durs-network-documents 0.3.0",
  "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.78 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -472,14 +472,14 @@ name = "durs-ws2p-v1-legacy"
 version = "0.1.0-a0.1"
 dependencies = [
  "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "dubp-documents 0.10.0-b1",
+ "dubp-documents 0.11.0",
  "duniter-conf 0.1.0-a0.1",
  "duniter-dal 0.1.0-a0.1",
  "duniter-message 0.1.0-a0.1",
  "duniter-module 0.1.0-a0.1",
  "duniter-network 0.1.0-a0.1",
- "dup-crypto 0.4.0-b1",
- "durs-network-documents 0.2.0-b1",
+ "dup-crypto 0.5.0",
+ "durs-network-documents 0.3.0",
  "durs-wot 0.8.0-a0.9",
  "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/crypto/Cargo.toml b/crypto/Cargo.toml
index 983a3cf007b815a89135b602b74a19f5e240fda1..6347d17cb5f78b56617fc3330820e8b9601bc4b5 100644
--- a/crypto/Cargo.toml
+++ b/crypto/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "dup-crypto"
-version = "0.4.0-b1"
+version = "0.5.0"
 authors = ["nanocryk <nanocryk@duniter.org>", "elois <elois@duniter.org>"]
 description = "Manage cryptographic operations for the DUP (DUniter Protocol)."
 repository = "https://git.duniter.org/nodes/rust/duniter-rs"
diff --git a/documents/Cargo.toml b/documents/Cargo.toml
index 7ef7055d8961ab67583a225b410f37db2f45dba5..405cf08300de293bc9576ff2ad85a1ebfb8ed05f 100644
--- a/documents/Cargo.toml
+++ b/documents/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "dubp-documents"
-version = "0.10.0-b1"
+version = "0.11.0"
 authors = ["nanocryk <nanocryk@duniter.org>", "elois <elois@ifee.fr>"]
 description = "Handles DUBP documents (DUBP: DUniter Blockhain Protocol)"
 repository = "https://git.duniter.org/nodes/rust/duniter-rs"
diff --git a/documents/src/documents_grammar.pest b/documents/src/documents_grammar.pest
index 695f6e262c9b875cf694333a59e786338a2debe3..12f7d49706b9a4e91ffc4ae4f3e6e96c49a273fa 100644
--- a/documents/src/documents_grammar.pest
+++ b/documents/src/documents_grammar.pest
@@ -147,11 +147,11 @@ tx = ${
 
 document_v10 = ${
     &(SOI ~ v10 ~ nl) ~
-    (&"Type: Identity" ~ idty_v10) | 
-    (&"Type: Membership" ~ membership_v10) | 
-    (&"Type: Certification" ~ cert_v10) | 
-    (&"Type: Revocation" ~ revoc_v10) |
-    (&"Type: Transaction" ~ tx_v10)
+    idty_v10 | 
+    membership_v10 | 
+    cert_v10 | 
+    revoc_v10 |
+    tx_v10
 }
 
 document = ${
diff --git a/documents/src/lib.rs b/documents/src/lib.rs
index 586f5d41f7889685eae9de7f8846cfe15f5150e6..dbb8d5f675e470ffe27947bc40e128e4147556ad 100644
--- a/documents/src/lib.rs
+++ b/documents/src/lib.rs
@@ -50,7 +50,7 @@ use currencies_codes::*;
 use dup_crypto::hashs::Hash;
 use dup_crypto::keys::*;
 use pest::iterators::Pair;
-use pest::Parser;
+use pest::{Parser, RuleType};
 use serde::Serialize;
 use std::cmp::Ordering;
 use std::fmt::{Debug, Display, Error, Formatter};
@@ -64,14 +64,14 @@ pub use blockstamp::{Blockstamp, PreviousBlockstamp};
 /// Parser for Documents
 struct DocumentsParser;
 
-trait TextDocumentParser {
+pub trait TextDocumentParser<R: RuleType> {
     /// Type of document generated by the parser
     type DocumentType;
 
     /// Parse text document from raw format
     fn parse(doc: &str) -> Result<Self::DocumentType, TextDocumentParseError>;
     /// Parse text document from pest pairs
-    fn from_pest_pair(pairs: Pair<Rule>) -> Self::DocumentType;
+    fn from_pest_pair(pairs: Pair<R>) -> Self::DocumentType;
 }
 
 /// List of possible errors while parsing.
@@ -79,18 +79,16 @@ trait TextDocumentParser {
 pub enum TextDocumentParseError {
     /// The given source don't have a valid specific document format (document type).
     InvalidInnerFormat(&'static str),
-    /// Type fields contains an unknown document type.
-    UnknownDocumentType(String),
     /// Error with pest parser
     PestError(String),
-    /// Invalid currency
-    InvalidCurrency(),
     /// UnexpectedVersion
     UnexpectedVersion(String),
+    /// Unknown type
+    UnknownType,
 }
 
 /// Document of DUBP (DUniter Blockhain Protocol)
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, Serialize, Deserialize)]
 pub enum DUBPDocument {
     /// Version 10.
     V10(Box<v10::V10Document>),
@@ -98,12 +96,12 @@ pub enum DUBPDocument {
     V11(),
 }
 
-impl TextDocumentParser for DUBPDocument {
+impl TextDocumentParser<Rule> for DUBPDocument {
     type DocumentType = DUBPDocument;
 
     fn parse(doc: &str) -> Result<DUBPDocument, TextDocumentParseError> {
         match DocumentsParser::parse(Rule::document, doc) {
-            Ok(mut root_ast) => Ok(DUBPDocument::from_pest_pair(root_ast.next().unwrap())), // get and unwrap the `document` rule; never fails
+            Ok(mut doc_pairs) => Ok(DUBPDocument::from_pest_pair(doc_pairs.next().unwrap())), // get and unwrap the `document` rule; never fails
             Err(pest_error) => Err(TextDocumentParseError::PestError(format!("{}", pest_error))),
         }
     }
@@ -318,18 +316,43 @@ pub trait DocumentParser<S, D, E> {
     fn parse(source: S) -> Result<D, E>;
 }
 
-/// Jsonify a document
-pub trait ToJsonObject {
-    type JsonObject: Serialize;
-    /// Transforms an object into a json object
-    fn to_json_object(&self) -> Self::JsonObject;
+/// Stringify a document
+pub trait ToStringObject {
+    type StringObject: Serialize;
+    /// Transforms object fields into string
+    fn to_string_object(&self) -> Self::StringObject;
+}
 
+/// Jsonify a document
+pub trait ToJsonObject: ToStringObject {
     /// Convert to JSON String
     fn to_json_string(&self) -> Result<String, serde_json::Error> {
-        Ok(serde_json::to_string(&self.to_json_object())?)
+        Ok(serde_json::to_string(&self.to_string_object())?)
     }
     /// Convert to JSON String pretty
     fn to_json_string_pretty(&self) -> Result<String, serde_json::Error> {
-        Ok(serde_json::to_string_pretty(&self.to_json_object())?)
+        Ok(serde_json::to_string_pretty(&self.to_string_object())?)
+    }
+}
+
+impl<T: ToStringObject> ToJsonObject for T {}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    //use dup_crypto::keys::*;
+
+    #[test]
+    fn parse_dubp_document() {
+        let text = "Version: 10
+Type: Identity
+Currency: g1
+Issuer: D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx
+UniqueID: elois
+Timestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
+Ydnclvw76/JHcKSmU9kl9Ie0ne5/X8NYOqPqbGnufIK3eEPRYYdEYaQh+zffuFhbtIRjv6m/DkVLH5cLy/IyAg==";
+
+        let doc = DUBPDocument::parse(text).expect("Fail to parse DUBPDocument !");
+        println!("Doc : {:?}", doc);
     }
 }
diff --git a/documents/src/v10/certification.rs b/documents/src/v10/certification.rs
index 419b18d18924e81969126b7109fcb98ce2bd05f4..bb81effb764d2bf1b8ce4f4ee01331a08ee36aa0 100644
--- a/documents/src/v10/certification.rs
+++ b/documents/src/v10/certification.rs
@@ -75,6 +75,44 @@ pub struct CertificationDocument {
     signatures: Vec<Sig>,
 }
 
+#[derive(Clone, Debug, Deserialize, Hash, Serialize, PartialEq, Eq)]
+/// identity document for jsonification
+pub struct CertificationStringDocument {
+    /// Name of the currency.
+    currency: String,
+    /// Document issuer
+    issuer: String,
+    /// issuer of target identity.
+    target: String,
+    /// Username of target identity
+    identity_username: String,
+    /// Target Identity document blockstamp.
+    identity_blockstamp: String,
+    /// Target Identity document signature.
+    identity_sig: String,
+    /// Blockstamp
+    blockstamp: String,
+    /// Document signature
+    signature: String,
+}
+
+impl ToStringObject for CertificationDocument {
+    type StringObject = CertificationStringDocument;
+    /// Transforms an object into a json object
+    fn to_string_object(&self) -> CertificationStringDocument {
+        CertificationStringDocument {
+            currency: self.currency.clone(),
+            issuer: format!("{}", self.issuers[0]),
+            target: format!("{}", self.target),
+            identity_username: self.identity_username.clone(),
+            identity_blockstamp: format!("{}", self.identity_blockstamp),
+            blockstamp: format!("{}", self.blockstamp),
+            identity_sig: format!("{}", self.identity_sig),
+            signature: format!("{}", self.signatures[0]),
+        }
+    }
+}
+
 impl CertificationDocument {
     /// Username of target identity
     pub fn identity_username(&self) -> &str {
@@ -221,7 +259,7 @@ CertTimestamp: {blockstamp}
 #[derive(Debug, Clone, Copy)]
 pub struct CertificationDocumentParser;
 
-impl TextDocumentParser for CertificationDocumentParser {
+impl TextDocumentParser<Rule> for CertificationDocumentParser {
     type DocumentType = CertificationDocument;
 
     fn parse(doc: &str) -> Result<Self::DocumentType, TextDocumentParseError> {
diff --git a/documents/src/v10/identity.rs b/documents/src/v10/identity.rs
index 03bef1bee587266a954d24395a169940aee0dc00..ff28eb7e93c5eafc6fac15bd15cdfd57f48fdb24 100644
--- a/documents/src/v10/identity.rs
+++ b/documents/src/v10/identity.rs
@@ -44,6 +44,35 @@ pub struct IdentityDocument {
     signatures: Vec<Sig>,
 }
 
+#[derive(Clone, Debug, Deserialize, Hash, Serialize, PartialEq, Eq)]
+/// identity document for jsonification
+pub struct IdentityStringDocument {
+    /// Currency.
+    currency: String,
+    /// Unique ID
+    username: String,
+    /// Blockstamp
+    blockstamp: String,
+    /// Document issuer
+    issuer: String,
+    /// Document signature
+    signature: String,
+}
+
+impl ToStringObject for IdentityDocument {
+    type StringObject = IdentityStringDocument;
+    /// Transforms an object into a json object
+    fn to_string_object(&self) -> IdentityStringDocument {
+        IdentityStringDocument {
+            currency: self.currency.clone(),
+            username: self.username.clone(),
+            blockstamp: format!("{}", self.blockstamp),
+            issuer: format!("{}", self.issuers[0]),
+            signature: format!("{}", self.signatures[0]),
+        }
+    }
+}
+
 impl IdentityDocument {
     /// Unique ID
     pub fn username(&self) -> &str {
@@ -199,7 +228,7 @@ Timestamp: {blockstamp}
 #[derive(Debug, Clone, Copy)]
 pub struct IdentityDocumentParser;
 
-impl TextDocumentParser for IdentityDocumentParser {
+impl TextDocumentParser<Rule> for IdentityDocumentParser {
     type DocumentType = IdentityDocument;
 
     fn parse(doc: &str) -> Result<Self::DocumentType, TextDocumentParseError> {
diff --git a/documents/src/v10/membership.rs b/documents/src/v10/membership.rs
index 66154b79ce81e6964df455c451e73a0dbca76858..1c44b0cd1a1443033bda2f7bb1f6c63349c0b445 100644
--- a/documents/src/v10/membership.rs
+++ b/documents/src/v10/membership.rs
@@ -57,6 +57,44 @@ pub struct MembershipDocument {
     signatures: Vec<Sig>,
 }
 
+#[derive(Clone, Debug, Deserialize, Hash, Serialize, PartialEq, Eq)]
+/// identity document for jsonification
+pub struct MembershipStringDocument {
+    /// Currency.
+    currency: String,
+    /// Document issuer
+    issuer: String,
+    /// Blockstamp
+    blockstamp: String,
+    /// Membership message.
+    membership: String,
+    /// Unique ID
+    username: String,
+    /// Identity document blockstamp.
+    identity_blockstamp: String,
+    /// Document signature
+    signature: String,
+}
+
+impl ToStringObject for MembershipDocument {
+    type StringObject = MembershipStringDocument;
+    /// Transforms an object into a json object
+    fn to_string_object(&self) -> MembershipStringDocument {
+        MembershipStringDocument {
+            currency: self.currency.clone(),
+            issuer: format!("{}", self.issuers[0]),
+            blockstamp: format!("{}", self.blockstamp),
+            membership: match self.membership {
+                MembershipType::In() => "IN".to_owned(),
+                MembershipType::Out() => "OUT".to_owned(),
+            },
+            username: self.identity_username.clone(),
+            identity_blockstamp: format!("{}", self.identity_blockstamp),
+            signature: format!("{}", self.signatures[0]),
+        }
+    }
+}
+
 #[derive(Debug, Copy, Clone, PartialEq, Hash, Deserialize, Serialize)]
 /// Membership event type (blockchain event)
 pub enum MembershipEventType {
@@ -248,7 +286,7 @@ CertTS: {ity_blockstamp}
 #[derive(Debug, Clone, Copy)]
 pub struct MembershipDocumentParser;
 
-impl TextDocumentParser for MembershipDocumentParser {
+impl TextDocumentParser<Rule> for MembershipDocumentParser {
     type DocumentType = MembershipDocument;
 
     fn parse(doc: &str) -> Result<Self::DocumentType, TextDocumentParseError> {
diff --git a/documents/src/v10/mod.rs b/documents/src/v10/mod.rs
index bcad4ff71c566f938edf84cb9a83e5c574a66701..505510dad00142e5bec7659f5eaf2b37e5ba98a2 100644
--- a/documents/src/v10/mod.rs
+++ b/documents/src/v10/mod.rs
@@ -31,6 +31,7 @@ use v10::identity::*;
 use v10::membership::*;
 use v10::revocation::*;
 use v10::transaction::*;
+use ToStringObject;
 use *;
 
 #[derive(Clone, Debug, Deserialize, Serialize)]
@@ -53,7 +54,7 @@ impl<D: TextDocument> TextDocumentFormat<D> {
 }
 
 /// List of wrapped document types.
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, Serialize, Deserialize)]
 pub enum V10Document {
     /// Block document.
     Block(Box<BlockDocument>),
@@ -74,7 +75,52 @@ pub enum V10Document {
     Revocation(Box<RevocationDocument>),
 }
 
-impl TextDocumentParser for V10Document {
+/// List of stringified document types.
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub enum V10DocumentString {
+    /// Block document (not yet implemented)
+    Block(),
+
+    /// Transaction document.
+    Transaction(Box<TransactionDocumentStringified>),
+
+    /// Identity document.
+    Identity(IdentityStringDocument),
+
+    /// Membership document.
+    Membership(MembershipStringDocument),
+
+    /// Certification document.
+    Certification(Box<CertificationStringDocument>),
+
+    /// Revocation document.
+    Revocation(Box<RevocationStringDocument>),
+}
+
+impl ToStringObject for V10Document {
+    type StringObject = V10DocumentString;
+    /// Transforms an object into a json object
+    fn to_string_object(&self) -> Self::StringObject {
+        match *self {
+            V10Document::Block(_) => unimplemented!(),
+            V10Document::Identity(ref doc) => V10DocumentString::Identity(doc.to_string_object()),
+            V10Document::Membership(ref doc) => {
+                V10DocumentString::Membership(doc.to_string_object())
+            }
+            V10Document::Certification(ref doc) => {
+                V10DocumentString::Certification(Box::new(doc.to_string_object()))
+            }
+            V10Document::Revocation(ref doc) => {
+                V10DocumentString::Revocation(Box::new(doc.to_string_object()))
+            }
+            V10Document::Transaction(ref doc) => {
+                V10DocumentString::Transaction(Box::new(doc.to_string_object()))
+            }
+        }
+    }
+}
+
+impl TextDocumentParser<Rule> for V10Document {
     type DocumentType = V10Document;
 
     fn parse(doc: &str) -> Result<Self::DocumentType, TextDocumentParseError> {
@@ -216,49 +262,6 @@ pub struct V10DocumentParts {
     pub signatures: Vec<Sig>,
 }
 
-/*/// A V10 document parser.
-#[derive(Debug, Clone, Copy)]
-pub struct V10DocumentParser;
-
-impl<'a> DocumentParser<&'a str, V10Document, TextDocumentParseError> for V10DocumentParser {
-    fn parse(source: &'a str) -> Result<V10Document, TextDocumentParseError> {
-        /*match DocumentsParser::parse(Rule::document_v10, source) {
-            Ok(mut source_ast) => {
-                let doc_v10_ast = source_ast.next().unwrap(); // get and unwrap the `document_v10` rule; never fails
-                let doc_type_v10_ast = doc_v10_ast.into_inner().next().unwrap(); // get and unwrap the `{DOC_TYPE}_v10` rule; never fails
-        
-                match doc_type_v10_ast.as_rule() {
-                    Rule::idty_v10 => IdentityDocumentParser::parse_standard(doc_type_v10_ast.as_str(), "", currency, vec![]),
-                    Rule::membership_v10 => MembershipDocumentParser::parse_standard(doc_type_v10_ast.as_str(), "", currency, vec![]),
-                    Rule::cert_v10 => CertificationDocumentParser::parse_standard(doc_type_v10_ast.as_str(), "", currency, vec![]),
-                    Rule::revoc_v10 => RevocationDocumentParser::parse_standard(doc_type_v10_ast.as_str(), "", currency, vec![]),
-                    Rule::tx_v10 => TransactionDocumentParser::parse_standard(doc_type_v10_ast.as_str(), "", currency, vec![]),
-                }
-            }
-            Err(_) => Err(TextDocumentParseError::InvalidWrapperFormat()),
-        }*/
-if let Some(caps) = DOCUMENT_REGEX.captures(source) {
-let doctype = &caps["type"];
-let currency = &caps["currency"];
-
-// TODO : Improve error handling of Signature::from_base64 failure
-
-match doctype {
-"Identity" => IdentityDocumentParser::parse_standard(source, currency),
-"Membership" => MembershipDocumentParser::parse_standard(source, currency),
-"Certification" => CertificationDocumentParser::parse_standard(source, currency),
-"Revocation" => RevocationDocumentParser::parse_standard(source, currency),
-"Transaction" => TransactionDocumentParser::parse_standard(source, currency),
-_ => Err(TextDocumentParseError::UnknownDocumentType(
-doctype.to_string(),
-)),
-}
-} else {
-Err(TextDocumentParseError::InvalidWrapperFormat())
-}
-}
-}*/
-
 #[cfg(test)]
 mod tests {
     use super::certification::CertificationDocumentParser;
diff --git a/documents/src/v10/revocation.rs b/documents/src/v10/revocation.rs
index 26137d661ec1fa8114861e926e386c3b7e153d82..c070a49c424d4c3321feb738343a231da2542b94 100644
--- a/documents/src/v10/revocation.rs
+++ b/documents/src/v10/revocation.rs
@@ -65,6 +65,38 @@ pub struct RevocationDocument {
     signatures: Vec<Sig>,
 }
 
+#[derive(Clone, Debug, Deserialize, Hash, Serialize, PartialEq, Eq)]
+/// Revocation document for jsonification
+pub struct RevocationStringDocument {
+    /// Name of the currency.
+    currency: String,
+    /// Document issuer
+    issuer: String,
+    /// Username of target identity
+    identity_username: String,
+    /// Target Identity document blockstamp.
+    identity_blockstamp: String,
+    /// Target Identity document signature.
+    identity_sig: String,
+    /// Document signature
+    signature: String,
+}
+
+impl ToStringObject for RevocationDocument {
+    type StringObject = RevocationStringDocument;
+    /// Transforms an object into a json object
+    fn to_string_object(&self) -> RevocationStringDocument {
+        RevocationStringDocument {
+            currency: self.currency.clone(),
+            issuer: format!("{}", self.issuers[0]),
+            identity_username: self.identity_username.clone(),
+            identity_blockstamp: format!("{}", self.identity_blockstamp),
+            identity_sig: format!("{}", self.identity_sig),
+            signature: format!("{}", self.signatures[0]),
+        }
+    }
+}
+
 impl RevocationDocument {
     /// Username of target identity
     pub fn identity_username(&self) -> &str {
@@ -189,7 +221,7 @@ IdtySignature: {idty_sig}
 #[derive(Debug, Clone, Copy)]
 pub struct RevocationDocumentParser;
 
-impl TextDocumentParser for RevocationDocumentParser {
+impl TextDocumentParser<Rule> for RevocationDocumentParser {
     type DocumentType = RevocationDocument;
 
     fn parse(doc: &str) -> Result<Self::DocumentType, TextDocumentParseError> {
diff --git a/documents/src/v10/transaction.rs b/documents/src/v10/transaction.rs
index a3878a290579e4214dce47c417e4daa384ac8f45..fe61bca114fc66c542507d6fd0ce57a21ead75ef 100644
--- a/documents/src/v10/transaction.rs
+++ b/documents/src/v10/transaction.rs
@@ -509,6 +509,66 @@ pub struct TransactionDocument {
     hash: Option<Hash>,
 }
 
+#[derive(Clone, Debug, Deserialize, Hash, Serialize, PartialEq, Eq)]
+/// Transaction document stringifed
+pub struct TransactionDocumentStringified {
+    /// Currency.
+    currency: String,
+    /// Blockstamp
+    blockstamp: String,
+    /// Locktime
+    locktime: u64,
+    /// Document issuer (there should be only one).
+    issuers: Vec<String>,
+    /// Transaction inputs.
+    inputs: Vec<String>,
+    /// Inputs unlocks.
+    unlocks: Vec<String>,
+    /// Transaction outputs.
+    outputs: Vec<String>,
+    /// Transaction comment
+    comment: String,
+    /// Document signature (there should be only one).
+    signatures: Vec<String>,
+    /// Transaction hash
+    hash: Option<String>,
+}
+
+impl ToStringObject for TransactionDocument {
+    type StringObject = TransactionDocumentStringified;
+    /// Transforms an object into a json object
+    fn to_string_object(&self) -> TransactionDocumentStringified {
+        TransactionDocumentStringified {
+            currency: self.currency.clone(),
+            blockstamp: format!("{}", self.blockstamp),
+            locktime: self.locktime,
+            issuers: self.issuers.iter().map(|p| format!("{}", p)).collect(),
+            inputs: self
+                .inputs
+                .iter()
+                .map(TransactionInput::to_string)
+                .collect(),
+            unlocks: self
+                .unlocks
+                .iter()
+                .map(TransactionInputUnlocks::to_string)
+                .collect(),
+            outputs: self
+                .outputs
+                .iter()
+                .map(TransactionOutput::to_string)
+                .collect(),
+            comment: self.comment.clone(),
+            signatures: self.signatures.iter().map(|s| format!("{}", s)).collect(),
+            hash: if let Some(hash) = self.hash {
+                Some(hash.to_string())
+            } else {
+                None
+            },
+        }
+    }
+}
+
 impl TransactionDocument {
     /// Compute transaction hash
     pub fn compute_hash(&mut self) -> Hash {
@@ -758,7 +818,7 @@ Issuers:
 #[derive(Debug, Clone, Copy)]
 pub struct TransactionDocumentParser;
 
-impl TextDocumentParser for TransactionDocumentParser {
+impl TextDocumentParser<Rule> for TransactionDocumentParser {
     type DocumentType = TransactionDocument;
 
     fn parse(doc: &str) -> Result<Self::DocumentType, TextDocumentParseError> {
diff --git a/network-documents/Cargo.toml b/network-documents/Cargo.toml
index f0699f1f316730ab8b49ef059dbdf90e31091f4a..9149de41c496be9ebb3f78f67ae5b93356c2d00d 100644
--- a/network-documents/Cargo.toml
+++ b/network-documents/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "durs-network-documents"
-version = "0.2.0-b1"
+version = "0.3.0"
 authors = ["librelois <elois@duniter.org>"]
 description = "Network documents for DUNP (DUniter Network Protocol)"
 license = "AGPL-3.0"
diff --git a/network-documents/src/lib.rs b/network-documents/src/lib.rs
index ab80b8b3ab3718999a59c0c934ca4f961c600667..d9a0440114da23ebaac187aa80a5e2baed8d2e44 100644
--- a/network-documents/src/lib.rs
+++ b/network-documents/src/lib.rs
@@ -47,8 +47,15 @@ pub mod network_head_v2;
 pub mod network_head_v3;
 pub mod network_peer;
 
+use dubp_documents::{TextDocumentParseError, TextDocumentParser};
 use dup_crypto::hashs::*;
 use dup_crypto::keys::*;
+use network_head::NetworkHead;
+use network_head_v3::NetworkHeadV3;
+use network_peer::PeerCard;
+use network_peer::PeerCardV11;
+use pest::iterators::Pair;
+use pest::Parser;
 use std::fmt::{Display, Error, Formatter};
 
 #[derive(Parser)]
@@ -56,6 +63,39 @@ use std::fmt::{Display, Error, Formatter};
 /// Parser for network documents
 struct NetworkDocsParser;
 
+#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
+/// Network document
+pub enum NetworkDocument {
+    /// Peer
+    Peer(Box<PeerCard>),
+    /// Head
+    Head(NetworkHead),
+}
+
+impl TextDocumentParser<Rule> for NetworkDocument {
+    type DocumentType = NetworkDocument;
+
+    fn parse(doc: &str) -> Result<NetworkDocument, TextDocumentParseError> {
+        match NetworkDocsParser::parse(Rule::network_document, doc) {
+            Ok(mut net_doc_pairs) => Ok(NetworkDocument::from_pest_pair(
+                net_doc_pairs.next().unwrap().into_inner().next().unwrap(),
+            )), // get and unwrap the `network_document` rule; never fails
+            Err(pest_error) => Err(TextDocumentParseError::PestError(format!("{}", pest_error))),
+        }
+    }
+    fn from_pest_pair(pair: Pair<Rule>) -> NetworkDocument {
+        match pair.as_rule() {
+            Rule::peer_v11 => {
+                NetworkDocument::Peer(Box::new(PeerCard::V11(PeerCardV11::from_pest_pair(pair))))
+            }
+            Rule::head_v3 => NetworkDocument::Head(NetworkHead::V3(Box::new(
+                NetworkHeadV3::from_pest_pair(pair),
+            ))),
+            _ => panic!("unexpected rule: {:?}", pair.as_rule()), // Grammar ensures that we never reach this line
+        }
+    }
+}
+
 #[derive(Debug, Clone, PartialEq, Eq)]
 /// ParseError
 pub enum ParseError {
diff --git a/network-documents/src/network_documents.pest b/network-documents/src/network_documents.pest
index 5461807299b8949616d2d5c7312cd65de0d80761..112af2fda22cb587a07c4a0b515b82889c9a42c6 100644
--- a/network-documents/src/network_documents.pest
+++ b/network-documents/src/network_documents.pest
@@ -97,3 +97,7 @@ head_v3 = ${
     ed25519_sig? ~
     (nl ~ step)?
 }
+
+// Network document rule
+network_document_inner =  _{ head_v3 | peer_v11 }
+network_document = ${ SOI ~ network_document_inner ~ EOI }
\ No newline at end of file
diff --git a/network-documents/src/network_head_v3.rs b/network-documents/src/network_head_v3.rs
index 04be52130e7dfb3d732dcbb83aa485a05a7fa673..bb8be85b4a9435a4b3c523b249b358f34164b4cc 100644
--- a/network-documents/src/network_head_v3.rs
+++ b/network-documents/src/network_head_v3.rs
@@ -17,7 +17,7 @@
 
 use base58::ToBase58;
 use dubp_documents::blockstamp::Blockstamp;
-use dubp_documents::{BlockHash, BlockId, CurrencyName, ToJsonObject};
+use dubp_documents::{BlockHash, BlockId, CurrencyName, ToStringObject};
 use dup_crypto::keys::text_signable::TextSignable;
 use dup_crypto::keys::*;
 use pest::iterators::Pair;
@@ -105,17 +105,19 @@ impl TextSignable for NetworkHeadV3 {
     }
 }
 
-impl NetworkHeadV3 {
-    /// parse from raw ascii format
-    pub fn parse_from_raw(raw_peer: &str) -> Result<NetworkHeadV3, ParseError> {
-        match NetworkDocsParser::parse(Rule::head_v3, raw_peer) {
+impl TextDocumentParser<Rule> for NetworkHeadV3 {
+    /// Type of document generated by the parser
+    type DocumentType = NetworkHeadV3;
+
+    fn parse(doc: &str) -> Result<NetworkHeadV3, TextDocumentParseError> {
+        match NetworkDocsParser::parse(Rule::head_v3, doc) {
             Ok(mut head_v3_pairs) => {
                 Ok(NetworkHeadV3::from_pest_pair(head_v3_pairs.next().unwrap()))
             }
-            Err(pest_error) => Err(ParseError::PestError(format!("{}", pest_error))),
+            Err(pest_error) => Err(TextDocumentParseError::PestError(format!("{}", pest_error))),
         }
     }
-    /// Generate from pest pair
+
     fn from_pest_pair(pair: Pair<Rule>) -> NetworkHeadV3 {
         let mut currency_str = "";
         let mut api_outgoing_conf = 0;
@@ -183,48 +185,23 @@ impl NetworkHeadV3 {
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
 /// Head V3 for json serializer
-pub struct JsonHeadV3 {
-    /// WS2P Private configuration
-    pub api_outgoing_conf: u8,
-    /// WS2P Public configuration
-    pub api_incoming_conf: u8,
-    /// Issuer node free member rooms
-    pub free_member_rooms: u8,
-    /// Issuer node free mirror rooms
-    pub free_mirror_rooms: u8,
-    /// Issuer node id
-    pub node_id: NodeId,
-    /// Issuer key algorithm
-    pub algorithm: KeysAlgo,
-    /// Issuer pubkey
-    pub pubkey: String,
-    /// Head blockstamp
-    pub blockstamp: String,
-    /// Issuer node software
-    pub software: String,
-    /// Issuer node soft version
-    pub soft_version: String,
+pub struct HeadV3Stringified {
+    /// Head body
+    pub body: String,
     /// Issuer signature
     pub signature: Option<String>,
     /// Head step
     pub step: u8,
 }
 
-impl<'a> ToJsonObject for NetworkHeadV3 {
-    type JsonObject = JsonHeadV3;
+impl<'a> ToStringObject for NetworkHeadV3 {
+    type StringObject = HeadV3Stringified;
 
-    fn to_json_object(&self) -> Self::JsonObject {
-        JsonHeadV3 {
-            api_outgoing_conf: self.api_outgoing_conf,
-            api_incoming_conf: self.api_incoming_conf,
-            free_member_rooms: self.free_member_rooms,
-            free_mirror_rooms: self.free_mirror_rooms,
-            node_id: self.node_id,
-            algorithm: self.pubkey.algo(),
-            pubkey: self.pubkey.to_base58(),
-            blockstamp: self.blockstamp.to_string(),
-            software: self.software.clone(),
-            soft_version: self.soft_version.clone(),
+    fn to_string_object(&self) -> Self::StringObject {
+        let body = self.as_signable_text();
+        let body_len = body.len();
+        HeadV3Stringified {
+            body: body.chars().take(body_len - 1).collect(),
             signature: if let Some(sig) = self.signature {
                 Some(sig.to_base64())
             } else {
@@ -266,7 +243,7 @@ mod tests {
             println!("{}", head_v3_raw);
             assert_eq!(
                 head_v3,
-                NetworkHeadV3::parse_from_raw(&head_v3_raw).expect("Fail to parse head v3 !")
+                NetworkHeadV3::parse(&head_v3_raw).expect("Fail to parse head v3 !")
             )
         } else {
             panic!("fail to sign head v3 : {:?}", sign_result.err().unwrap())
diff --git a/network-documents/src/network_peer.rs b/network-documents/src/network_peer.rs
index 134ef7e74a356b8dd63fabc22550097ec27963bf..c4b93afa8f918ebe59a44126e8b15777e34ba181 100644
--- a/network-documents/src/network_peer.rs
+++ b/network-documents/src/network_peer.rs
@@ -20,6 +20,7 @@ extern crate dup_crypto;
 extern crate serde;
 
 use base58::ToBase58;
+use dubp_documents::ToStringObject;
 use dubp_documents::{blockstamp::Blockstamp, CurrencyName};
 use dubp_documents::{BlockHash, BlockId};
 use dup_crypto::keys::text_signable::TextSignable;
@@ -29,7 +30,7 @@ use pest::iterators::Pair;
 use pest::Parser;
 use *;
 
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
 /// Peer card V10
 pub struct PeerCardV10 {
     /// Peer card Blockstamp
@@ -59,6 +60,45 @@ pub struct PeerCardV11 {
     pub sig: Option<Sig>,
 }
 
+#[derive(Clone, Debug, Deserialize, Hash, Serialize, PartialEq, Eq)]
+/// identity document for jsonification
+pub struct PeerCardV11Stringified {
+    /// Currency name
+    pub currency_name: String,
+    /// Peer card issuer
+    pub issuer: String,
+    /// Issuer node id
+    pub node_id: String,
+    /// Peer card Blockstamp
+    pub blockstamp: String,
+    /// Peer card string endpoints
+    pub endpoints: Vec<String>,
+    /// Signature
+    pub sig: String,
+}
+
+impl ToStringObject for PeerCardV11 {
+    type StringObject = PeerCardV11Stringified;
+    /// Transforms an object into a json object
+    fn to_string_object(&self) -> PeerCardV11Stringified {
+        let mut endpoints: Vec<String> = self.endpoints.iter().map(EndpointV2::to_string).collect();
+        endpoints.extend_from_slice(&self.endpoints_str);
+
+        PeerCardV11Stringified {
+            currency_name: self.currency_name.0.clone(),
+            issuer: format!("{}", self.issuer),
+            node_id: format!("{}", self.node_id),
+            blockstamp: format!("{}", self.blockstamp),
+            endpoints,
+            sig: if let Some(sig) = self.sig {
+                format!("{}", sig)
+            } else {
+                "".to_owned()
+            },
+        }
+    }
+}
+
 impl TextSignable for PeerCardV11 {
     fn as_signable_text(&self) -> String {
         format!(
@@ -92,17 +132,18 @@ impl TextSignable for PeerCardV11 {
     }
 }
 
-impl PeerCardV11 {
-    /// parse from raw ascii format
-    pub fn parse_from_raw(raw_peer: &str) -> Result<PeerCardV11, ParseError> {
-        match NetworkDocsParser::parse(Rule::peer_v11, raw_peer) {
+impl TextDocumentParser<Rule> for PeerCardV11 {
+    type DocumentType = PeerCardV11;
+
+    fn parse(doc: &str) -> Result<Self::DocumentType, TextDocumentParseError> {
+        match NetworkDocsParser::parse(Rule::peer_v11, doc) {
             Ok(mut peer_v11_pairs) => {
                 Ok(PeerCardV11::from_pest_pair(peer_v11_pairs.next().unwrap()))
             }
-            Err(pest_error) => Err(ParseError::PestError(format!("{}", pest_error))),
+            Err(pest_error) => Err(TextDocumentParseError::PestError(format!("{}", pest_error))),
         }
     }
-    /// Generate from pest pair
+
     fn from_pest_pair(pair: Pair<Rule>) -> PeerCardV11 {
         let mut currency_str = "";
         let mut node_id = NodeId(0);
@@ -150,6 +191,9 @@ impl PeerCardV11 {
             sig,
         }
     }
+}
+
+impl PeerCardV11 {
     /// Convert to JSON String
     pub fn to_json_peer(&self) -> Result<String, serde_json::Error> {
         Ok(serde_json::to_string_pretty(&JsonPeerCardV11 {
@@ -190,7 +234,7 @@ pub struct JsonPeerCardV11<'a> {
     pub signature: Option<String>,
 }
 
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
 /// Peer card
 pub enum PeerCard {
     /// Peer card V10
@@ -280,8 +324,7 @@ mod tests {
             println!("{}", peer_card_v11_raw);
             assert_eq!(
                 peer_card_v11,
-                PeerCardV11::parse_from_raw(&peer_card_v11_raw)
-                    .expect("Fail to parse peer card v11 !")
+                PeerCardV11::parse(&peer_card_v11_raw).expect("Fail to parse peer card v11 !")
             )
         } else {
             panic!("fail to sign peer card : {:?}", sign_result.err().unwrap())