diff --git a/apps/mcast/web/src/main/java/org/onosproject/mcast/web/McastRouteWebResource.java b/apps/mcast/web/src/main/java/org/onosproject/mcast/web/McastRouteWebResource.java
index c198a66..26e3317 100644
--- a/apps/mcast/web/src/main/java/org/onosproject/mcast/web/McastRouteWebResource.java
+++ b/apps/mcast/web/src/main/java/org/onosproject/mcast/web/McastRouteWebResource.java
@@ -16,14 +16,35 @@
 
 package org.onosproject.mcast.web;
 
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.google.common.annotations.Beta;
+import com.google.common.collect.ImmutableSet;
+import org.onlab.packet.IpAddress;
+import org.onosproject.mcast.api.McastRoute;
+import org.onosproject.mcast.api.MulticastRouteService;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.HostId;
 import org.onosproject.rest.AbstractWebResource;
 
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
+import javax.ws.rs.POST;
 import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+
+import static org.onlab.util.Tools.nullIsIllegal;
 
 /**
  * Manage the multicast routing information.
@@ -32,6 +53,20 @@
 @Path("mcast")
 public class McastRouteWebResource extends AbstractWebResource {
 
+    //TODO return error messages
+
+    private static final String SOURCES = "sources";
+    private static final String SINKS = "sinks";
+    private static final String ROUTES = "routes";
+    private static final String ROUTES_KEY_ERROR = "No routes";
+    private static final String ASM = "*";
+
+    private Optional<McastRoute> getStaticRoute(Set<McastRoute> mcastRoutes) {
+        return mcastRoutes.stream()
+                .filter(mcastRoute -> mcastRoute.type() == McastRoute.Type.STATIC)
+                .findAny();
+    }
+
     /**
      * Get all multicast routes.
      * Returns array of all known multicast routes.
@@ -41,7 +76,462 @@
     @GET
     @Produces(MediaType.APPLICATION_JSON)
     public Response getRoutes() {
+        Set<McastRoute> routes = get(MulticastRouteService.class).getRoutes();
+        ObjectNode root = encodeArray(McastRoute.class, ROUTES, routes);
+        return ok(root).build();
+    }
+
+    /**
+     * Gets a multicast route.
+     *
+     * @param group group IP address
+     * @param srcIp source IP address
+     * @return 200 OK with a multicast routes
+     */
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("{group}/{srcIp}")
+    public Response getRoute(@PathParam("group") String group,
+                             @PathParam("srcIp") String srcIp) {
+        Optional<McastRoute> route = getMcastRoute(group, srcIp);
+        if (route.isPresent()) {
+            ObjectNode root = encode(route.get(), McastRoute.class);
+            return ok(root).build();
+        }
         return Response.noContent().build();
     }
 
