diff --git a/ragconnect.base/src/main/jastadd/Errors.jrag b/ragconnect.base/src/main/jastadd/Errors.jrag
index bfee2545d4bee28223b04ce931ccd6a6429cf13f..cf001ac9d3b64181b58e9b1c461cba6e316d1370 100644
--- a/ragconnect.base/src/main/jastadd/Errors.jrag
+++ b/ragconnect.base/src/main/jastadd/Errors.jrag
@@ -7,32 +7,32 @@ aspect Errors {
     [new TreeSet<ErrorMessage>()]
     root RagConnect;
 
-    ReceiveFromMqttDefinition contributes error("Receive definition already defined for " + getToken().getName())
+    ReceiveTokenEndpointDefinition contributes error("Receive definition already defined for " + getToken().getName())
       when isAlreadyDefined()
       to RagConnect.errors();
 
-    ReceiveFromMqttDefinition contributes error("Receiving target token must not be an NTA token!")
+    ReceiveTokenEndpointDefinition contributes error("Receiving target token must not be an NTA token!")
       when getToken().getNTA()
       to RagConnect.errors();
 
     // if first mapping is null, then suitableDefaultMapping() == null
-    ReceiveFromMqttDefinition contributes error("No suitable default mapping found for type " +
+    ReceiveTokenEndpointDefinition contributes error("No suitable default mapping found for type " +
       ((getMappingList().isEmpty())
-        ? getToken().getJavaTypeUse().prettyPrint()
+        ? getToken().effectiveJavaTypeUse().prettyPrint()
         : getMappingList().get(0).getFromType().prettyPrint()))
       when effectiveMappings().get(0) == null
       to RagConnect.errors();
 
-    ReceiveFromMqttDefinition contributes error("to-type of last mapping must be type of the Token!")
-      when getToken().getJavaTypeUse().prettyPrint().equals(
-          effectiveMappings().get(effectiveMappings().size() - 1))
+    ReceiveTokenEndpointDefinition contributes error("to-type of last mapping (" + effectiveMappings().get(effectiveMappings().size() - 1).getToType().prettyPrint() + ") does not match type of the Token (" + getToken().effectiveJavaTypeUse().prettyPrint() + ")!")
+      when !getToken().effectiveJavaTypeUse().prettyPrint().equals(
+          effectiveMappings().get(effectiveMappings().size() - 1).getToType().prettyPrint())
       to RagConnect.errors();
 
-    SendToMqttDefinition contributes error("Sending target token must be an NTA token!")
+    SendTokenEndpointDefinition contributes error("Sending target token must be an NTA token!")
       when !getToken().getNTA()
       to RagConnect.errors();
 
-    SendToMqttDefinition contributes error("Send definition already defined for " + getToken().getName())
+    SendTokenEndpointDefinition contributes error("Send definition already defined for " + getToken().getName())
       when isAlreadyDefined()
       to RagConnect.errors();
 
@@ -44,7 +44,7 @@ aspect Errors {
       when isAlreadyDefinedAsList()
       to RagConnect.errors();
 
-    DependencyDefinition contributes error("There must be a send update definition targeting " + getSource().parentTypeypeAndName() + " for dependency definition " + getID())
+    DependencyDefinition contributes error("There must be a send endpoint definition targeting " + getSource().parentTypeypeAndName() + " for dependency definition " + getID())
       when targetEndpointDefinition() == null
       to RagConnect.errors();
 }
diff --git a/ragconnect.base/src/main/jastadd/MustacheNodes.relast b/ragconnect.base/src/main/jastadd/MustacheNodes.relast
index ce85caba554d1f582079b299f457d7675ab12dfa..1a35853e84701475c11632e7b31a31458b8de729 100644
--- a/ragconnect.base/src/main/jastadd/MustacheNodes.relast
+++ b/ragconnect.base/src/main/jastadd/MustacheNodes.relast
@@ -13,8 +13,8 @@ MTokenComponent;
 
 rel MRagConnect.RagConnect -> RagConnect;
 rel MInnerMappingDefinition.MappingDefinition -> MappingDefinition;
-rel MReceiveDefinition.ReceiveFromMqttDefinition -> ReceiveFromMqttDefinition;
-rel MSendDefinition.SendToMqttDefinition -> SendToMqttDefinition;
+rel MReceiveDefinition.ReceiveTokenEndpointDefinition -> ReceiveTokenEndpointDefinition;
+rel MSendDefinition.SendTokenEndpointDefinition -> SendTokenEndpointDefinition;
 rel MMappingDefinition.MappingDefinition -> MappingDefinition;
 rel MDependencyDefinition.DependencyDefinition -> DependencyDefinition;
 rel MTypeComponent.TypeComponent -> TypeComponent;
diff --git a/ragconnect.base/src/main/jastadd/Navigation.jrag b/ragconnect.base/src/main/jastadd/Navigation.jrag
index 2314386eb9f74ecb5699d6fba91956e80f75fa63..481de3d1c960de76e962c2c8fb087e63b5bd9104 100644
--- a/ragconnect.base/src/main/jastadd/Navigation.jrag
+++ b/ragconnect.base/src/main/jastadd/Navigation.jrag
@@ -10,7 +10,9 @@ aspect Navigation {
   eq MRagConnect.getChild().ragconnect() = getRagConnect();
 
   // --- containedFile
+  eq Grammar.getChild().containedFile() = null;
   eq RagConnect.getChild().containedFile() = null;
+  eq MRagConnect.getChild().containedFile() = null;
 
   // --- containedFileName ---
   eq RagConnect.getChild().containedFileName() = getFileName();
@@ -24,30 +26,33 @@ aspect Navigation {
   syn TokenEndpointDefinition EndpointDefinition.asTokenEndpointDefinition() = null;
   eq TokenEndpointDefinition.asTokenEndpointDefinition() = this;
 
-  // --- isSendToMqttDefinition ---
-  syn boolean EndpointDefinition.isSendToMqttDefinition() = false;
-  eq SendToMqttDefinition.isSendToMqttDefinition() = true;
+  // --- isSendTokenEndpointDefinition ---
+  syn boolean EndpointDefinition.isSendTokenEndpointDefinition() = false;
+  eq SendTokenEndpointDefinition.isSendTokenEndpointDefinition() = true;
 
-  // --- asSendToMqttDefinition ---
-  syn SendToMqttDefinition EndpointDefinition.asSendToMqttDefinition() = null;
-  eq SendToMqttDefinition.asSendToMqttDefinition() = this;
+  // --- asSendTokenEndpointDefinition ---
+  syn SendTokenEndpointDefinition EndpointDefinition.asSendTokenEndpointDefinition() = null;
+  eq SendTokenEndpointDefinition.asSendTokenEndpointDefinition() = this;
 
-  // --- asReceiveFromMqttDefinition ---
-  syn ReceiveFromMqttDefinition EndpointDefinition.asReceiveFromMqttDefinition() = null;
-  eq ReceiveFromMqttDefinition.asReceiveFromMqttDefinition() = this;
+  // --- asReceiveTokenEndpointDefinition ---
+  syn ReceiveTokenEndpointDefinition EndpointDefinition.asReceiveTokenEndpointDefinition() = null;
+  eq ReceiveTokenEndpointDefinition.asReceiveTokenEndpointDefinition() = this;
 
   // --- targetEndpointDefinition ---
-  syn SendToMqttDefinition DependencyDefinition.targetEndpointDefinition() {
+  syn SendTokenEndpointDefinition DependencyDefinition.targetEndpointDefinition() {
     // resolve definition in here, as we do not need resolveMethod in any other place (yet)
     for (EndpointDefinition endpointDefinition : ragconnect().getEndpointDefinitionList()) {
-      if (endpointDefinition.isSendToMqttDefinition() &&
-          endpointDefinition.asSendToMqttDefinition().getToken().equals(this.getTarget())) {
-        return endpointDefinition.asSendToMqttDefinition();
+      if (endpointDefinition.isSendTokenEndpointDefinition() &&
+          endpointDefinition.asSendTokenEndpointDefinition().getToken().equals(this.getTarget())) {
+        return endpointDefinition.asSendTokenEndpointDefinition();
       }
     }
     return null;
   }
 
+  // --- effectiveJavaTypeUse (should be in preprocessor) ---
+  syn lazy JavaTypeUse TokenComponent.effectiveJavaTypeUse() = hasJavaTypeUse() ? getJavaTypeUse() : new SimpleJavaTypeUse("String");
+
   // --- isDefaultMappingDefinition ---
   syn boolean MappingDefinition.isDefaultMappingDefinition() = false;
   eq DefaultMappingDefinition.isDefaultMappingDefinition() = true;
diff --git a/ragconnect.base/src/main/jastadd/RagConnect.relast b/ragconnect.base/src/main/jastadd/RagConnect.relast
index d30116efae1a6735e88922e31f42f99911c6532a..2729b85c23a87725a954e00d303caf1414cf9267 100644
--- a/ragconnect.base/src/main/jastadd/RagConnect.relast
+++ b/ragconnect.base/src/main/jastadd/RagConnect.relast
@@ -2,13 +2,18 @@ RagConnect ::= EndpointDefinition* DependencyDefinition* MappingDefinition* Prog
 
 abstract EndpointDefinition ::= <AlwaysApply:boolean> ;
 
-rel EndpointDefinition.Mapping* -> MappingDefinition;
+rel EndpointDefinition.Mapping* <-> MappingDefinition.UsedAt*;
 
 abstract TokenEndpointDefinition : EndpointDefinition;
 rel TokenEndpointDefinition.Token -> TokenComponent;
 
-ReceiveFromMqttDefinition : TokenEndpointDefinition;
-SendToMqttDefinition  : TokenEndpointDefinition;
+abstract ReceiveTokenEndpointDefinition : TokenEndpointDefinition;
+abstract SendTokenEndpointDefinition : TokenEndpointDefinition;
+
+ReceiveFromMqttDefinition : ReceiveTokenEndpointDefinition;
+SendToMqttDefinition  : SendTokenEndpointDefinition;
+ReceiveFromRestDefinition : ReceiveTokenEndpointDefinition;
+SendToRestDefinition  : SendTokenEndpointDefinition;
 
 DependencyDefinition ::= <ID>;
 rel DependencyDefinition.Source <-> TokenComponent.DependencySourceDefinition*;
diff --git a/ragconnect.base/src/main/jastadd/backend/Generation.jadd b/ragconnect.base/src/main/jastadd/backend/Generation.jadd
index 067626ed42f12add896ca4eea7c65917309c0e2e..512750e268fea52e0c0d46284e55fb3d66054ec1 100644
--- a/ragconnect.base/src/main/jastadd/backend/Generation.jadd
+++ b/ragconnect.base/src/main/jastadd/backend/Generation.jadd
@@ -37,6 +37,8 @@ aspect AttributesForMustache {
   syn String MRagConnect.mqttWaitUntilReadyMethod() = getRagConnect().mqttWaitUntilReadyMethod();
   syn String MRagConnect.mqttCloseMethod() = getRagConnect().mqttCloseMethod();
 
+  syn String MRagConnect.restHandlerAttribute() = getRagConnect().restHandlerAttribute();
+
   // --- MEndpointDefinition ---
   syn String MEndpointDefinition.preemptiveExpectedValue();
   syn String MEndpointDefinition.preemptiveReturn();
@@ -49,6 +51,7 @@ aspect AttributesForMustache {
 
   inh String MEndpointDefinition.mqttHandlerAttribute();
 
+  syn String MEndpointDefinition.handlerAttribute() = endpointDef().handlerAttribute();
   syn String MEndpointDefinition.connectMethod() = endpointDef().connectMethod();
   syn TokenComponent MEndpointDefinition.token() = endpointDef().getToken();
   syn boolean MEndpointDefinition.alwaysApply() = endpointDef().getAlwaysApply();
@@ -82,20 +85,20 @@ aspect AttributesForMustache {
   // --- MReceiveDefinition ---
   eq MReceiveDefinition.preemptiveExpectedValue() = "get" + tokenName() + "()";
   eq MReceiveDefinition.preemptiveReturn() = "return;";
-  eq MReceiveDefinition.endpointDef() = getReceiveFromMqttDefinition();
+  eq MReceiveDefinition.endpointDef() = getReceiveTokenEndpointDefinition();
   eq MReceiveDefinition.firstInputVarName() = "message";
 
   // --- MSendDefinition ---
   eq MSendDefinition.preemptiveExpectedValue() = lastValue();
   eq MSendDefinition.preemptiveReturn() = "return false;";
-  eq MSendDefinition.endpointDef() = getSendToMqttDefinition();
+  eq MSendDefinition.endpointDef() = getSendTokenEndpointDefinition();
   eq MSendDefinition.firstInputVarName() = "get" + tokenName() + "()";
 
-  syn String MSendDefinition.sendTopic() = getSendToMqttDefinition().sendTopic();
-  syn String MSendDefinition.lastValue() = getSendToMqttDefinition().lastValue();
-  syn String MSendDefinition.updateMethod() = getSendToMqttDefinition().updateMethod();
-  syn String MSendDefinition.writeMethod() = getSendToMqttDefinition().writeMethod();
-  syn String MSendDefinition.tokenResetMethod() = getSendToMqttDefinition().tokenResetMethod();
+  syn String MSendDefinition.sendTopic() = getSendTokenEndpointDefinition().sendTopic();
+  syn String MSendDefinition.lastValue() = getSendTokenEndpointDefinition().lastValue();
+  syn String MSendDefinition.updateMethod() = getSendTokenEndpointDefinition().updateMethod();
+  syn String MSendDefinition.writeMethod() = getSendTokenEndpointDefinition().writeMethod();
+  syn String MSendDefinition.tokenResetMethod() = getSendTokenEndpointDefinition().tokenResetMethod();
 
   // --- MMappingDefinition ---
   syn String MMappingDefinition.toType() = getMappingDefinition().getToType().prettyPrint();
@@ -122,7 +125,7 @@ aspect AttributesForMustache {
   // --- MTokenComponent ---
   syn String MTokenComponent.parentTypeName() = getTokenComponent().containingTypeDecl().getName();
   syn String MTokenComponent.name() = getTokenComponent().getName();
-  syn String MTokenComponent.javaType() = getTokenComponent().getJavaTypeUse().prettyPrint();
+  syn String MTokenComponent.javaType() = getTokenComponent().effectiveJavaTypeUse().prettyPrint();
   syn String MTokenComponent.internalName() = getTokenComponent().internalName();
 
   // --- toMustache ---
@@ -130,10 +133,10 @@ aspect AttributesForMustache {
     MRagConnect result = new MRagConnect();
     result.setRagConnect(this);
     for (EndpointDefinition def : getEndpointDefinitionList()) {
-      if (def.isSendToMqttDefinition()) {
-        result.addSendDefinition(def.asSendToMqttDefinition().toMustache());
+      if (def.isSendTokenEndpointDefinition()) {
+        result.addSendDefinition(def.asSendTokenEndpointDefinition().toMustache());
       } else {
-        result.addReceiveDefinition(def.asReceiveFromMqttDefinition().toMustache());
+        result.addReceiveDefinition(def.asReceiveTokenEndpointDefinition().toMustache());
       }
     }
     for (MappingDefinition def : allMappingDefinitions()) {
@@ -163,15 +166,31 @@ aspect AttributesForMustache {
       addInnerMappingDefinition(inner);
     }
   }
-  syn lazy MReceiveDefinition ReceiveFromMqttDefinition.toMustache() {
+  syn lazy MReceiveDefinition ReceiveTokenEndpointDefinition.toMustache();
+  eq ReceiveFromMqttDefinition.toMustache() {
+    MReceiveDefinition result = new MReceiveDefinition();
+    result.setReceiveTokenEndpointDefinition(this);
+    result.addInnerMappings();
+    return result;
+  }
+  eq ReceiveFromRestDefinition.toMustache() {
     MReceiveDefinition result = new MReceiveDefinition();
-    result.setReceiveFromMqttDefinition(this);
+    System.err.println("REST not implemented!");
+    result.setReceiveTokenEndpointDefinition(this);
+    result.addInnerMappings();
+    return result;
+  }
+  syn lazy MSendDefinition SendTokenEndpointDefinition.toMustache();
+  eq SendToMqttDefinition.toMustache() {
+    MSendDefinition result = new MSendDefinition();
+    result.setSendTokenEndpointDefinition(this);
     result.addInnerMappings();
     return result;
   }
-  syn lazy MSendDefinition SendToMqttDefinition.toMustache() {
+  eq SendToRestDefinition.toMustache() {
     MSendDefinition result = new MSendDefinition();
-    result.setSendToMqttDefinition(this);
+    System.err.println("REST not implemented!");
+    result.setSendTokenEndpointDefinition(this);
     result.addInnerMappings();
     return result;
   }
@@ -206,11 +225,11 @@ aspect AspectGeneration {
   syn String TokenComponent.externalName() = getName();
 
   syn String TokenEndpointDefinition.connectMethod() = "connect" + getToken().getName();
-  syn String SendToMqttDefinition.sendTopic() = "_topic_" + getToken().getName();
-  syn String SendToMqttDefinition.lastValue() = "_lastValue" + getToken().getName();
-  syn String SendToMqttDefinition.updateMethod() = "_update_" + getToken().getName();
-  syn String SendToMqttDefinition.writeMethod() = "_writeLastValue_" + getToken().getName();
-  syn String SendToMqttDefinition.tokenResetMethod() = "get" + getToken().getName() + "_reset";
+  syn String SendTokenEndpointDefinition.sendTopic() = "_topic_" + getToken().getName();
+  syn String SendTokenEndpointDefinition.lastValue() = "_lastValue" + getToken().getName();
+  syn String SendTokenEndpointDefinition.updateMethod() = "_update_" + getToken().getName();
+  syn String SendTokenEndpointDefinition.writeMethod() = "_writeLastValue_" + getToken().getName();
+  syn String SendTokenEndpointDefinition.tokenResetMethod() = "get" + getToken().getName() + "_reset";
   syn String MappingDefinition.methodName() = "_apply_" + getID();
   syn String DependencyDefinition.dependencyMethod() = "add" +
     Character.toUpperCase(getID().charAt(0)) +
@@ -225,13 +244,24 @@ aspect AspectGeneration {
   syn String RagConnect.mqttWaitUntilReadyMethod() = "MqttWaitUntilReady";
   syn String RagConnect.mqttCloseMethod() = "MqttCloseConnections";
 
+  syn String RagConnect.restHandlerAttribute() = "_restHandler";
+  syn String RagConnect.restHandlerField() = "_restHandler";
+
+  syn String TokenEndpointDefinition.handlerAttribute();
+  eq ReceiveFromMqttDefinition.handlerAttribute() = mqttHandlerAttribute();
+  eq SendToMqttDefinition.handlerAttribute() = mqttHandlerAttribute();
+  eq ReceiveFromRestDefinition.handlerAttribute() = restHandlerAttribute();
+  eq SendToRestDefinition.handlerAttribute() = restHandlerAttribute();
+
   // naming copy attributes
   // --- mqttHandlerAttribute ---
   inh String EndpointDefinition.mqttHandlerAttribute();
-  inh String MappingDefinition.mqttHandlerAttribute();
-  inh String DependencyDefinition.mqttHandlerAttribute();
   eq RagConnect.getChild().mqttHandlerAttribute() = mqttHandlerAttribute();
 
+  // --- restHandlerAttribute ---
+  inh String EndpointDefinition.restHandlerAttribute();
+  eq RagConnect.getChild().restHandlerAttribute() = restHandlerAttribute();
+
   // --- rootNodeName ---
   syn String ASTNode.rootNodeName() = rootNode.getName();
 
@@ -296,7 +326,7 @@ aspect GrammarExtension {
     if (!getName().equals("")) {
       b.append(internalName()).append(":");
     }
-    getJavaTypeUse().generateAbstractGrammar(b);
+    effectiveJavaTypeUse().generateAbstractGrammar(b);
     b.append(">");
     if (getNTA()) {
       b.append("/");
diff --git a/ragconnect.base/src/main/jastadd/backend/Mappings.jrag b/ragconnect.base/src/main/jastadd/backend/Mappings.jrag
index 07cbf5b81a531638ac092635f915ed856a65df4c..d5f79046be4271f93a954061c28978aa19ba63b9 100644
--- a/ragconnect.base/src/main/jastadd/backend/Mappings.jrag
+++ b/ragconnect.base/src/main/jastadd/backend/Mappings.jrag
@@ -18,6 +18,26 @@ aspect DefaultMappings {
     return result;
   }
 
+  private String RagConnect.baseDefaultMappingTypeNamePart(String typeName) {
+    return Character.toUpperCase(typeName.charAt(0)) + typeName.substring(1).replace("[]", "s");
+  }
+
+  private MappingDefinitionType RagConnect.baseDefaultMappingTypeFromName(String typeName) {
+    return typeName.endsWith("[]") ?
+        new JavaArrayMappingDefinitionType(new SimpleJavaTypeUse(typeName.replace("[]", ""))) :
+        new JavaMappingDefinitionType(new SimpleJavaTypeUse(typeName));
+  }
+
+  private DefaultMappingDefinition RagConnect.baseDefaultMappingDefinition(String fromTypeName, String toTypeName, String content) {
+    DefaultMappingDefinition result = new DefaultMappingDefinition();
+    result.setID("_Default" + baseDefaultMappingTypeNamePart(fromTypeName) + "To" + baseDefaultMappingTypeNamePart(toTypeName) + "Mapping");
+    result.setFromType(baseDefaultMappingTypeFromName(fromTypeName));
+    result.setFromVariableName("input");
+    result.setToType(baseDefaultMappingTypeFromName(toTypeName));
+    result.setContent(content);
+    return result;
+  }
+
   syn nta DefaultMappingDefinition RagConnect.defaultBytesToIntMapping() {
     DefaultMappingDefinition result = baseDefaultMappingDefinitionFromBytes("int");
     result.setContent("return java.nio.ByteBuffer.wrap(bytes).getInt();");
@@ -101,17 +121,31 @@ aspect DefaultMappings {
     result.setContent("return input.getBytes();");
     return result;
   }
+
+  syn nta DefaultMappingDefinition RagConnect.defaultStringToIntMapping() = baseDefaultMappingDefinition("String", "int", "return Integer.parseInteger(input);");
+  syn nta DefaultMappingDefinition RagConnect.defaultStringToShortMapping() = baseDefaultMappingDefinition("String", "short", "return Short.parseShort(input);");
+  syn nta DefaultMappingDefinition RagConnect.defaultStringToLongMapping() = baseDefaultMappingDefinition("String", "long", "return Long.parseLong(input);");
+  syn nta DefaultMappingDefinition RagConnect.defaultStringToFloatMapping() = baseDefaultMappingDefinition("String", "float", "return Float.parseFloat(input);");
+  syn nta DefaultMappingDefinition RagConnect.defaultStringToDoubleMapping() = baseDefaultMappingDefinition("String", "double", "return Double.parseDouble(input);");
+  syn nta DefaultMappingDefinition RagConnect.defaultStringToCharMapping() = baseDefaultMappingDefinition("String", "char", "return input.charAt(0);");
+
+  syn nta DefaultMappingDefinition RagConnect.defaultIntToStringMapping() = baseDefaultMappingDefinition("int", "String", "return String.valueOf(input);");
+  syn nta DefaultMappingDefinition RagConnect.defaultShortToStringMapping() = baseDefaultMappingDefinition("int", "String", "return String.valueOf(input);");
+  syn nta DefaultMappingDefinition RagConnect.defaultLongToStringMapping() = baseDefaultMappingDefinition("int", "String", "return String.valueOf(input);");
+  syn nta DefaultMappingDefinition RagConnect.defaultFloatToStringMapping() = baseDefaultMappingDefinition("int", "String", "return String.valueOf(input);");
+  syn nta DefaultMappingDefinition RagConnect.defaultDoubleToStringMapping() = baseDefaultMappingDefinition("int", "String", "return String.valueOf(input);");
+  syn nta DefaultMappingDefinition RagConnect.defaultCharToStringMapping() = baseDefaultMappingDefinition("int", "String", "return String.valueOf(input);");
 }
 
 aspect Mappings {
   // --- effectiveMappings ---
   syn java.util.List<MappingDefinition> EndpointDefinition.effectiveMappings();
-  eq ReceiveFromMqttDefinition.effectiveMappings() {
-    // if there is a first mapping, check if its input type is byte[].
+  eq ReceiveTokenEndpointDefinition.effectiveMappings() {
+    // if there is a first mapping, check if it is suitable.
     //  or if no mappings are specified.
     // then prepend the suitable default mapping
     java.util.List<MappingDefinition> result;
-    if (getMappingList().isEmpty() || !getMappingList().get(0).getFromType().isByteArray()) {
+    if (getMappingList().isEmpty() || !hasSuitableEdgeMapping()) {
       result = new java.util.ArrayList();
       result.add(suitableDefaultMapping());
       result.addAll(getMappingList());
@@ -120,13 +154,12 @@ aspect Mappings {
     }
     return result;
   }
-  eq SendToMqttDefinition.effectiveMappings() {
-    // if there is a mapping, check if the output type of the last mapping is byte[].
+  eq SendTokenEndpointDefinition.effectiveMappings() {
+    // if there is a mapping, check if it is suitable.
     //  or if no mappings are specified.
     // then append the suitable default mapping
     java.util.List<MappingDefinition> result;
-    int numMappings = getMappingList().size();
-    if (numMappings == 0 || !getMappingList().get(numMappings - 1).getToType().isByteArray()) {
+    if (getMappingList().isEmpty() || !hasSuitableEdgeMapping()) {
       result = new java.util.ArrayList();
       result.addAll(getMappingList());
       result.add(suitableDefaultMapping());
@@ -136,8 +169,20 @@ aspect Mappings {
     return result;
   }
 
+  // --- hasSuitableEdgeMapping ---
+  syn boolean TokenEndpointDefinition.hasSuitableEdgeMapping();
+  eq ReceiveTokenEndpointDefinition.hasSuitableEdgeMapping() = isSuitableEdgeMapping(getMappingList().get(0));
+  eq SendTokenEndpointDefinition.hasSuitableEdgeMapping() = isSuitableEdgeMapping(getMappingList().get(getMappingList().size() - 1));
+
+  // --- isSuitableEdgeMapping(def) ---
+  syn boolean TokenEndpointDefinition.isSuitableEdgeMapping(MappingDefinition def);
+  eq ReceiveFromMqttDefinition.isSuitableEdgeMapping(MappingDefinition def) = def.getFromType().isByteArray();
+  eq SendToMqttDefinition.isSuitableEdgeMapping(MappingDefinition def) = def.getToType().isByteArray();
+  eq ReceiveFromRestDefinition.isSuitableEdgeMapping(MappingDefinition def) = def.getFromType().isString();
+  eq SendToRestDefinition.isSuitableEdgeMapping(MappingDefinition def) = def.getToType().isString();
+
   // --- isPrimitiveType ---
-  syn boolean TokenComponent.isPrimitiveType() = getJavaTypeUse().isPrimitiveType();
+  syn boolean TokenComponent.isPrimitiveType() = effectiveJavaTypeUse().isPrimitiveType();
   syn boolean JavaTypeUse.isPrimitiveType() = false;
   eq SimpleJavaTypeUse.isPrimitiveType() {
     switch(getName()) {
@@ -202,15 +247,60 @@ aspect Mappings {
       default: return null;
     }
   }
+  eq ReceiveFromRestDefinition.suitableDefaultMapping() {
+    String typeName = getMappingList().isEmpty() ?
+        getToken().getJavaTypeUse().getName() :
+        getMappingList().get(0).getFromType().prettyPrint();
+    switch(typeName) {
+      case "int":
+      case "Integer": return ragconnect().defaultStringToIntMapping();
+      case "short":
+      case "Short": return ragconnect().defaultStringToShortMapping();
+      case "long":
+      case "Long": return ragconnect().defaultStringToLongMapping();
+      case "float":
+      case "Float": return ragconnect().defaultStringToFloatMapping();
+      case "double":
+      case "Double": return ragconnect().defaultStringToDoubleMapping();
+      case "char":
+      case "Character": return ragconnect().defaultStringToCharMapping();
+      default: return null;
+    }
+  }
+  eq SendToRestDefinition.suitableDefaultMapping() {
+    String typeName = getMappingList().isEmpty() ?
+        getToken().getJavaTypeUse().getName() :
+        getMappingList().get(getMappingList().size() - 1).getFromType().prettyPrint();
+    switch(typeName) {
+      case "int":
+      case "Integer": return ragconnect().defaultIntToStringMapping();
+      case "short":
+      case "Short": return ragconnect().defaultShortToStringMapping();
+      case "long":
+      case "Long": return ragconnect().defaultLongToStringMapping();
+      case "float":
+      case "Float": return ragconnect().defaultFloatToStringMapping();
+      case "double":
+      case "Double": return ragconnect().defaultDoubleToStringMapping();
+      case "char":
+      case "Character": return ragconnect().defaultCharToStringMapping();
+      default: return null;
+    }
+  }
 
   // --- isByteArray ---
   syn boolean MappingDefinitionType.isByteArray() = false;
   eq JavaArrayMappingDefinitionType.isByteArray() = getType().getName().equals("byte");
 
+  // --- isString ---
+  syn boolean MappingDefinitionType.isString() = false;
+  eq JavaMappingDefinitionType.isString() = getType().getName().equals("String");
+
   // --- allMappingDefinitions ---
   syn java.util.List<MappingDefinition> RagConnect.allMappingDefinitions() {
     java.util.List<MappingDefinition> result = new java.util.ArrayList<>();
     getMappingDefinitionList().iterator().forEachRemaining(result::add);
+    // byte[] converstion
     result.add(defaultBytesToIntMapping());
     result.add(defaultBytesToShortMapping());
     result.add(defaultBytesToLongMapping());
@@ -225,6 +315,19 @@ aspect Mappings {
     result.add(defaultDoubleToBytesMapping());
     result.add(defaultCharToBytesMapping());
     result.add(defaultStringToBytesMapping());
+    // string converstion
+    result.add(defaultStringToIntMapping());
+    result.add(defaultStringToShortMapping());
+    result.add(defaultStringToLongMapping());
+    result.add(defaultStringToFloatMapping());
+    result.add(defaultStringToDoubleMapping());
+    result.add(defaultStringToCharMapping());
+    result.add(defaultIntToStringMapping());
+    result.add(defaultShortToStringMapping());
+    result.add(defaultLongToStringMapping());
+    result.add(defaultFloatToStringMapping());
+    result.add(defaultDoubleToStringMapping());
+    result.add(defaultCharToStringMapping());
     return result;
   }
 }
diff --git a/ragconnect.base/src/main/jastadd/parser/RagConnect.parser b/ragconnect.base/src/main/jastadd/parser/RagConnect.parser
index e2685c15555056c64d4f5e8bebdc458ecea981a3..0f897afc1992544d7736ccee4d884b934e7f0227 100644
--- a/ragconnect.base/src/main/jastadd/parser/RagConnect.parser
+++ b/ragconnect.base/src/main/jastadd/parser/RagConnect.parser
@@ -13,38 +13,32 @@ RagConnect ragconnect
 :} ;
 
 EndpointDefinition endpoint_definition
-  = RECEIVE ID.type_name DOT ID.token_name SCOL
+  = endpoint_definition_type.endpointDef SCOL
     {:
-      ReceiveFromMqttDefinition result = new ReceiveFromMqttDefinition();
-      result.setToken(TokenComponent.createRef(type_name + "." + token_name));
-      return result;
-    :}
-  | RECEIVE ID.type_name DOT ID.token_name USING string_list.mapping_defs SCOL
-    {:
-      ReceiveFromMqttDefinition result = new ReceiveFromMqttDefinition();
-      result.setToken(TokenComponent.createRef(type_name + "." + token_name));
-      for (String mapping_def : makeMappingDefs(mapping_defs)) {
-        result.addMapping(MappingDefinition.createRef(mapping_def));
-      }
-      return result;
-    :}
-  | SEND ID.type_name DOT ID.token_name SCOL
-    {:
-      SendToMqttDefinition result = new SendToMqttDefinition();
-      result.setToken(TokenComponent.createRef(type_name + "." + token_name));
-      return result;
+      return endpointDef;
     :}
-  | SEND ID.type_name DOT ID.token_name USING string_list.mapping_defs SCOL
+  | endpoint_definition_type.endpointDef USING string_list.mapping_defs SCOL
     {:
-      SendToMqttDefinition result = new SendToMqttDefinition();
-      result.setToken(TokenComponent.createRef(type_name + "." + token_name));
       for (String mapping_def : makeMappingDefs(mapping_defs)) {
-        result.addMapping(MappingDefinition.createRef(mapping_def));
+        endpointDef.addMapping(MappingDefinition.createRef(mapping_def));
       }
-      return result;
+      return endpointDef;
     :}
 ;
 
+EndpointDefinition endpoint_definition_type
+  = RECEIVE token_ref           {: return new ReceiveFromMqttDefinition().setToken(token_ref); :}
+  | RECEIVE token_ref VIA MQTT  {: return new ReceiveFromMqttDefinition().setToken(token_ref); :}
+  | RECEIVE token_ref VIA REST  {: return new ReceiveFromRestDefinition().setToken(token_ref); :}
+  | SEND token_ref              {: return new SendToMqttDefinition().setToken(token_ref); :}
+  | SEND token_ref VIA MQTT     {: return new SendToMqttDefinition().setToken(token_ref); :}
+  | SEND token_ref VIA REST     {: return new SendToRestDefinition().setToken(token_ref); :}
+;
+
+TokenComponent token_ref
+  = ID.type_name DOT ID.token_name  {: return TokenComponent.createRef(type_name + "." + token_name); :}
+;
+
 ArrayList string_list
   = ID
   | string_list COMMA ID
diff --git a/ragconnect.base/src/main/jastadd/scanner/Keywords.flex b/ragconnect.base/src/main/jastadd/scanner/Keywords.flex
index 5773118d8fda8ffdc536b504aa7056b8784ddfb3..fe8a8141140884f7c53295f76877dd277c41ac4c 100644
--- a/ragconnect.base/src/main/jastadd/scanner/Keywords.flex
+++ b/ragconnect.base/src/main/jastadd/scanner/Keywords.flex
@@ -5,3 +5,6 @@
 "maps"       { return sym(Terminals.MAPS); }
 "to"         { return sym(Terminals.TO); }
 "as"         { return sym(Terminals.AS); }
+"via"        { return sym(Terminals.VIA); }
+"mqtt"       { return sym(Terminals.MQTT); }
+"rest"       { return sym(Terminals.REST); }
diff --git a/ragconnect.base/src/main/resources/receiveDefinition.mustache b/ragconnect.base/src/main/resources/receiveDefinition.mustache
index e2df0433fe82b37df2c016887da52a11cfd2692b..c02f5e5f49f6a9bebf0f6a1e7498ec743024afb3 100644
--- a/ragconnect.base/src/main/resources/receiveDefinition.mustache
+++ b/ragconnect.base/src/main/resources/receiveDefinition.mustache
@@ -1,8 +1,8 @@
   public void {{parentTypeName}}.{{connectMethod}}(String topic) {
-    {{mqttHandlerAttribute}}().newConnection(topic, message -> {
+    {{handlerAttribute}}().newConnection(topic, message -> {
       {{> mappingApplication}}
       {{#loggingEnabledForReads}}
-      System.out.println("[Receive] " + topic + " -> {{tokenName}} = " + {{lastResult}});{{!lastResult has to be a new attribute}}
+      System.out.println("[Receive] " + topic + " -> {{tokenName}} = " + {{lastResult}});
       {{/loggingEnabledForReads}}
       set{{tokenName}}({{lastResult}});
     });
diff --git a/ragconnect.base/src/main/resources/sendDefinition.mustache b/ragconnect.base/src/main/resources/sendDefinition.mustache
index 477dbc550132af842e53e8fed2cbbee0c8996296..874a342512326434d365563f5c1de93a609c5029 100644
--- a/ragconnect.base/src/main/resources/sendDefinition.mustache
+++ b/ragconnect.base/src/main/resources/sendDefinition.mustache
@@ -20,5 +20,5 @@
     {{#loggingEnabledForWrites}}
     System.out.println("[Send] {{tokenName}} = " + get{{tokenName}}() + " -> " + {{sendTopic}});
     {{/loggingEnabledForWrites}}
-    {{mqttHandlerAttribute}}().publish({{sendTopic}}, {{lastValue}});
+    {{handlerAttribute}}().publish({{sendTopic}}, {{lastValue}});
   }
diff --git a/ragconnect.tests/build.gradle b/ragconnect.tests/build.gradle
index d0a6997e48aac4caa7b4c5c0c249210c7276271d..4cb42ea9965f71777280c355df42a8cde31ab47d 100644
--- a/ragconnect.tests/build.gradle
+++ b/ragconnect.tests/build.gradle
@@ -64,6 +64,10 @@ sourceSets {
     }
 }
 
+clean {
+    delete 'src/test/02-after-ragconnect/*/', 'src/test/03-after-relast/*/', 'src/test/java-gen/*/'
+}
+
 // --- Test: Example ---
 task preprocessExampleTest(type: JavaExec, group: 'verification') {
     doFirst {
@@ -223,6 +227,34 @@ task compileRead2Write1Test(type: RelastTest) {
 testClasses.dependsOn compileRead2Write1Test
 compileRead2Write1Test.dependsOn preprocessRead2Write1Test
 
-clean {
-    delete 'src/test/02-after-ragconnect/*/', 'src/test/03-after-relast/*/', 'src/test/java-gen/*/'
+// --- Test: via ---
+task preprocessViaTest(type: JavaExec, group: 'verification') {
+    doFirst {
+        delete 'src/test/02-after-ragconnect/via/Test.relast',
+                'src/test/02-after-ragconnect/via/MqttHandler.java',
+                'src/test/02-after-ragconnect/via/RagConnect.jadd'
+    }
+
+    classpath = sourceSets.main.runtimeClasspath
+    main = 'org.jastadd.ragconnect.compiler.Compiler'
+    args '--o=src/test/02-after-ragconnect/via',
+            'src/test/01-input/via/Test.relast',
+            'src/test/01-input/via/Test.connect',
+            '--rootNode=A', '--verbose',
+            '--logReads', '--logWrites'
 }
+
+task compileViaTest(type: RelastTest) {
+    useJastAddNames = true
+    jastAddList = 'JastAddList'
+    relastFiles 'src/test/02-after-ragconnect/via/Test.relast',
+            'src/test/02-after-ragconnect/via/RagConnect.relast'
+    grammarName = 'src/test/03-after-relast/via/via'
+    packageName = 'via.ast'
+    moreInputFiles 'src/test/01-input/via/Test.jadd',
+            'src/test/02-after-ragconnect/via/MqttHandler.jadd',
+            'src/test/02-after-ragconnect/via/RagConnect.jadd'
+}
+
+testClasses.dependsOn compileViaTest
+compileViaTest.dependsOn preprocessViaTest
diff --git a/ragconnect.tests/src/test/01-input/via/Test.connect b/ragconnect.tests/src/test/01-input/via/Test.connect
new file mode 100644
index 0000000000000000000000000000000000000000..2f39f088672c170a424dd1707bbbfcd24e169c4d
--- /dev/null
+++ b/ragconnect.tests/src/test/01-input/via/Test.connect
@@ -0,0 +1,28 @@
+receive A.Mqtt2MqttInput via mqtt using MarkMqttInput ;
+receive A.Rest2RestInput via rest using MarkRestInput ;
+receive A.Mqtt2RestInput via mqtt using MarkMqttInput ;
+receive A.Rest2MqttInput via rest using MarkRestInput ;
+
+send A.Mqtt2MqttOutput via mqtt using MarkMqttOutput ;
+send A.Rest2RestOutput via rest using MarkRestOutput ;
+send A.Mqtt2RestOutput via rest using MarkRestOutput ;
+send A.Rest2MqttOutput via mqtt using MarkMqttOutput ;
+
+A.Mqtt2MqttOutput canDependOn A.Mqtt2MqttInput as dependencyMqtt2Mqtt ;
+A.Rest2RestOutput canDependOn A.Rest2RestInput as dependencyRest2Rest ;
+A.Mqtt2RestOutput canDependOn A.Mqtt2RestInput as dependencyMqtt2Rest ;
+A.Rest2MqttOutput canDependOn A.Rest2MqttInput as dependencyRest2Mqtt ;
+
+MarkMqttInput maps String s to String {:
+  return "FromMqtt" + s;
+:}
+MarkRestInput maps String s to String {:
+  return "FromRest" + s;
+:}
+
+MarkMqttOutput maps String s to String {:
+  return s + "ToMqtt";
+:}
+MarkRestOutput maps String s to String {:
+  return s + "ToRest";
+:}
diff --git a/ragconnect.tests/src/test/01-input/via/Test.jadd b/ragconnect.tests/src/test/01-input/via/Test.jadd
new file mode 100644
index 0000000000000000000000000000000000000000..3c4313fb9b799f12d73ec1ea10279b579a5e388e
--- /dev/null
+++ b/ragconnect.tests/src/test/01-input/via/Test.jadd
@@ -0,0 +1,6 @@
+aspect Computation {
+  syn lazy String A.getMqtt2MqttOutput() = getMqtt2MqttInput() + "M2M" ;
+  syn lazy String A.getRest2RestOutput() = getRest2RestInput() + "R2R" ;
+  syn lazy String A.getMqtt2RestOutput() = getMqtt2RestInput() + "M2R" ;
+  syn lazy String A.getRest2MqttOutput() = getRest2MqttInput() + "R2M" ;
+}
diff --git a/ragconnect.tests/src/test/01-input/via/Test.relast b/ragconnect.tests/src/test/01-input/via/Test.relast
new file mode 100644
index 0000000000000000000000000000000000000000..6868ed853c2c06a60798db23c153deb200f6c647
--- /dev/null
+++ b/ragconnect.tests/src/test/01-input/via/Test.relast
@@ -0,0 +1,4 @@
+A ::= <Mqtt2MqttInput> /<Mqtt2MqttOutput>/
+      <Rest2RestInput> /<Rest2RestOutput>/
+      <Mqtt2RestInput> /<Mqtt2RestOutput>/
+      <Rest2MqttInput> /<Rest2MqttOutput>/;