diff --git a/controller/api/app.go b/controller/api/app.go
new file mode 100644
index 0000000000000000000000000000000000000000..fcb66d5f4ac4453d72e50b10a88fd2ad7db6dd8e
--- /dev/null
+++ b/controller/api/app.go
@@ -0,0 +1,40 @@
+package api
+
+import (
+	"context"
+	"time"
+
+	apb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/app"
+	nbi "code.fbi.h-da.de/danet/gosdn/controller/northbound/client"
+)
+
+// Register checks if the app already exists and if not creates a new one.
+func Register(ctx context.Context, addr, appname, token string) (*apb.AppRegisterResponse, error) {
+	appClient, err := nbi.AppClient(addr, dialOptions...)
+	if err != nil {
+		return nil, err
+	}
+
+	req := &apb.AppRegisterRequest{
+		Timestamp: time.Now().UnixNano(),
+		Appname:   appname,
+		Token:     token,
+	}
+
+	return appClient.Register(ctx, req)
+}
+
+// Deregister deregisters an app.
+func Deregister(ctx context.Context, addr, appname, token string) (*apb.AppDeregisterResponse, error) {
+	appClient, err := nbi.AppClient(addr, dialOptions...)
+	if err != nil {
+		return nil, err
+	}
+
+	req := &apb.AppDeregisterRequest{
+		Timestamp: time.Now().UnixNano(),
+		Appname:   appname,
+	}
+
+	return appClient.Deregister(ctx, req)
+}
diff --git a/controller/northbound/client/app.go b/controller/northbound/client/app.go
new file mode 100644
index 0000000000000000000000000000000000000000..750af3056c54d174b6c9c07716533b0ae0a247cc
--- /dev/null
+++ b/controller/northbound/client/app.go
@@ -0,0 +1,17 @@
+package client
+
+import (
+	apb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/app"
+	"google.golang.org/grpc"
+)
+
+// AppClient returns a client for the gRPC App service. It takes
+// the address of the gRPC endpoint and optional grpc.DialOption
+// as argument.
+func AppClient(addr string, opts ...grpc.DialOption) (apb.AppServiceClient, error) {
+	conn, err := grpc.Dial(addr, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return apb.NewAppServiceClient(conn), nil
+}