diff --git a/examples/lorawan/main.c b/examples/lorawan/main.c
index 97770294d03f8634513a28ced684c47166305f46..da2e43212d392a359e92517bf7ad3a46fa4cb587 100644
--- a/examples/lorawan/main.c
+++ b/examples/lorawan/main.c
@@ -67,9 +67,15 @@ static void _prepare_next_alarm(void)
 static void _send_message(void)
 {
     printf("Sending: %s\n", message);
-    /* The send call blocks until done */
-    semtech_loramac_send(&loramac, (uint8_t *)message, strlen(message));
-    /* Wait until the send cycle has completed */
+    /* Try to send the message */
+    uint8_t ret = semtech_loramac_send(&loramac,
+                                       (uint8_t *)message, strlen(message));
+    if (ret != SEMTECH_LORAMAC_TX_OK) {
+        printf("Cannot send message '%s', ret code: %d\n", message, ret);
+        return;
+    }
+    /* The send was successfully scheduled, now wait until the send cycle has
+       completed and a reply is received from the MAC */
     semtech_loramac_recv(&loramac);
 }
 
diff --git a/pkg/semtech-loramac/contrib/semtech_loramac.c b/pkg/semtech-loramac/contrib/semtech_loramac.c
index 2329708efaf1f630c67ee5f3a09dac32f4938630..7e14f352426df4b1c39e8917cbe7ad567d9ddf36 100644
--- a/pkg/semtech-loramac/contrib/semtech_loramac.c
+++ b/pkg/semtech-loramac/contrib/semtech_loramac.c
@@ -239,6 +239,7 @@ static void mcps_indication(McpsIndication_t *indication)
         msg.content.ptr = indication;
     }
     else {
+        DEBUG("[semtech-loramac] MCPS indication: TX done\n");
         msg.type = MSG_TYPE_LORAMAC_TX_STATUS;
         msg.content.value = SEMTECH_LORAMAC_TX_DONE;
     }
@@ -552,18 +553,16 @@ static void _send(semtech_loramac_t *mac, void *arg)
 {
     loramac_send_params_t params = *(loramac_send_params_t *)arg;
     uint8_t status = _semtech_loramac_send(mac, params.payload, params.len);
-    if (status != SEMTECH_LORAMAC_TX_OK) {
-        msg_t msg;
-        msg.type = MSG_TYPE_LORAMAC_TX_STATUS;
-        msg.content.value = (uint8_t)status;
-        msg_send(&msg, semtech_loramac_pid);
-    }
 #ifdef MODULE_PERIPH_EEPROM
-    else {
+    if (status == SEMTECH_LORAMAC_TX_OK) {
         /* save the uplink counter */
         _save_uplink_counter(mac);
     }
 #endif
+    msg_t msg;
+    msg.type = MSG_TYPE_LORAMAC_TX_STATUS;
+    msg.content.value = (uint8_t)status;
+    msg_send(&msg, semtech_loramac_pid);
 }
 
 static void _semtech_loramac_call(semtech_loramac_func_t func, void *arg)
@@ -708,7 +707,7 @@ void *_semtech_loramac_event_loop(void *arg)
                 }
                 case MSG_TYPE_LORAMAC_TX_STATUS:
                 {
-                    DEBUG("[semtech-loramac] loramac TX status msg\n");
+                    DEBUG("[semtech-loramac] received TX status\n");
                     if (msg.content.value == SEMTECH_LORAMAC_TX_SCHEDULE) {
                         DEBUG("[semtech-loramac] schedule immediate TX\n");
                         uint8_t prev_port = mac->port;
@@ -717,6 +716,7 @@ void *_semtech_loramac_event_loop(void *arg)
                         mac->port = prev_port;
                     }
                     else {
+                        DEBUG("[semtech-loramac] forward TX status to caller thread\n");
                         msg_t msg_ret;
                         msg_ret.type = msg.type;
                         msg_ret.content.value = msg.content.value;
@@ -828,13 +828,23 @@ uint8_t semtech_loramac_send(semtech_loramac_t *mac, uint8_t *data, uint8_t len)
         return SEMTECH_LORAMAC_NOT_JOINED;
     }
 
+    /* Correctly set the caller pid */
+    mac->caller_pid = thread_getpid();
+
     loramac_send_params_t params;
     params.payload = data;
     params.len = len;
 
     _semtech_loramac_call(_send, &params);
 
-    return SEMTECH_LORAMAC_TX_SCHEDULE;
+    /* Wait for TX status information from the MAC */
+    msg_t msg;
+    msg_receive(&msg);
+    if (msg.type != MSG_TYPE_LORAMAC_TX_STATUS) {
+        return SEMTECH_LORAMAC_TX_ERROR;
+    }
+
+    return (uint8_t)msg.content.value;
 }
 
 uint8_t semtech_loramac_recv(semtech_loramac_t *mac)
