diff --git a/src/main/java/it/inaf/oats/vospace/CreateNodeController.java b/src/main/java/it/inaf/oats/vospace/CreateNodeController.java
index 5c124efe3909508a4df3d11c919d3245a061ad6d..759af9ffa271a04cb383b43594eb320622fdbcbd 100644
--- a/src/main/java/it/inaf/oats/vospace/CreateNodeController.java
+++ b/src/main/java/it/inaf/oats/vospace/CreateNodeController.java
@@ -6,6 +6,9 @@
 package it.inaf.oats.vospace;
 
 import it.inaf.ia2.aa.data.User;
+import it.inaf.oats.vospace.exception.InvalidArgumentException;
+import it.inaf.oats.vospace.exception.InvalidURIException;
+import net.ivoa.xml.vospace.v2.LinkNode;
 import net.ivoa.xml.vospace.v2.Node;
 import org.springframework.http.MediaType;
 import org.springframework.web.bind.annotation.RequestBody;
@@ -14,6 +17,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.PutMapping;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
 
 @RestController
 public class CreateNodeController extends BaseNodeController {
@@ -23,6 +27,9 @@ public class CreateNodeController extends BaseNodeController {
     @Autowired
     private CreateNodeService createNodeService;
 
+    @Value("${vospace-authority}")
+    private String authority;
+
     @PutMapping(value = {"/nodes", "/nodes/**"},
             consumes = {MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE, MediaType.APPLICATION_JSON_VALUE},
             produces = {MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE, MediaType.APPLICATION_JSON_VALUE})
@@ -32,8 +39,36 @@ public class CreateNodeController extends BaseNodeController {
 
         LOG.debug("createNodeController called for node with URI {} and PATH {}", node.getUri(), path);
 
+        // Get Node path (and validates it too)
+        String decodedURIPathFromNode = URIUtils.returnVosPathFromNodeURI(node.getUri(), authority);
+
+        LOG.debug("createNodeController URI: {} decoded as {}", node.getUri(), decodedURIPathFromNode);
+
+        // Check if payload URI is consistent with http request
+        if (!decodedURIPathFromNode.equals(path)) {
+            throw new InvalidURIException(decodedURIPathFromNode, path);
+        }
+
+        // validate format of input node
+        this.validateInputNode(node);
+
         return createNodeService.createNode(node, path, principal);
 
     }
 
+    private void validateInputNode(Node node) {
+
+        if (node instanceof LinkNode) {
+            LinkNode linkNode = (LinkNode) node;
+            String target = linkNode.getTarget();
+            // I validate it here to add context easily
+            if (target == null) {
+                throw new InvalidArgumentException("LinkNode in payload has no target element specified");
+            }
+
+            URIUtils.returnVosPathFromNodeURI(linkNode.getTarget(), authority);
+        }
+
+    }
+
 }
diff --git a/src/main/java/it/inaf/oats/vospace/CreateNodeService.java b/src/main/java/it/inaf/oats/vospace/CreateNodeService.java
index 516f110643e7fdcb2e108527a740a938d6e61b72..83e4dfcac8a942f554bc08a2a73750c3723b274a 100644
--- a/src/main/java/it/inaf/oats/vospace/CreateNodeService.java
+++ b/src/main/java/it/inaf/oats/vospace/CreateNodeService.java
@@ -10,7 +10,6 @@ import it.inaf.oats.vospace.datamodel.NodeProperties;
 import it.inaf.oats.vospace.datamodel.NodeUtils;
 import it.inaf.oats.vospace.exception.ContainerNotFoundException;
 import it.inaf.oats.vospace.exception.DuplicateNodeException;
-import it.inaf.oats.vospace.exception.InvalidURIException;
 import it.inaf.oats.vospace.exception.LinkFoundException;
 import it.inaf.oats.vospace.exception.PermissionDeniedException;
 import it.inaf.oats.vospace.persistence.NodeDAO;
@@ -19,7 +18,6 @@ import net.ivoa.xml.vospace.v2.Property;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.EnableTransactionManagement;
 
@@ -30,25 +28,12 @@ public class CreateNodeService {
     @Autowired
     private NodeDAO nodeDao;
 
-    @Value("${vospace-authority}")
-    private String authority;
-
     private static final Logger LOG = LoggerFactory.getLogger(CreateNodeService.class);
 
     public Node createNode(Node node, String path, User principal) {
         
         LOG.debug("createNodeService called for node with URI {} and PATH {}", node.getUri(), path);
         
-        // Get Node path (and validates it too)
-        String decodedURIPathFromNode = URIUtils.returnVosPathFromNodeURI(node.getUri(), authority);       
-        
-        LOG.debug("createNodeService URI: {} decoded as {}", node.getUri(), decodedURIPathFromNode);
-
-        // Check if payload URI is consistent with http request
-        if (!decodedURIPathFromNode.equals(path)) {
-            throw new InvalidURIException(decodedURIPathFromNode, path);
-        }
-
         // Check if another node is already present at specified path
         // This checks if the user is trying to insert the root node at "/" too
         if (nodeDao.listNode(path).isPresent()) {
diff --git a/src/main/java/it/inaf/oats/vospace/URIUtils.java b/src/main/java/it/inaf/oats/vospace/URIUtils.java
index dbfedf21627bf115b76befd9ca8717e079bff738..0250050fd271a772725b8a1097f4a63a367c1f94 100644
--- a/src/main/java/it/inaf/oats/vospace/URIUtils.java
+++ b/src/main/java/it/inaf/oats/vospace/URIUtils.java
@@ -51,6 +51,10 @@ public class URIUtils {
         String resultPath = null;
 
         try {
+            
+            if(nodeURI == null)
+                throw new IllegalArgumentException("URI string is null");
+            
             URI uri = new URI(nodeURI);
 
             // Check scheme
@@ -88,7 +92,7 @@ public class URIUtils {
 
         } catch (URISyntaxException e) {
             throw new InvalidURIException(nodeURI);
-        }
+        } 
 
         return resultPath;
 
diff --git a/src/test/java/it/inaf/oats/vospace/CreateNodeControllerTest.java b/src/test/java/it/inaf/oats/vospace/CreateNodeControllerTest.java
index dc3d24526db6033f35130e1baa1845a860345f93..f9dcff79ee7bb9fbbc6ae1928e4ea1ad95796a11 100644
--- a/src/test/java/it/inaf/oats/vospace/CreateNodeControllerTest.java
+++ b/src/test/java/it/inaf/oats/vospace/CreateNodeControllerTest.java
@@ -30,6 +30,7 @@ import org.springframework.boot.test.mock.mockito.SpyBean;
 import net.ivoa.xml.vospace.v2.ContainerNode;
 import net.ivoa.xml.vospace.v2.LinkNode;
 import java.util.List;
+import java.util.Objects;
 import java.util.Optional;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -44,17 +45,17 @@ import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMock
 @TestPropertySource(properties = "spring.main.allow-bean-definition-overriding=true")
 @AutoConfigureMockMvc
 public class CreateNodeControllerTest {
-    
+
     @MockBean
     private NodeDAO nodeDao;
-    
+
     @SpyBean
     @Autowired
     private CreateNodeController controller;
-    
+
     @Autowired
     private MockMvc mockMvc;
-    
+
     private ContainerNode getContainerParentNode(String path) {
         ContainerNode parentNode = new ContainerNode();
         // Set parent node address at /
@@ -66,7 +67,7 @@ public class CreateNodeControllerTest {
         parentNode.setProperties(List.of(groups));
         return parentNode;
     }
-    
+
     private ContainerNode getContainerParentNodeWithCreator(String path) {
         ContainerNode parentNode = new ContainerNode();
         // Set parent node address at /
@@ -77,7 +78,7 @@ public class CreateNodeControllerTest {
         parentNode.setProperties(List.of(creator));
         return parentNode;
     }
-    
+
     private LinkNode getLinkParentNode(String path) {
         LinkNode parentNode = new LinkNode();
         // Set parent node address at /
@@ -89,15 +90,15 @@ public class CreateNodeControllerTest {
         parentNode.setProperties(List.of(groups));
         return parentNode;
     }
-    
+
     @Test
     public void testFromJsonToXml() throws Exception {
         String requestBody
                 = getResourceFileContent("create-unstructured-data-node.json");
-        
+
         when(nodeDao.listNode(eq("/")))
                 .thenReturn(Optional.of(getContainerParentNode("/")));
-        
+
         mockMvc.perform(put("/nodes/mydata1")
                 .header("Authorization", "Bearer user2_token")
                 .content(requestBody)
@@ -105,17 +106,17 @@ public class CreateNodeControllerTest {
                 .accept(MediaType.APPLICATION_XML))
                 .andDo(print())
                 .andExpect(status().isOk());
-        
+
         verifyArguments();
     }
-    
+
     @Test
     public void testFromXmlToJson() throws Exception {
         String requestBody = getResourceFileContent("create-unstructured-data-node.xml");
-        
+
         when(nodeDao.listNode(eq("/")))
                 .thenReturn(Optional.of(getContainerParentNode("/")));
-        
+
         mockMvc.perform(put("/nodes/mydata1")
                 .header("Authorization", "Bearer user2_token")
                 .content(requestBody)
@@ -123,18 +124,18 @@ public class CreateNodeControllerTest {
                 .accept(MediaType.APPLICATION_JSON))
                 .andDo(print())
                 .andExpect(status().isOk());
-        
+
         verifyArguments();
         verify(nodeDao, times(1)).createNode(any());
     }
-    
+
     @Test
     public void testFromXmlToXml() throws Exception {
         String requestBody = getResourceFileContent("create-unstructured-data-node.xml");
-        
+
         when(nodeDao.listNode(eq("/")))
                 .thenReturn(Optional.of(getContainerParentNode("/")));
-        
+
         mockMvc.perform(put("/nodes/mydata1")
                 .header("Authorization", "Bearer user2_token")
                 .content(requestBody)
@@ -142,18 +143,18 @@ public class CreateNodeControllerTest {
                 .accept(MediaType.APPLICATION_XML))
                 .andDo(print())
                 .andExpect(status().isOk());
-        
+
         verifyArguments();
         verify(nodeDao, times(1)).createNode(any());
     }
-    
+
     @Test
     public void testFromJsonToJson() throws Exception {
         String requestBody = getResourceFileContent("create-unstructured-data-node.json");
-        
+
         when(nodeDao.listNode(eq("/")))
                 .thenReturn(Optional.of(getContainerParentNode("/")));
-        
+
         mockMvc.perform(put("/nodes/mydata1")
                 .header("Authorization", "Bearer user2_token")
                 .content(requestBody)
@@ -161,18 +162,18 @@ public class CreateNodeControllerTest {
                 .accept(MediaType.APPLICATION_JSON))
                 .andDo(print())
                 .andExpect(status().isOk());
-        
+
         verifyArguments();
         verify(nodeDao, times(1)).createNode(any());
     }
-    
+
     @Test
     public void testURIConsistence() throws Exception {
         String requestBody = getResourceFileContent("create-unstructured-data-node.xml");
-        
+
         when(nodeDao.listNode(eq("/")))
                 .thenReturn(Optional.of(getContainerParentNode("/")));
-        
+
         mockMvc.perform(put("/nodes/mydata2")
                 .header("Authorization", "Bearer user2_token")
                 .content(requestBody)
@@ -180,20 +181,77 @@ public class CreateNodeControllerTest {
                 .accept(MediaType.APPLICATION_XML))
                 .andDo(print())
                 .andExpect(status().is4xxClientError());
-        
+
         verifyArguments();
-        
+
+    }
+
+    @Test
+    public void testCreateInternalLinkNode() throws Exception {
+        String requestBody = getResourceFileContent("create-internal-link-node.xml");
+
+        when(nodeDao.listNode(eq("/")))
+                .thenReturn(Optional.of(getContainerParentNode("/")));
+
+        mockMvc.perform(put("/nodes/myInternalLink")
+                .header("Authorization", "Bearer user2_token")
+                .content(requestBody)
+                .contentType(MediaType.APPLICATION_XML)
+                .accept(MediaType.APPLICATION_XML))
+                .andDo(print())
+                .andExpect(status().isOk());
+
+        verifyLinkArguments("vos://example.com!vospace/myDummyDataNode1");
+
+    }
+
+    @Test
+    public void testCreateExternalLinkNode() throws Exception {
+        String requestBody = getResourceFileContent("create-external-link-node.xml");
+
+        when(nodeDao.listNode(eq("/")))
+                .thenReturn(Optional.of(getContainerParentNode("/")));
+
+        mockMvc.perform(put("/nodes/myExternalLink")
+                .header("Authorization", "Bearer user2_token")
+                .content(requestBody)
+                .contentType(MediaType.APPLICATION_XML)
+                .accept(MediaType.APPLICATION_XML))
+                .andDo(print())
+                .andExpect(status().is4xxClientError());
+
+        verifyLinkArguments("vos://external.com!vospace/myDummyDataNode1");
+
+    }
+
+    @Test
+    public void testCreateLinkNodeNoTarget() throws Exception {
+        String requestBody = getResourceFileContent("create-link-node-notarget.xml");
+
+        when(nodeDao.listNode(eq("/")))
+                .thenReturn(Optional.of(getContainerParentNode("/")));
+
+        mockMvc.perform(put("/nodes/myNoTargetLink")
+                .header("Authorization", "Bearer user2_token")
+                .content(requestBody)
+                .contentType(MediaType.APPLICATION_XML)
+                .accept(MediaType.APPLICATION_XML))
+                .andDo(print())
+                .andExpect(status().is4xxClientError());
+
+        verifyLinkArguments(null);
+
     }
-    
+
     @Test
     public void testNodeAlreadyExisting() throws Exception {
         String requestBody = getResourceFileContent("create-unstructured-data-node.xml");
-        
+
         when(nodeDao.listNode(eq("/")))
                 .thenReturn(Optional.of(getContainerParentNode("/")));
         when(nodeDao.listNode(eq("/mydata1")))
                 .thenReturn(Optional.of(getContainerParentNode("/mydata1")));
-        
+
         mockMvc.perform(put("/nodes/mydata1")
                 .header("Authorization", "Bearer user2_token")
                 .content(requestBody)
@@ -201,17 +259,17 @@ public class CreateNodeControllerTest {
                 .accept(MediaType.APPLICATION_XML))
                 .andDo(print())
                 .andExpect(status().is4xxClientError());
-        
+
         verifyArguments();
     }
-    
+
     @Test
     public void testContainerNotFound() throws Exception {
         String requestBody = getResourceFileContent("create-unstructured-data-node.xml");
-        
+
         when(nodeDao.listNode(eq("/")))
                 .thenReturn(Optional.ofNullable(null));
-        
+
         mockMvc.perform(put("/nodes/mydata1")
                 .header("Authorization", "Bearer user2_token")
                 .content(requestBody)
@@ -219,17 +277,17 @@ public class CreateNodeControllerTest {
                 .accept(MediaType.APPLICATION_XML))
                 .andDo(print())
                 .andExpect(status().is4xxClientError());
-        
+
         verifyArguments();
     }
-    
+
     @Test
     public void testLinkNodeFound() throws Exception {
         String requestBody = getResourceFileContent("create-unstructured-data-node.xml");
-        
+
         when(nodeDao.listNode(eq("/")))
                 .thenReturn(Optional.of(getLinkParentNode("/")));
-        
+
         mockMvc.perform(put("/nodes/mydata1")
                 .header("Authorization", "Bearer user2_token")
                 .content(requestBody)
@@ -237,17 +295,17 @@ public class CreateNodeControllerTest {
                 .accept(MediaType.APPLICATION_XML))
                 .andDo(print())
                 .andExpect(status().is4xxClientError());
-        
+
         verifyArguments();
     }
-    
+
     @Test
     public void testPermissionDenied() throws Exception {
         String requestBody = getResourceFileContent("create-unstructured-data-node.xml");
-        
+
         when(nodeDao.listNode(eq("/")))
                 .thenReturn(Optional.of(getContainerParentNode("/")));
-        
+
         mockMvc.perform(put("/nodes/mydata1")
                 .header("Authorization", "Bearer user1_token")
                 .content(requestBody)
@@ -255,17 +313,17 @@ public class CreateNodeControllerTest {
                 .accept(MediaType.APPLICATION_XML))
                 .andDo(print())
                 .andExpect(status().is4xxClientError());
-        
+
         verifyArguments();
     }
-    
+
     @Test
     public void testWriteWithOnlyOwnership() throws Exception {
         String requestBody = getResourceFileContent("create-unstructured-data-node.xml");
-        
+
         when(nodeDao.listNode(eq("/")))
                 .thenReturn(Optional.of(getContainerParentNodeWithCreator("/")));
-        
+
         mockMvc.perform(put("/nodes/mydata1")
                 .header("Authorization", "Bearer user2_token")
                 .content(requestBody)
@@ -273,16 +331,16 @@ public class CreateNodeControllerTest {
                 .accept(MediaType.APPLICATION_XML))
                 .andDo(print())
                 .andExpect(status().is2xxSuccessful());
-        
+
         verifyArguments();
         verify(nodeDao, times(1)).createNode(any());
     }
-    
+
     @Test
     public void testWriteOwnerAbsent() throws Exception {
         String requestBody
                 = getResourceFileContent("create-unstructured-data-node.xml");
-        
+
         when(nodeDao.listNode(eq("/")))
                 .thenReturn(Optional.of(getContainerParentNodeWithCreator("/")));
 
@@ -300,18 +358,18 @@ public class CreateNodeControllerTest {
             UnstructuredDataNode udn = (UnstructuredDataNode) node;
             String creator = NodeProperties.getNodePropertyByURI(
                     udn, NodeProperties.CREATOR_URI);
-            return (creator != null && creator.equals("user2"));            
+            return (creator != null && creator.equals("user2"));
         }));
-        
+
     }
-    
+
     @Test
     public void testGroupPropertiesAbsent() throws Exception {
         String requestBody
                 = getResourceFileContent("create-unstructured-data-node.xml");
-        
+
         ContainerNode cdn = getContainerParentNode("/");
-        
+
         when(nodeDao.listNode(eq("/")))
                 .thenReturn(Optional.of(cdn));
 
@@ -331,16 +389,16 @@ public class CreateNodeControllerTest {
                     udn, NodeProperties.GROUP_READ_URI);
             String groupWrite = NodeProperties.getNodePropertyByURI(
                     udn, NodeProperties.GROUP_WRITE_URI);
-            return (groupRead == null && groupWrite.equals("group1 group2"));            
+            return (groupRead == null && groupWrite.equals("group1 group2"));
         }));
-        
+
     }
-    
+
     @Test
     public void testWriteOwnerMismatch() throws Exception {
         String requestBody
                 = getResourceFileContent("create-unstructured-data-node-user1.xml");
-        
+
         when(nodeDao.listNode(eq("/")))
                 .thenReturn(Optional.of(getContainerParentNodeWithCreator("/")));
 
@@ -354,15 +412,15 @@ public class CreateNodeControllerTest {
                 .andExpect(status().is4xxClientError());
 
         // assert createNode is not called
-        verify(nodeDao, times(0)).createNode(any());        
+        verify(nodeDao, times(0)).createNode(any());
     }
-    
+
     @Test
     public void testSubPath() throws Exception {
-        
+
         String requestBody = getResourceFileContent("create-unstructured-data-node.xml")
                 .replace("/mydata1", "/mydata1/anothernode");
-        
+
         mockMvc.perform(put("/nodes/mydata1/anothernode")
                 .header("Authorization", "Bearer user2_token")
                 .content(requestBody)
@@ -373,19 +431,19 @@ public class CreateNodeControllerTest {
 
         // Using ArgumentCaptor for verifying multiple method invocations
         ArgumentCaptor<String> argCaptor = ArgumentCaptor.forClass(String.class);
-        
+
         verify(nodeDao, times(2)).listNode(argCaptor.capture());
-        
+
         assertEquals("/mydata1/anothernode", argCaptor.getAllValues().get(0));
         assertEquals("/mydata1", argCaptor.getAllValues().get(1));
     }
-    
+
     @Test
     public void testIllegalChars() throws Exception {
-        
+
         String requestBody = getResourceFileContent("create-unstructured-data-node.xml")
                 .replace("/mydata1", "/mydata1/?anothernode");
-        
+
         String message = mockMvc.perform(put(new URI("/nodes/mydata1/%3Fanothernode"))
                 .header("Authorization", "Bearer user2_token")
                 .content(requestBody)
@@ -394,10 +452,10 @@ public class CreateNodeControllerTest {
                 .andDo(print())
                 .andExpect(status().isBadRequest())
                 .andReturn().getResolvedException().getMessage();
-        
+
         assertTrue(message.contains("contains an illegal character"));
     }
-    
+
     private void verifyArguments() {
         verify(controller).createNode(
                 argThat(node -> {
@@ -408,7 +466,19 @@ public class CreateNodeControllerTest {
                             && "ivo://ivoa.net/vospace/core#description".equals(property.getUri());
                 }), any());
     }
-    
+
+    private void verifyLinkArguments(String target) {
+        verify(controller).createNode(
+                argThat(node -> {
+                    LinkNode linkNode = (LinkNode) node;
+                    Property property = linkNode.getProperties().get(0);
+                    return "vos:LinkNode".equals(linkNode.getType())
+                            && "test value".equals(property.getValue())
+                            && "ivo://ivoa.net/vospace/core#description".equals(property.getUri())
+                            && Objects.equals(target, linkNode.getTarget());
+                }), any());
+    }
+
     protected static String getResourceFileContent(String fileName) throws Exception {
         try (InputStream in = CreateNodeControllerTest.class.getClassLoader().getResourceAsStream(fileName)) {
             return new String(in.readAllBytes(), StandardCharsets.UTF_8);
diff --git a/src/test/java/it/inaf/oats/vospace/persistence/NodeDAOTest.java b/src/test/java/it/inaf/oats/vospace/persistence/NodeDAOTest.java
index c85b48a9aa93c7fb9a2503ad9257c93c4b3a5af5..1b07a7b29c265e14af1273e4e2cc3d923937b086 100644
--- a/src/test/java/it/inaf/oats/vospace/persistence/NodeDAOTest.java
+++ b/src/test/java/it/inaf/oats/vospace/persistence/NodeDAOTest.java
@@ -17,6 +17,7 @@ import java.util.Set;
 import javax.sql.DataSource;
 import net.ivoa.xml.vospace.v2.ContainerNode;
 import net.ivoa.xml.vospace.v2.DataNode;
+import net.ivoa.xml.vospace.v2.LinkNode;
 import net.ivoa.xml.vospace.v2.View;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import net.ivoa.xml.vospace.v2.Node;
@@ -65,6 +66,23 @@ public class NodeDAOTest {
         assertEquals(retrievedNode.getAccepts().get(0).getUri(), dataNode.getAccepts().get(0).getUri());
         assertEquals(retrievedNode.getProvides().get(0).getUri(), dataNode.getProvides().get(0).getUri());
     }
+    
+    @Test
+    public void testCreateLinkNode() {
+        LinkNode linkNode = new LinkNode();
+        
+        String target = "vos://example.com!vospace/myData1";
+
+        linkNode.setUri("vos://example.com!vospace/myLink1");
+        linkNode.setTarget(target);
+
+        dao.createNode(linkNode);
+                
+        Node retrievedNode = dao.listNode("/myLink1").get();
+        
+        assertTrue(retrievedNode instanceof LinkNode);
+        assertEquals(target, ((LinkNode) retrievedNode).getTarget());        
+    }
 
     @Test
     public void testListNode() {
diff --git a/src/test/resources/create-external-link-node.xml b/src/test/resources/create-external-link-node.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b723379943a1a995c88df2e4ca3046ed628a6a59
--- /dev/null
+++ b/src/test/resources/create-external-link-node.xml
@@ -0,0 +1,11 @@
+<vos:node xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xmlns:vos="http://www.ivoa.net/xml/VOSpace/v2.0" xsi:type="vos:LinkNode" uri="vos://example.com!vospace/myExternalLink">
+    <vos:properties>
+        <vos:property uri="ivo://ivoa.net/vospace/core#description">test value</vos:property>        
+    </vos:properties>
+    <vos:target>vos://external.com!vospace/myDummyDataNode1</vos:target>
+    <vos:accepts/>
+    <vos:provides/>
+    <vos:capabilities/>
+</vos:node>
\ No newline at end of file
diff --git a/src/test/resources/create-internal-link-node.xml b/src/test/resources/create-internal-link-node.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0d60b5f1e43b812d7ae1dc78ad91428f55a55859
--- /dev/null
+++ b/src/test/resources/create-internal-link-node.xml
@@ -0,0 +1,11 @@
+<vos:node xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xmlns:vos="http://www.ivoa.net/xml/VOSpace/v2.0" xsi:type="vos:LinkNode" uri="vos://example.com!vospace/myInternalLink">
+    <vos:properties>
+        <vos:property uri="ivo://ivoa.net/vospace/core#description">test value</vos:property>        
+    </vos:properties>
+    <vos:target>vos://example.com!vospace/myDummyDataNode1</vos:target>
+    <vos:accepts/>
+    <vos:provides/>
+    <vos:capabilities/>
+</vos:node>
\ No newline at end of file
diff --git a/src/test/resources/create-link-node-notarget.xml b/src/test/resources/create-link-node-notarget.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7ab5488311ab674cb72d678e9269cd649d0b37e6
--- /dev/null
+++ b/src/test/resources/create-link-node-notarget.xml
@@ -0,0 +1,10 @@
+<vos:node xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xmlns:vos="http://www.ivoa.net/xml/VOSpace/v2.0" xsi:type="vos:LinkNode" uri="vos://example.com!vospace/myNoTargetLink">
+    <vos:properties>
+        <vos:property uri="ivo://ivoa.net/vospace/core#description">test value</vos:property>        
+    </vos:properties>
+    <vos:accepts/>
+    <vos:provides/>
+    <vos:capabilities/>
+</vos:node>
\ No newline at end of file