diff --git a/src/te/apps/epce/src/epce_server.erl b/src/te/apps/epce/src/epce_server.erl
index 03f1dacb21302221ad86311d50556c99469ea6e4..8996d3b358bdcebbbadaa7ff2d61467664d5b27b 100644
--- a/src/te/apps/epce/src/epce_server.erl
+++ b/src/te/apps/epce/src/epce_server.erl
@@ -67,8 +67,8 @@ get_flows() ->
 update_flow(FlowId, LabelStack) ->
     gen_server:call(?MODULE, {update_flow, FlowId, LabelStack}).
 
-initiate_flow(Name, FromAddr, ToAddr, BindingLabel) ->
-    gen_server:call(?MODULE, {initiate_flow, Name, FromAddr, ToAddr,
+initiate_flow(Name, From, To, BindingLabel) ->
+    gen_server:call(?MODULE, {initiate_flow, Name, From, To,
                               BindingLabel}, ?LARGE_TIMEOUT).
 
 
@@ -111,19 +111,26 @@ handle_call({update_flow, FlowId, Labels}, From,
                     {noreply, State}
             end
     end;
-handle_call({initiate_flow, Name, FromAddr, ToAddr, Binding}, From,
+handle_call({initiate_flow, Name, FromKey, ToKey, Binding}, From,
             #state{sessions = SessMap} = State) ->
-    case maps:find(FromAddr, SessMap) of
-        error -> {reply, {error, session_not_found}, State};
-        {ok, #sess{pid = Pid}} ->
-            case compute_path(FromAddr, ToAddr) of
-                {error, Reason} ->
-                    {reply, {error, Reason}, State};
-                {ok, Labels} ->
-                    InitRoute = routeinit_from_labels(Name, FromAddr, ToAddr,
-                                                      [], Binding, Labels),
-                    session_initiate_flow(State, Pid, InitRoute, From),
-                    {noreply, State}
+    case {pcc_address(FromKey), pcc_address(ToKey)} of
+        {{error, Reason}, _} ->
+            {reply, {error, Reason}, State};
+        {_, {error, Reason}} ->
+            {reply, {error, Reason}, State};
+        {{ok, FromAddr}, {ok, ToAddr}} ->
+            case maps:find(FromAddr, SessMap) of
+                error -> {reply, {error, session_not_found}, State};
+                {ok, #sess{pid = Pid}} ->
+                    case compute_path(FromAddr, ToAddr) of
+                        {error, Reason} ->
+                            {reply, {error, Reason}, State};
+                        {ok, Labels} ->
+                            InitRoute = routeinit_from_labels(Name, FromAddr,
+                                            ToAddr, [], Binding, Labels),
+                            session_initiate_flow(State, Pid, InitRoute, From),
+                            {noreply, State}
+                    end
             end
     end;
 handle_call({session_opened, Id, Caps, Pid}, _From,
@@ -227,18 +234,33 @@ terminate(_Reason, _State) ->
 
 %%% INTERNAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-compute_path(From, To) ->
-    case epce_ted:compute_path(pcc_address, From, To) of
-        {ok, Devices} ->
-            Labels = tl([L || #{mpls_label := L} <- Devices, L =/= undefined]),
-            logger:debug("Route from ~p to ~p: ~p", [From, To, Labels]),
-            {ok, Labels};
+ted_index(Id) when is_binary(Id) -> id;
+ted_index({_, _, _, _}) -> pcc_address.
+
+pcc_address(Key) ->
+    case epce_ted:lookup(ted_index(Key), Key) of
         {error, Reason} ->
-            logger:warning("Failed to find a route from ~p to ~p: ~p",
-                           [From, To, Reason]),
-            {error, route_not_found}
+            logger:warning("Failed to find a PCC address for router ~p: ~p",
+                           [Key, Reason]),
+            {error, router_not_found};
+        {ok, #{pcc_address := Addr}} ->
+            {ok, Addr}
     end.
 
+compute_path(From, To) when is_binary(From), is_binary(To) ->
+    compute_path_result(From, To, epce_ted:compute_path(id, From, To));
+compute_path({_, _, _, _} = From, {_, _, _, _} = To) ->
+    compute_path_result(From, To, epce_ted:compute_path(pcc_address, From, To)).
+
+compute_path_result(From, To, {error, Reason}) ->
+    logger:warning("Failed to find a route from ~p to ~p: ~p",
+                   [From, To, Reason]),
+    {error, route_not_found};
+compute_path_result(From, To, {ok, Devices}) ->
+    Labels = tl([L || #{mpls_label := L} <- Devices, L =/= undefined]),
+    logger:debug("Route from ~p to ~p: ~p", [From, To, Labels]),
+    {ok, Labels}.
+
 routereq_from_labels(Source, Destination, Constraints, Labels) ->
     #{
         source => Source,
diff --git a/src/te/apps/epce/src/epce_ted.erl b/src/te/apps/epce/src/epce_ted.erl
index aaf5a4e9a09183e51686457613f89a1804f5276c..879b92920e5e3a3553341f23f878a7b7918739db 100644
--- a/src/te/apps/epce/src/epce_ted.erl
+++ b/src/te/apps/epce/src/epce_ted.erl
@@ -19,6 +19,7 @@
 -export([link_updated/2]).
 -export([link_deleted/1]).
 -export([compute_path/3]).
+-export([lookup/2]).
 
 -export([get_graph/0]).
 
@@ -69,6 +70,12 @@ compute_path(Index, From, To)
 compute_path(Index, _From, _To) ->
     {error, {invalid_index, Index}}.
 
+lookup(Index, Key)
+  when Index =:= id; Index =:= pcc_address ->
+    gen_server:call(?MODULE, {lookup, Index, Key});
+lookup(Index, _Key) ->
+    {error, {invalid_index, Index}}.
+
 
 get_graph() ->
     gen_server:call(?MODULE, get_graph).
@@ -106,6 +113,13 @@ handle_call({compute_path, Index, From, To}, _From, #state{graph = G} = State) -
         {error, Reason} ->
             {reply, {error, Reason}, State}
     end;
+handle_call({lookup, Index, Key}, _From, #state{graph = G} = State) ->
+    case as_ids(State, Index, [Key]) of
+        {ok, [Id]} ->
+            {reply, do_lookup(G, Id), State};
+        {error, Reason} ->
+            {reply, {error, Reason}, State}
+    end;
 handle_call(get_graph, _From, #state{graph = G} = State) ->
     {reply, G, State};
 handle_call(Request, _From, State) ->
@@ -193,6 +207,12 @@ do_compute_path(G, FromId, ToId) ->
         Ids -> {ok, retrieve_devices(G, Ids, [])}
     end.
 
+do_lookup(G, Id) ->
+    case digraph:vertex(G, Id) of
+        {_, Info} -> {ok, Info};
+        false -> {error, not_found}
+    end.
+
 retrieve_devices(_G, [], Acc) ->
     lists:reverse(Acc);
 retrieve_devices(G, [Id | Rest], Acc) ->
diff --git a/src/te/apps/tfte/src/tfte.app.src b/src/te/apps/tfte/src/tfte.app.src
index 06adeb848ba96963c734f1c2bc6de2f3771eba8d..64fffcb61250102fb9f682d55ca5fce2936f0215 100644
--- a/src/te/apps/tfte/src/tfte.app.src
+++ b/src/te/apps/tfte/src/tfte.app.src
@@ -7,6 +7,7 @@
    [kernel,
     stdlib,
     tfpb,
+    jsx,
     epce
    ]},
   {env,[]},
diff --git a/src/te/apps/tfte/src/tfte_server.erl b/src/te/apps/tfte/src/tfte_server.erl
index 29dddf3d1dab6b08810746c5f5a2ef2636c5ad99..ea80848f7b22ab6280207e90f0c8f1b7aa59db0e 100644
--- a/src/te/apps/tfte/src/tfte_server.erl
+++ b/src/te/apps/tfte/src/tfte_server.erl
@@ -16,6 +16,8 @@
 -export([context_event/1]).
 -export([topology_ready/1]).
 -export([topology_event/1]).
+-export([request_lsp/1]).
+-export([delete_lsp/1]).
 
 % Behaviour gen_statem functions
 -export([init/1]).
@@ -28,6 +30,7 @@
 %%% Records %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 -record(data, {
+    services = #{}
 }).
 
 
@@ -51,6 +54,12 @@ topology_ready(Topology) ->
 topology_event(Event) ->
     gen_statem:cast(?MODULE, {topology_event, Event}).
 
+request_lsp(ServiceMap) ->
+    gen_statem:cast(?MODULE, {request_lsp, ServiceMap}).
+
+delete_lsp(ServiceId) ->
+    gen_statem:cast(?MODULE, {delete_lsp, ServiceId}).
+
 
 %%% BEHAVIOUR gen_statem FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
@@ -83,6 +92,17 @@ handle_event(cast, {topology_ready, _Topology}, ready, _Data) ->
 handle_event(cast, {topology_event, _Event}, ready, _Data) ->
     ?LOG_DEBUG("Teraflow topology event: ~p", [_Event]),
     keep_state_and_data;
+handle_event({call, _From}, {request_lsp, ServiceMap}, ready, Data) ->
+    #{service_id := ServiceId} = ServiceMap,
+    ?LOG_DEBUG("Teraflow service ~s requested its LSPs",
+               [format_service_id(ServiceId)]),
+    {Result, Data2} = do_request_lsp(Data, ServiceMap),
+    {keep_state, Data2, [{reply, Result}]};
+handle_event(cast, {delete_lsp, ServiceId}, ready, Data) ->
+    ?LOG_DEBUG("Teraflow service ~s delete its LSPs",
+              [format_service_id(ServiceId)]),
+    {Result, Data2} = do_delete_lsp(Data, ServiceId),
+    {keep_state, Data2, [{reply, Result}]};
 %-- ANY STATE ------------------------------------------------------------------
 handle_event(EventType, EventContent, State, Data) ->
     ?LOG_WARNING(Data, "Unexpected ~w event in state ~w: ~w",
@@ -98,3 +118,42 @@ code_change(_OldVsn, OldState, OldData, _Extra) ->
 
 
 %%% INTERNAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+format_service_id(#{context_id := #{context_uuid := #{uuid := ContextName}},
+                    service_uuid := #{uuid := ServiceUUID}}) ->
+    iolist_to_binary(io_lib:format("~s:~s", [ContextName, ServiceUUID])).
+
+do_request_lsp(#data{services = Services} = Data,
+               #{service_type := 'SERVICETYPE_TE'} = ServiceMap) ->
+    #{service_config := Config,
+      service_endpoint_ids := Endpoints,
+      service_id := ServiceId} = ServiceMap,
+    #{binding_label := BindingLabel1, symbolic_name := SymbolicName1}
+        = tfte_util:custom_config(Config, <<"/lsp-fw">>),
+    #{binding_label := BindingLabel2, symbolic_name := SymbolicName2}
+        = tfte_util:custom_config(Config, <<"/lsp-bw">>),
+    [#{device_id := #{device_uuid := #{uuid := Id1}}},
+     #{device_id := #{device_uuid := #{uuid := Id2}}}] = Endpoints,
+    case epce_server:initiate_flow(SymbolicName1, Id1, Id2, BindingLabel1) of
+        {error, Reason} ->
+            ?LOG_ERROR("Error while setting up service ~s forward LSP: ~p",
+                       [format_service_id(ServiceId), Reason]),
+            {'SERVICESTATUS_UNDEFINED', Data};
+        {ok, ForwardFlow} ->
+            case epce_server:initiate_flow(SymbolicName2, Id2, Id1, BindingLabel2) of
+                {error, Reason} ->
+                    ?LOG_ERROR("Error while setting up service ~s backward LSP: ~p",
+                               [format_service_id(ServiceId), Reason]),
+                    %TODO: Cleanup forward flow ?
+                    {'SERVICESTATUS_UNDEFINED', Data};
+                {ok, BackwardFlow} ->
+                    ServiceData = {ServiceMap, ForwardFlow, BackwardFlow},
+                    Services2 = Services#{ServiceId => ServiceData},
+                    Data2 = Data#data{services = Services2},
+                    {'SERVICESTATUS_ACTIVE', Data2}
+            end
+    end.
+
+do_delete_lsp(Data, ServiceId) ->
+    ?LOG_INFO("LSP DELETION REQUESTED ~p", [ServiceId]),
+    {'SERVICESTATUS_UNDEFINED', Data}.
\ No newline at end of file
diff --git a/src/te/apps/tfte/src/tfte_te_service.erl b/src/te/apps/tfte/src/tfte_te_service.erl
index 1cadd7aad0b7f512445fae62fbcdb380d92bf544..2f230fd6b2c7fa55c34d8b22d5289c4e30226b76 100644
--- a/src/te/apps/tfte/src/tfte_te_service.erl
+++ b/src/te/apps/tfte/src/tfte_te_service.erl
@@ -6,6 +6,7 @@
 %%% INCLUDES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 -include_lib("grpcbox/include/grpcbox.hrl").
+-include_lib("kernel/include/logger.hrl").
 
 
 %%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -18,14 +19,22 @@
 
 %%% BEHAVIOUR te_te_service_bhvr CALLBACK FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-request_lsp(_Ctx, _Service) ->
-    {error, {?GRPC_STATUS_UNIMPLEMENTED, <<"Not yet implemented">>},
-             #{headers => #{}, trailers => #{}}}.
+request_lsp(_Ctx, Service) ->
+    ?LOG_ERROR("Requesting LSP: ~p", [Service]),
+    try tfte_server:request_lsp(Service)
+    catch E:R:S ->
+        ?LOG_ERROR("Error while requesting LSP: ~p:~p ~p", [E, R, S]),
+        'SERVICESTATUS_UNDEFINED'
+    end.
 
-update_lsp(_Ctx, _Service) ->
+update_lsp(_Ctx, _ServiceId) ->
     {error, {?GRPC_STATUS_UNIMPLEMENTED, <<"Not yet implemented">>},
              #{headers => #{}, trailers => #{}}}.
 
-delete_lsp(_Ctx, _Service) ->
-    {error, {?GRPC_STATUS_UNIMPLEMENTED, <<"Not yet implemented">>},
-             #{headers => #{}, trailers => #{}}}.
+delete_lsp(_Ctx, ServiceId) ->
+    ?LOG_ERROR("Deleting LSP: ~p", [ServiceId]),
+    try tfte_server:delete_lsp(ServiceId)
+    catch E:R:S ->
+        ?LOG_ERROR("Error while deleting LSP: ~p:~p ~p", [E, R, S]),
+        'SERVICESTATUS_UNDEFINED'
+    end.
diff --git a/src/te/apps/tfte/src/tfte_topology.erl b/src/te/apps/tfte/src/tfte_topology.erl
index d2c6fc0d9cdb2ceb097bc21dff5211308ed7bd9e..54825c409614c7adfd9a2844ace899c4703f9d5c 100644
--- a/src/te/apps/tfte/src/tfte_topology.erl
+++ b/src/te/apps/tfte/src/tfte_topology.erl
@@ -281,37 +281,31 @@ device_status(#{device_operational_status := 'DEVICEOPERATIONALSTATUS_ENABLED'})
     enabled.
 
 device_mpls_label(Device) ->
-    case device_config_value(<<"mpls_label">>, Device) of
+    case device_config_value(<<"/te_data/mpls_label">>, Device) of
         undefined -> undefined;
-        LabelBin ->
-            try binary_to_integer(LabelBin)
+        LabelJson ->
+            try jsx:decode(LabelJson)
             catch error:badarg -> undefined
             end
     end.
 
 device_pcc_address(Device) ->
-    case device_config_value(<<"pcc_address">>, Device) of
+    case device_config_value(<<"/te_data/pcc_address">>, Device) of
         undefined -> undefined;
-        AddressBin ->
-            case inet_parse:address(binary_to_list(AddressBin)) of
-                {ok, Address} -> Address;
-                {error,einval} -> undefined
+        AddressJson ->
+            try jsx:decode(AddressJson) of
+                AddressBin ->
+                    case inet_parse:address(binary_to_list(AddressBin)) of
+                        {ok, Address} -> Address;
+                        {error,einval} -> undefined
+                    end
+            catch
+                error:badarg -> undefined
             end
     end.
 
-device_config_value(Key, #{device_config := #{config_rules := Rules}}) ->
-    device_config_value(Key, Rules);
-device_config_value(_Key, []) ->
-    undefined;
-device_config_value(Key, [#{action := 'CONFIGACTION_SET',
-                          config_rule := {custom, Rule}} | Rest]) ->
-    case Rule of
-        #{resource_key := Key, resource_value := Value} -> Value;
-        _ -> device_config_value(Key, Rest)
-    end;
-device_config_value(Key, [_Rule | Rest]) ->
-    device_config_value(Key, Rest).
-
+device_config_value(Key, #{device_config := Config}) ->
+    tfte_util:custom_config(Config, Key).
 
 device_endpoints(Device) ->
     device_endpoints(Device, []).
diff --git a/src/te/apps/tfte/src/tfte_util.erl b/src/te/apps/tfte/src/tfte_util.erl
new file mode 100644
index 0000000000000000000000000000000000000000..7b766b5ba5d1bad92c883e066914abf97463dd30
--- /dev/null
+++ b/src/te/apps/tfte/src/tfte_util.erl
@@ -0,0 +1,27 @@
+-module(tfte_util).
+
+%%% INCLUDES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+-include_lib("kernel/include/logger.hrl").
+
+
+%%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% API functions
+-export([custom_config/2]).
+
+
+%%% API FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+custom_config(#{config_rules := Rules}, Key) ->
+    custom_config(Rules, Key);
+custom_config([], _Key) ->
+    undefined;
+custom_config([#{action := 'CONFIGACTION_SET',
+                       config_rule := {custom, Rule}} | Rest], Key) ->
+    case Rule of
+        #{resource_key := Key, resource_value := Value} -> jsx:decode(Value);
+        _ -> custom_config(Rest, Key)
+    end;
+custom_config([_Rule | Rest], Key) ->
+    custom_config(Rest, Key).
diff --git a/src/te/rebar.config b/src/te/rebar.config
index 776a802492d12473dfd428ba136d777d62a21d68..06bff13c75ef30efbdf2e10a8ff2504d83366825 100644
--- a/src/te/rebar.config
+++ b/src/te/rebar.config
@@ -2,6 +2,7 @@
 
 {deps, [
     grpcbox,
+    jsx,
     {pcep_server, {git, "https://github.com/stritzinger/pcep_server.git", {branch, "master"}}}
 ]}.
 
@@ -17,6 +18,7 @@
         runtime_tools,
         epce,
         grpcbox,
+        jsx,
         tfpb,
         tfte
     ]},
diff --git a/src/te/rebar.lock b/src/te/rebar.lock
index 446884e6bea9e743e6b1575f3291982c54a2f538..c435b045661e26b84495269c3ba79406990d09fb 100644
--- a/src/te/rebar.lock
+++ b/src/te/rebar.lock
@@ -9,6 +9,7 @@
  {<<"gproc">>,{pkg,<<"gproc">>,<<"0.8.0">>},1},
  {<<"grpcbox">>,{pkg,<<"grpcbox">>,<<"0.15.0">>},0},
  {<<"hpack">>,{pkg,<<"hpack_erl">>,<<"0.2.3">>},2},
+ {<<"jsx">>,{pkg,<<"jsx">>,<<"3.1.0">>},0},
  {<<"pcep_codec">>,
   {git,"https://github.com/stritzinger/pcep_codec.git",
        {ref,"ca5eb0822d9971ec4bcfb427a49b2e516081a126"}},
@@ -26,6 +27,7 @@
  {<<"gproc">>, <<"CEA02C578589C61E5341FCE149EA36CCEF236CC2ECAC8691FBA408E7EA77EC2F">>},
  {<<"grpcbox">>, <<"97C7126296A091602D372EBF5860A04F7BC795B45B33A984CAD2B8E362774FD8">>},
  {<<"hpack">>, <<"17670F83FF984AE6CD74B1C456EDDE906D27FF013740EE4D9EFAA4F1BF999633">>},
+ {<<"jsx">>, <<"D12516BAA0BB23A59BB35DCCAF02A1BD08243FCBB9EFE24F2D9D056CCFF71268">>},
  {<<"ranch">>, <<"FBF3D79661C071543256F9051CAF19D65DAA6DF1CF6824D8F37A49B19A66F703">>}]},
 {pkg_hash_ext,[
  {<<"acceptor_pool">>, <<"0CBCD83FDC8B9AD2EEE2067EF8B91A14858A5883CB7CD800E6FCD5803E158788">>},
@@ -34,5 +36,6 @@
  {<<"gproc">>, <<"580ADAFA56463B75263EF5A5DF4C86AF321F68694E7786CB057FD805D1E2A7DE">>},
  {<<"grpcbox">>, <<"161ABE9E17E7D1982EFA6488ADEAA13C3E847A07984A6E6B224E553368918647">>},
  {<<"hpack">>, <<"06F580167C4B8B8A6429040DF36CC93BBA6D571FAEAEC1B28816523379CBB23A">>},
+ {<<"jsx">>, <<"0C5CC8FDC11B53CC25CF65AC6705AD39E54ECC56D1C22E4ADB8F5A53FB9427F3">>},
  {<<"ranch">>, <<"C20A4840C7D6623C19812D3A7C828B2F1BD153EF0F124CB69C54FE51D8A42AE0">>}]}
 ].