+    /**
+     * Get all sources connect points for a multicast route.
+     *
+     * @param group group IP address
+     * @param srcIp source IP address
+     * @return 200 OK with array of all sources for multicast route
+     */
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("sources/{group}/{srcIp}")
+    public Response getSources(@PathParam("group") String group,
+                               @PathParam("srcIp") String srcIp) {
+        Optional<McastRoute> route = getMcastRoute(group, srcIp);
+        if (route.isPresent()) {
+            get(MulticastRouteService.class).sources(route.get());
+            ArrayNode node = this.mapper().createArrayNode();
+            get(MulticastRouteService.class).sources(route.get()).forEach(source -> {
+                node.add(source.toString());
+            });
+            ObjectNode root = this.mapper().createObjectNode().putPOJO(SOURCES, node);
+            return ok(root).build();
+        }
+        return Response.noContent().build();
+    }
+
+    /**
+     * Get all sinks connect points for a multicast route.
+     *
+     * @param group group IP address
+     * @param srcIp source IP address
+     * @return 200 OK with array of all sinks for multicast route
+     */
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("sinks/{group}/{srcIp}")
+    public Response getSinks(@PathParam("group") String group,
+                             @PathParam("srcIp") String srcIp) {
+        Optional<McastRoute> route = getMcastRoute(group, srcIp);
+        if (route.isPresent()) {
+            get(MulticastRouteService.class).sources(route.get());
+            ObjectNode sinks = this.mapper().createObjectNode();
+            get(MulticastRouteService.class).routeData(route.get()).sinks().forEach((k, v) -> {
+                ArrayNode node = this.mapper().createArrayNode();
+                v.forEach(sink -> {
+                    node.add(sink.toString());
+                });
+                sinks.putPOJO(k.toString(), node);
+            });
+            ObjectNode root = this.mapper().createObjectNode().putPOJO(SINKS, sinks);
+            return ok(root).build();
+        }
+        return Response.noContent().build();
+    }
+
+    /**
+     * Get all sink connect points for a given sink host in a multicast route.
+     *
+     * @param group  group IP address
+     * @param srcIp  source IP address
+     * @param hostId host Id
+     * @return 200 OK with array of all sinks for multicast route
+     */
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("sinks/{group}/{srcIp}/{hostId}")
+    public Response getHostSinks(@PathParam("group") String group,
+                                 @PathParam("srcIp") String srcIp,
+                                 @PathParam("hostId") String hostId) {
+        Optional<McastRoute> route = getMcastRoute(group, srcIp);
+        if (route.isPresent()) {
+            get(MulticastRouteService.class).sources(route.get());
+            ArrayNode node = this.mapper().createArrayNode();
+            get(MulticastRouteService.class).sinks(route.get(), HostId.hostId(hostId))
+                    .forEach(source -> {
+                        node.add(source.toString());
+                    });
+            ObjectNode root = this.mapper().createObjectNode().putPOJO(SINKS, node);
+            return ok(root).build();
+        }
+        return Response.noContent().build();
+    }
+
+    /**
+     * Creates a set of new multicast routes.
+     *
+     * @param stream multicast routes JSON
+     * @return status of the request - CREATED if the JSON is correct,
+     * BAD_REQUEST if the JSON is invalid
+     * @onos.rsModel McastRouteBulk
+     */
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Path("bulk/")
+    public Response createRoutes(InputStream stream) {
+        MulticastRouteService service = get(MulticastRouteService.class);
+        try {
+            ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
+            ArrayNode routesArray = nullIsIllegal((ArrayNode) jsonTree.get(ROUTES),
+                    ROUTES_KEY_ERROR);
+            routesArray.forEach(routeJson -> {
+                McastRoute route = codec(McastRoute.class).decode((ObjectNode) routeJson, this);
+                service.add(route);
+
+                Set<ConnectPoint> sources = new HashSet<>();
+                routeJson.path(SOURCES).elements().forEachRemaining(src -> {
+                    sources.add(ConnectPoint.deviceConnectPoint(src.asText()));
+                });
+                Set<HostId> sinks = new HashSet<>();
+                routeJson.path(SINKS).elements().forEachRemaining(sink -> {
+                    sinks.add(HostId.hostId(sink.asText()));
+                });
+
+                if (!sources.isEmpty()) {
+                    service.addSources(route, sources);
+                }
+                if (!sinks.isEmpty()) {
+                    sinks.forEach(sink -> {
+                        service.addSink(route, sink);
+                    });
+                }
+            });
+        } catch (IOException ex) {
+            throw new IllegalArgumentException(ex);
+        }
+
+        return Response
+                .created(URI.create(""))
+                .build();
+    }
+
+    /**
+     * Create new multicast route.
+     *
+     * @param stream multicast route JSON
+     * @return status of the request - CREATED if the JSON is correct,
+     * BAD_REQUEST if the JSON is invalid
+     * @onos.rsModel McastRoute
+     */
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    public Response createRoute(InputStream stream) {
+        MulticastRouteService service = get(MulticastRouteService.class);
+        try {
+            ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
+            McastRoute route = codec(McastRoute.class).decode(jsonTree, this);
+            service.add(route);
+
+            Set<ConnectPoint> sources = new HashSet<>();
+            jsonTree.path(SOURCES).elements().forEachRemaining(src -> {
+                sources.add(ConnectPoint.deviceConnectPoint(src.asText()));
+            });
+            Set<HostId> sinks = new HashSet<>();
+            jsonTree.path(SINKS).elements().forEachRemaining(sink -> {
+                sinks.add(HostId.hostId(sink.asText()));
+            });
+
+            if (!sources.isEmpty()) {
+                service.addSources(route, sources);
+            }
+            if (!sinks.isEmpty()) {
+                sinks.forEach(sink -> {
+                    service.addSink(route, sink);
+                });
+            }
+
+        } catch (IOException ex) {
+            throw new IllegalArgumentException(ex);
+        }
+
+        return Response
+                .created(URI.create(""))
+                .build();
+    }
+
+    /**
+     * Adds sources for a given existing multicast route.
+     *
+     * @param group  group IP address
+     * @param srcIp  source IP address
+     * @param stream host sinks JSON
+     * @return status of the request - CREATED if the JSON is correct,
+     * BAD_REQUEST if the JSON is invalid
+     * @onos.rsModel McastSourcesAdd
+     */
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("sources/{group}/{srcIp}")
+    public Response addSources(@PathParam("group") String group,
+                               @PathParam("srcIp") String srcIp,
+                               InputStream stream) {
+        MulticastRouteService service = get(MulticastRouteService.class);
+        Optional<McastRoute> route = getMcastRoute(group, srcIp);
+        if (route.isPresent()) {
+            ArrayNode jsonTree;
+            try {
+                jsonTree = (ArrayNode) mapper().readTree(stream).get(SOURCES);
+                Set<ConnectPoint> sources = new HashSet<>();
+                jsonTree.elements().forEachRemaining(src -> {
+                    sources.add(ConnectPoint.deviceConnectPoint(src.asText()));
+                });
+                if (!sources.isEmpty()) {
+                    service.addSources(route.get(), sources);
+                }
+            } catch (IOException e) {
+                throw new IllegalArgumentException(e);
+            }
+            return Response.ok().build();
+        }
+        return Response.noContent().build();
+
+    }
+
+    /**
+     * Adds sinks for a given existing multicast route.
+     *
+     * @param group  group IP address
+     * @param srcIp  source IP address
+     * @param stream host sinks JSON
+     * @return status of the request - CREATED if the JSON is correct,
+     * BAD_REQUEST if the JSON is invalid
+     * @onos.rsModel McastSinksAdd
+     */
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("sinks/{group}/{srcIp}")
+    public Response addSinks(@PathParam("group") String group,
+                             @PathParam("srcIp") String srcIp,
+                             InputStream stream) {
+        MulticastRouteService service = get(MulticastRouteService.class);
+        Optional<McastRoute> route = getMcastRoute(group, srcIp);
+        if (route.isPresent()) {
+            ArrayNode jsonTree;
+            try {
+                jsonTree = (ArrayNode) mapper().readTree(stream).get(SINKS);
+                Set<HostId> sinks = new HashSet<>();
+                jsonTree.elements().forEachRemaining(sink -> {
+                    sinks.add(HostId.hostId(sink.asText()));
+                });
+                if (!sinks.isEmpty()) {
+                    sinks.forEach(sink -> {
+                        service.addSink(route.get(), sink);
+                    });
+                }
+            } catch (IOException e) {
+                throw new IllegalArgumentException(e);
+            }
+            return Response.ok().build();
+        }
+        return Response.noContent().build();
+    }
+
+
+    /**
+     * Adds a new sink for an existing host in a given multicast route.
+     *
+     * @param group  group IP address
+     * @param srcIp  source IP address
+     * @param hostId the host Id
+     * @param stream sink connect points JSON
+     * @return status of the request - CREATED if the JSON is correct,
+     * BAD_REQUEST if the JSON is invalid
+     * @onos.rsModel McastHostSinksAdd
+     */
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("sinks/{group}/{srcIp}/{hostId}")
+    public Response addHostSinks(@PathParam("group") String group,
+                                 @PathParam("srcIp") String srcIp,
+                                 @PathParam("hostId") String hostId,
+                                 InputStream stream) {
+        MulticastRouteService service = get(MulticastRouteService.class);
+        Optional<McastRoute> route = getMcastRoute(group, srcIp);
+        if (route.isPresent()) {
+            ArrayNode jsonTree;
+            try {
+                jsonTree = (ArrayNode) mapper().readTree(stream).get(SINKS);
+                Set<ConnectPoint> sinks = new HashSet<>();
+                jsonTree.elements().forEachRemaining(src -> {
+                    sinks.add(ConnectPoint.deviceConnectPoint(src.asText()));
+                });
+                if (!sinks.isEmpty()) {
+                    service.addSinks(route.get(), HostId.hostId(hostId), sinks);
+                }
+            } catch (IOException e) {
+                throw new IllegalArgumentException(e);
+            }
+            return Response.ok().build();
+        }
+        return Response.noContent().build();
+    }
+
+    /**
+     * Removes all the multicast routes.
+     *
+     * @return 204 NO CONTENT
+     */
+    @DELETE
+    public Response deleteRoutes() {
+        MulticastRouteService service = get(MulticastRouteService.class);
+        service.getRoutes().forEach(service::remove);
+        return Response.noContent().build();
+    }
+
+    /**
+     * Removes all the given multicast routes.
+     *
+     * @param stream the set of multicast routes
+     * @return 204 NO CONTENT
+     */
+    @DELETE
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Path("bulk/")
+    public Response deleteRoutes(InputStream stream) {
+        MulticastRouteService service = get(MulticastRouteService.class);
+        try {
+            ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
+            ArrayNode routesArray = nullIsIllegal((ArrayNode) jsonTree.get(ROUTES),
+                    ROUTES_KEY_ERROR);
+            List<McastRoute> routes = codec(McastRoute.class).decode(routesArray, this);
+            routes.forEach(service::remove);
+        } catch (IOException ex) {
+            throw new IllegalArgumentException(ex);
+        }
+        return Response.noContent().build();
+    }
+
+    /**
+     * Deletes a specific route.
+     *
+     * @param group group IP address
+     * @param srcIp source IP address
+     * @return 204 NO CONTENT
+     */
+    @DELETE
+    @Path("{group}/{srcIp}")
+    public Response deleteRoute(@PathParam("group") String group,
+                                @PathParam("srcIp") String srcIp) {
+        Optional<McastRoute> route = getMcastRoute(group, srcIp);
+        route.ifPresent(mcastRoute -> {
+            get(MulticastRouteService.class).remove(mcastRoute);
+        });
+        return Response.noContent().build();
+    }
+
+    /**
+     * Deletes all the source connect points for a specific route.
+     * If the sources are empty the entire route is removed.
+     *
+     * @param group group IP address
+     * @param srcIp source IP address
+     * @return 204 NO CONTENT
+     */
+    @DELETE
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Path("sources/{group}/{srcIp}")
+    public Response deleteSources(@PathParam("group") String group,
+                                  @PathParam("srcIp") String srcIp) {
+        Optional<McastRoute> route = getMcastRoute(group, srcIp);
+        route.ifPresent(mcastRoute -> get(MulticastRouteService.class).removeSources(mcastRoute));
+        return Response.noContent().build();
+    }
+
+    /**
+     * Deletes a source connect point for a specific route.
+     * If the sources are empty the entire route is removed.
+     *
+     * @param group group IP address
+     * @param srcIp source IP address
+     * @param srcCp source connect point
+     * @return 204 NO CONTENT
+     */
+    @DELETE
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Path("sources/{group}/{srcIp}/{srcCp}")
+    public Response deleteSource(@PathParam("group") String group,
+                                 @PathParam("srcIp") String srcIp,
+                                 @PathParam("srcCp") String srcCp) {
+        Optional<McastRoute> route = getMcastRoute(group, srcIp);
+        route.ifPresent(mcastRoute -> get(MulticastRouteService.class)
+                .removeSources(mcastRoute, ImmutableSet.of(ConnectPoint.deviceConnectPoint(srcCp))));
+        return Response.noContent().build();
+    }
+
+    /**
+     * Deletes all the sinks for a specific route.
+     *
+     * @param group group IP address
+     * @param srcIp source IP address
+     * @return 204 NO CONTENT
+     */
+    @DELETE
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Path("sinks/{group}/{srcIp}")
+    public Response deleteHostsSinks(@PathParam("group") String group,
+                                     @PathParam("srcIp") String srcIp) {
+        Optional<McastRoute> route = getMcastRoute(group, srcIp);
+        route.ifPresent(mcastRoute -> get(MulticastRouteService.class)
+                .removeSinks(mcastRoute));
+        return Response.noContent().build();
+    }
+
+    /**
+     * Deletes a sink connect points for a given host for a specific route.
+     *
+     * @param group  group IP address
+     * @param srcIp  source IP address
+     * @param hostId sink host
+     * @return 204 NO CONTENT
+     */
+    @DELETE
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Path("sinks/{group}/{srcIp}/{hostId}")
+    public Response deleteHostSinks(@PathParam("group") String group,
+                                    @PathParam("srcIp") String srcIp,
+                                    @PathParam("hostId") String hostId) {
+        Optional<McastRoute> route = getMcastRoute(group, srcIp);
+        route.ifPresent(mcastRoute -> get(MulticastRouteService.class)
+                .removeSink(mcastRoute, HostId.hostId(hostId)));
+        return Response.noContent().build();
+    }
+
+    private Optional<McastRoute> getMcastRoute(String group, String srcIp) {
+        IpAddress ipAddress = null;
+        if (!srcIp.equals(ASM)) {
+            ipAddress = IpAddress.valueOf(srcIp);
+        }
+        return getStaticRoute(get(MulticastRouteService.class)
+                .getRoute(IpAddress.valueOf(group), ipAddress));
+    }
+
 }
