diff --git a/Makefile.dep b/Makefile.dep
index f596f883f685a2711445b0dbc292ad5a268d39d2..802f98b2aa5c2420bc887b8ec414158cd4a38090 100644
--- a/Makefile.dep
+++ b/Makefile.dep
@@ -57,6 +57,10 @@ ifneq (,$(filter gnrc_conn_udp,$(USEMODULE)))
   USEMODULE += gnrc_udp
 endif
 
+ifneq (,$(filter gnrc_netapi_mbox,$(USEMODULE)))
+  USEMODULE += core_mbox
+endif
+
 ifneq (,$(filter netdev2_tap,$(USEMODULE)))
   USEMODULE += netif
   USEMODULE += netdev2_eth
diff --git a/Makefile.pseudomodules b/Makefile.pseudomodules
index 9e02789345f0f5ba206cdcb6d32c5bfdab52d3ff..438fa415ad90cc9e8ff7c3b359cd07b921676906 100644
--- a/Makefile.pseudomodules
+++ b/Makefile.pseudomodules
@@ -12,6 +12,7 @@ PSEUDOMODULES += gnrc_ipv6_router
 PSEUDOMODULES += gnrc_ipv6_router_default
 PSEUDOMODULES += gnrc_netdev_default
 PSEUDOMODULES += gnrc_neterr
+PSEUDOMODULES += gnrc_netapi_mbox
 PSEUDOMODULES += gnrc_pktbuf
 PSEUDOMODULES += gnrc_sixlowpan_border_router_default
 PSEUDOMODULES += gnrc_sixlowpan_default
diff --git a/sys/include/net/gnrc/netapi.h b/sys/include/net/gnrc/netapi.h
index 52ce4ae7a945dbe3de89895efcb9cd268fe47245..63ea497b7820bd80643c52782ffa9ff81cba057e 100644
--- a/sys/include/net/gnrc/netapi.h
+++ b/sys/include/net/gnrc/netapi.h
@@ -21,6 +21,21 @@
  * @file
  * @brief       Generic interface to communicate with GNRC modules
  *
+ * @defgroup    net_gnrc_netapi_mbox   Mailbox IPC extension
+ * @ingroup     net_gnrc_netapi
+ * @brief       @ref core_mbox "Mailbox IPC" extension for @ref net_gnrc_netapi
+ * @{
+ *
+ * @details The submodule `gnrc_netapi_mbox` provides an extension for
+ *          @ref core_mbox "Mailbox IPC".
+ *
+ * To use, add the module `gnrc_netapi_mbox` to the `USEMODULE` macro in your
+ * application's Makefile:
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.mk}
+ * USEMODULE += gnrc_netapi_mbox
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * @}
  * @author      Martine Lenders <mlenders@inf.fu-berlin.de>
  * @author      Hauke Petersen <hauke.petersen@fu-berlin.de>
  */
diff --git a/sys/include/net/gnrc/netreg.h b/sys/include/net/gnrc/netreg.h
index 0b7b48a86f30406031be5fc90eb8b74792467bba..d040f332c95cb0a2fba4cb0519c01140b88ce23a 100644
--- a/sys/include/net/gnrc/netreg.h
+++ b/sys/include/net/gnrc/netreg.h
@@ -27,10 +27,24 @@
 #include "net/gnrc/nettype.h"
 #include "net/gnrc/pkt.h"
 
+#ifdef MODULE_GNRC_NETAPI_MBOX
+#include "mbox.h"
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#if defined(MODULE_GNRC_NETAPI_MBOX) || defined(DOXYGEN)
+typedef enum {
+    GNRC_NETREG_TYPE_DEFAULT = 0,
+#if defined(MODULE_GNRC_NETAPI_MBOX) || defined(DOXYGEN)
+    GNRC_NETREG_TYPE_MBOX,
+#endif
+    GNRC_NETREG_TYPE_CB,
+} gnrc_netreg_type_t;
+#endif
+
 /**
  * @brief   Demux context value to get all packets of a certain type.
  *
@@ -47,7 +61,30 @@ extern "C" {
  *
  * @return  An initialized netreg entry
  */