diff --git a/pkg/semtech-loramac/include/semtech_loramac.h b/pkg/semtech-loramac/include/semtech_loramac.h
index 2e58021d1bc3838aede88f59ef96dbb99fc2c2cc..69c7ad398d1356064f8088fc6979ab64d793264d 100644
--- a/pkg/semtech-loramac/include/semtech_loramac.h
+++ b/pkg/semtech-loramac/include/semtech_loramac.h
@@ -149,17 +149,22 @@ uint8_t semtech_loramac_join(semtech_loramac_t *mac, uint8_t type);
 /**
  * @brief   Sends data to the LoRaWAN network
  *
- * This function returns immediately and leave the mac in busy state until a
- * message is received from the network (with RX1 and RX2 receive windows).
+ * This function returns after TX status is replied from the MAC. To receive
+ * potential messages sent from the network an explicit call to
+ * @ref semtech_loramac_recv must be done after this function if it returned
+ * @ref SEMTECH_LORAMAC_TX_OK and within the RX windows delays.
+ *
  * @see semtech_loramac_recv
  *
  * @param[in] mac          Pointer to the mac
  * @param[in] data         The TX data
  * @param[in] len          The length of the TX data
  *
+ * @return SEMTECH_LORAMAC_TX_OK when the message can be transmitted
  * @return SEMTECH_LORAMAC_NOT_JOINED when the network is not joined
  * @return SEMTECH_LORAMAC_BUSY when the mac is already active (join or tx in progress)
- * @return SEMTECH_LORAMAC_TX_SCHEDULED when the TX is scheduled in the mac
+ * @return SEMTECH_LORAMAC_DUTYCYCLE_RESTRICTED when the send is rejected because of dutycycle restriction
+ * @return SEMTECH_LORAMAC_TX_ERROR when an invalid parameter is given
  */
 uint8_t semtech_loramac_send(semtech_loramac_t *mac, uint8_t *data, uint8_t len);
 
@@ -172,6 +177,9 @@ uint8_t semtech_loramac_send(semtech_loramac_t *mac, uint8_t *data, uint8_t len)
  * class C device, a message can be received at any time. In this case, this
  * function can be used in a dedicated listener thread.
  *
+ * Be sure to call this function before the end of the RX windows otherwise it
+ * may block the calling thread.
+ *
  * @see semtech_loramac_send
  *
  * @param[in] mac          Pointer to the mac
diff --git a/tests/pkg_semtech-loramac/main.c b/tests/pkg_semtech-loramac/main.c
index 56d97d6a76d47dfe36b8442f3498a98580c641a2..52547aabc2d667edfa5d06facb71a7c21e744555 100644
--- a/tests/pkg_semtech-loramac/main.c
+++ b/tests/pkg_semtech-loramac/main.c
@@ -414,15 +414,23 @@ static int _cmd_loramac(int argc, char **argv)
         switch (semtech_loramac_send(&loramac,
                                      (uint8_t *)argv[2], strlen(argv[2]))) {
             case SEMTECH_LORAMAC_NOT_JOINED:
-                puts("Failed: not joined");
+                puts("Cannot send: not joined");
+                return 1;
+
+            case SEMTECH_LORAMAC_DUTYCYCLE_RESTRICTED:
+                puts("Cannot send: dutycycle restriction");
                 return 1;
 
             case SEMTECH_LORAMAC_BUSY:
-                puts("Failed: mac is busy");
+                puts("Cannot send: MAC is busy");
+                return 1;
+
+            case SEMTECH_LORAMAC_TX_ERROR:
+                puts("Cannot send: error");
                 return 1;
         }
 
-        /* clear the rx buffer of the mac */
+        /* wait for receive windows */
         switch (semtech_loramac_recv(&loramac)) {
             case SEMTECH_LORAMAC_DATA_RECEIVED:
                 loramac.rx_data.payload[loramac.rx_data.payload_len] = 0;