-#define GNRC_NETREG_ENTRY_INIT_PID(demux_ctx, pid)  { NULL, demux_ctx, pid }
+#ifdef MODULE_GNRC_NETAPI_MBOX
+#define GNRC_NETREG_ENTRY_INIT_PID(demux_ctx, pid)  { NULL, demux_ctx, \
+                                                      GNRC_NETREG_TYPE_DEFAULT, \
+                                                      { pid } }
+#else
+#define GNRC_NETREG_ENTRY_INIT_PID(demux_ctx, pid)  { NULL, demux_ctx, { pid } }
+#endif
+
+#if defined(MODULE_GNRC_NETAPI_MBOX) || defined(DOXYGEN)
+/**
+ * @brief   Initializes a netreg entry statically with mbox
+ *
+ * @param[in] demux_ctx The @ref gnrc_netreg_entry_t::demux_ctx "demux context"
+ *                      for the netreg entry
+ * @param[in] mbox      Target @ref core_mbox "mailbox" for the registry entry
+ *
+ * @note    Only available with @ref net_gnrc_netreg_extra.
+ *
+ * @return  An initialized netreg entry
+ */
+#define GNRC_NETREG_ENTRY_INIT_MBOX(demux_ctx, mbox) { NULL, demux_ctx, \
+                                                       GNRC_NETREG_TYPE_MBOX, \
+                                                       { .mbox = mbox } }
+#endif
 
 /**
  * @brief   Entry to the @ref net_gnrc_netreg
@@ -68,7 +105,26 @@ typedef struct gnrc_netreg_entry {
      *          ports in UDP/TCP, or similar.
      */
     uint32_t demux_ctx;
-    kernel_pid_t pid;       /**< The PID of the registering thread */
+#if defined(MODULE_GNRC_NETAPI_MBOX) || defined(DOXYGEN)
+    /**
+     * @brief   Type of the registry entry
+     *
+     * @note    Only available with @ref net_gnrc_netapi_mbox or
+     *          @ref net_gnrc_netapi_callbacks.
+     */
+    gnrc_netreg_type_t type;
+#endif
+    union {
+        kernel_pid_t pid;       /**< The PID of the registering thread */
+#if defined(MODULE_GNRC_NETAPI_MBOX) || defined(DOXYGEN)
+        /**
+         * @brief   Target @ref core_mbox "mailbox" for the registry entry
+         *
+         * @note    Only available with @ref net_gnrc_netapi_mbox.
+         */
+        mbox_t *mbox;
+#endif
+    } target;                   /**< Target for the registry entry */
 } gnrc_netreg_entry_t;
 
 /**
@@ -91,9 +147,34 @@ static inline void gnrc_netreg_entry_init_pid(gnrc_netreg_entry_t *entry,
 {
     entry->next = NULL;
     entry->demux_ctx = demux_ctx;
-    entry->pid = pid;
+#ifdef MODULE_GNRC_NETAPI_MBOX
+    entry->type = GNRC_NETREG_TYPE_DEFAULT;
+#endif
+    entry->target.pid = pid;
 }
 
+#if defined(MODULE_GNRC_NETAPI_MBOX) || defined(DOXYGEN)
+/**
+ * @brief   Initializes a netreg entry dynamically with mbox
+ *
+ * @param[out] entry    A netreg entry
+ * @param[in] demux_ctx The @ref gnrc_netreg_entry_t::demux_ctx "demux context"
+ *                      for the netreg entry
+ * @param[in] mbox      Target @ref core_mbox "mailbox" for the registry entry
+ *
+ * @note    Only available with @ref net_gnrc_netapi_mbox.
+ */
+static inline void gnrc_netreg_entry_init_mbox(gnrc_netreg_entry_t *entry,
+                                               uint32_t demux_ctx,
+                                               mbox_t *mbox)
+{
+    entry->next = NULL;
+    entry->demux_ctx = demux_ctx;
+    entry->type = GNRC_NETREG_TYPE_MBOX;
+    entry->target.mbox = mbox;
+}
+#endif
+
 /**
  * @brief   Registers a thread to the registry.
  *
diff --git a/sys/net/gnrc/netapi/gnrc_netapi.c b/sys/net/gnrc/netapi/gnrc_netapi.c
index a6294cbcabb8988b52e8f37e6dd6ffb49530f582..5f80302524108256c0dedd64d6b57f1929482550 100644
--- a/sys/net/gnrc/netapi/gnrc_netapi.c
+++ b/sys/net/gnrc/netapi/gnrc_netapi.c
@@ -18,6 +18,7 @@
  * @}
  */
 
+#include "mbox.h"
 #include "msg.h"
 #include "net/gnrc/netreg.h"
 #include "net/gnrc/pktbuf.h"
@@ -74,6 +75,22 @@ static inline int _snd_rcv(kernel_pid_t pid, uint16_t type, gnrc_pktsnip_t *pkt)
     return ret;
 }
 
+#ifdef MODULE_GNRC_NETAPI_MBOX
+static inline int _snd_rcv_mbox(mbox_t *mbox, uint16_t type, gnrc_pktsnip_t *pkt)
+{
+    msg_t msg;
+    /* set the outgoing message's fields */
+    msg.type = type;
+    msg.content.ptr = (void *)pkt;
+    /* send message */
+    int ret = mbox_try_put(mbox, &msg);
+    if (ret < 1) {
+        DEBUG("gnrc_netapi: dropped message to %p (was full)\n", mbox);
+    }
+    return ret;
+}
+#endif
+
 int gnrc_netapi_dispatch(gnrc_nettype_t type, uint32_t demux_ctx,
                          uint16_t cmd, gnrc_pktsnip_t *pkt)
 {
@@ -85,10 +102,35 @@ int gnrc_netapi_dispatch(gnrc_nettype_t type, uint32_t demux_ctx,
         gnrc_pktbuf_hold(pkt, numof - 1);
 
         while (sendto) {
-            if (_snd_rcv(sendto->pid, cmd, pkt) < 1) {
+#ifdef MODULE_GNRC_NETAPI_MBOX
+            int release = 0;
+            switch (sendto->type) {
+                case GNRC_NETREG_TYPE_DEFAULT:
+                    if (_snd_rcv(sendto->target.pid, cmd, pkt) < 1) {
+                        /* unable to dispatch packet */
+                        release = 1;
+                    }
+                    break;
+                case GNRC_NETREG_TYPE_MBOX:
+                    if (_snd_rcv_mbox(sendto->target.mbox, cmd, pkt) < 1) {
+                        /* unable to dispatch packet */
+                        release = 1;
+                    }
+                    break;
+                default:
+                    /* unknown dispatch type */
+                    release = 1;
+                    break;
+            }
+            if (release) {
+                gnrc_pktbuf_release(pkt);
+            }
+#else
+            if (_snd_rcv(sendto->target.pid, cmd, pkt) < 1) {
                 /* unable to dispatch packet */
                 gnrc_pktbuf_release(pkt);
             }
+#endif
             sendto = gnrc_netreg_getnext(sendto);
         }
     }
diff --git a/sys/net/gnrc/netreg/gnrc_netreg.c b/sys/net/gnrc/netreg/gnrc_netreg.c
index 7effd16f120e34b447008d3314d643ac476f783d..a01c557c72909ab9ad8056a2001754c611acc62a 100644
--- a/sys/net/gnrc/netreg/gnrc_netreg.c
+++ b/sys/net/gnrc/netreg/gnrc_netreg.c
@@ -37,8 +37,16 @@ void gnrc_netreg_init(void)
 
 int gnrc_netreg_register(gnrc_nettype_t type, gnrc_netreg_entry_t *entry)
 {
+#if defined(MODULE_GNRC_NETAPI_MBOX) || defined(MODULE_GNRC_NETAPI_CALLBACKS)
+#ifdef DEVELHELP
     /* only threads with a message queue are allowed to register at gnrc */
-    assert(sched_threads[entry->pid]->msg_array);
+    assert((entry->type != GNRC_NETREG_TYPE_DEFAULT) ||
+           sched_threads[entry->target.pid]->msg_array);
+#endif
+#else
+    /* only threads with a message queue are allowed to register at gnrc */
+    assert(sched_threads[entry->target.pid]->msg_array);
+#endif
 
     if (_INVALID_TYPE(type)) {
         return -EINVAL;