diff --git a/modules/sms_track/sms_track.module b/modules/sms_track/sms_track.module
index 9f9f38d..7e0933f 100644
--- a/modules/sms_track/sms_track.module
+++ b/modules/sms_track/sms_track.module
@@ -8,6 +8,7 @@
  */
 
 use Drupal\Core\Cache\CacheBackendInterface;
+use Drupal\sms\Message\SmsMessageResultInterface;
 use Drupal\sms\Plugin\SmsGatewayPluginInterface;
 use Drupal\sms\Message\SmsMessageInterface;
 use Drupal\views\Plugin\views\query\QueryPluginBase;
@@ -64,17 +65,21 @@ function sms_track_sms_send(SmsMessageInterface $sms, array $options, SmsGateway
  *   Additional options array including sender.
  * @param \Drupal\sms\Entity\SmsGatewayInterface $sms_gateway
  *   Gateway array for the active gateway.
- * @param bool|array $result
- *   The result from the gateway response handler.
+ * @param \Drupal\sms\Message\SmsMessageResultInterface $result
+ *   (optional) The SMS message result from the gateway.
  */
-function sms_track_sms_send_process($op, SmsMessageInterface $sms, array $options, SmsGatewayInterface $sms_gateway, $result) {
+function sms_track_sms_send_process($op, SmsMessageInterface $sms, array $options, SmsGatewayInterface $sms_gateway, SmsMessageResultInterface $result = NULL) {
   if ($op == 'post process') {
     // Archiving (outgoing == 0)
     $dir = 0;
     $options = (isset($options) && is_array($options))? $options : array();
     $options['gateway_id'] = $sms_gateway->id();
     $options['result']  = $result;
-    sms_track_archive_write($dir, implode(',', $sms->getRecipients()), $sms->getMessage(), $options);
+    $message = $sms->getMessage();
+    foreach ($result->getReports() as $report) {
+      $options['reference'] = $report->getMessageId();
+      sms_track_archive_write($dir, $report->getRecipient(), $message, $options);
+    }
   }
 }
 
@@ -90,12 +95,13 @@ function sms_track_sms_send_process($op, SmsMessageInterface $sms, array $option
  *   Additional options including receiver MSISDN.
  */
 function sms_track_sms_incoming($op, SmsMessageInterface $sms, array $options) {
-  $number = $sms->getRecipients()[0];
   $message = $sms->getMessage();
-  if ($op == 'pre process' && isset($number)) {
+  if ($op == 'pre process') {
     // Archiving (incoming == 1)
     $dir = 1;
-    sms_track_archive_write($dir, $number, $message, $options);
+    foreach ($sms->getRecipients() as $number) {
+      sms_track_archive_write($dir, $number, $message, $options);
+    }
   }
 }
 
@@ -105,19 +111,15 @@ function sms_track_sms_incoming($op, SmsMessageInterface $sms, array $options) {
  *
  * @param string $op
  *   Operation string.
- * @param string $number
- *   MSISDN (number) of recipient.
- * @param string $reference
- *   Reference code of the message.
- * @param string $status
- *   Message status code. See sms constants.
+ * @param \Drupal\sms\Message\SmsDeliveryReportInterface[] $reports
+ *   Delivery reports received from the SMS gateway.
  * @param array $options
  *   Additional options array.
  */
-function sms_track_sms_receipt($op, $number, $reference, $status, array $options) {
+function sms_track_sms_receipt($op, array $reports, array $options) {
   if ($op == 'pre process') {
     // Tracking.
-    sms_track_update_message($reference, $status);
+    sms_track_update_message($reports);
   }
 }
 
@@ -213,30 +215,33 @@ function sms_track_archive_write($dir, $number, $message, array $options = array
 }
 
 /**
- * Updates a message with a new status code.
+ * Updates message reports with the new delivery status codes.
  *
- * @param string $reference
- *   Message reference code.
- * @param int $status
- *   Message status code. See sms constants.
+ * @param \Drupal\sms\Message\SmsDeliveryReportInterface[] $reports
+ *   The SMS delivery reports.
  *
  * @todo Log record handling.
  */
-function sms_track_update_message($reference, $status) {
+function sms_track_update_message(array $reports) {
   $updated = REQUEST_TIME;
+  $affected_rows = 0;
 
-  \Drupal::logger('sms_track')->notice($reference . ' ' . $status . ' ' . $updated);
+  foreach ($reports as $number => $report) {
+    \Drupal::logger('sms_track')
+      ->notice($report->getMessageId() . ' ' . $report->getStatus() . ' ' . $updated);
 
-  $result = db_update('sms_track')
-    ->fields(array(
-      'status' => $status,
-      'updated' => $updated,
-    ))
-    ->condition('reference', $reference)
-    ->execute();
+    $result = db_update('sms_track')
+      ->fields(array(
+        'status' => $report->getStatus(),
+        'updated' => $updated,
+      ))
+      ->condition('reference', $report->getMessageId())
+      ->execute();
+    $affected_rows += $result->rowCount();
+  }
 
-  if ($result) {
-    \Drupal::logger('sms_track')->notice('Affected rows: ' . $result->rowCount());
+  if ($affected_rows) {
+    \Drupal::logger('sms_track')->notice('Affected rows: ' . $affected_rows);
   }
 }
 
diff --git a/sms.module b/sms.module
index 55f4cd3..973d084 100644
--- a/sms.module
+++ b/sms.module
@@ -193,8 +193,8 @@ function sms_incoming($number, $message, array $options = array()) {
  *
  * @deprecated use \Drupal\sms\Provider\SmsProviderInterface::receipt() instead.
  */
-function sms_receipt($number, $reference, $message_status = GatewayInterface::STATUS_UNKNOWN, $options = array()) {
-  \Drupal::service('sms_provider')->receipt($number, $reference, $message_status, $options);
+function sms_receipt(array $reports, array $options = []) {
+  \Drupal::service('sms_provider')->receipt($reports, $options);
 }
 
 /**
diff --git a/sms.routing.yml b/sms.routing.yml
index 6e629d1..40bd970 100644
--- a/sms.routing.yml
+++ b/sms.routing.yml
@@ -98,7 +98,7 @@ sms.bootstrap_admin:
     _permission: 'administer smsframework'
 
 sms.delivery_report:
-  path: '/sms/deliveryreport/{gateway_id}'
+  path: '/sms/deliveryreport/{gateway_name}'
   defaults:
     _controller: '\Drupal\sms\DeliveryReportController::acknowledgeDelivery'
   requirements:
diff --git a/src/DeliveryReportController.php b/src/DeliveryReportController.php
index 3e0d8b5..df85b7f 100644
--- a/src/DeliveryReportController.php
+++ b/src/DeliveryReportController.php
@@ -8,7 +8,9 @@
 namespace Drupal\sms;
 
 use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\sms\Entity\SmsGateway;
+use Drupal\sms\Provider\SmsProviderInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Drupal\sms\Plugin\SmsGatewayPluginManagerInterface;
 use Symfony\Component\HttpFoundation\RequestStack;
@@ -27,6 +29,13 @@ class DeliveryReportController implements ContainerInjectionInterface {
   protected $gatewayManager;
 
   /**
+   * The SMS Provider.
+   *
+   * @var \Drupal\sms\Provider\SmsProviderInterface
+   */
+  protected $smsProvider;
+
+  /**
    * The request stack.
    *
    * @var \Symfony\Component\HttpFoundation\RequestStack
@@ -34,6 +43,12 @@ class DeliveryReportController implements ContainerInjectionInterface {
   protected $requestStack;
 
   /**
+   * The module handler.
+   *
+   * @var \Drupal\Core\Extension\ModuleHandlerInterface
+   */
+
+  /**
    * Creates an new delivery report controller.
    *
    * @param \Drupal\sms\Plugin\SmsGatewayPluginManagerInterface $gateway_manager
@@ -41,26 +56,34 @@ class DeliveryReportController implements ContainerInjectionInterface {
    * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
    *   The request stack.
    */
-  public function __construct(SmsGatewayPluginManagerInterface $gateway_manager, RequestStack $request_stack) {
+  public function __construct(SmsGatewayPluginManagerInterface $gateway_manager, SmsProviderInterface $sms_provider, RequestStack $request_stack, ModuleHandlerInterface $module_handler) {
     $this->gatewayManager = $gateway_manager;
     $this->requestStack = $request_stack;
+    $this->smsProvider = $sms_provider;
+    $this->moduleHandler = $module_handler;
   }
 
   /**
    * Acknowledges delivery reports and passes them to the correct gateway.
    *
-   * @param string $gateway_id
-   *   The gateway id of the gateway that is to handle the delivery report.
+   * @param string $gateway
+   *   The ID of the SMS Gateway that is to handle the delivery report.
    *
    * @return \Symfony\Component\HttpFoundation\Response
    */
-  public function acknowledgeDelivery($gateway_id) {
+  public function acknowledgeDelivery($gateway_name) {
+    // The response that will be sent back to the server API. The gateway plugin
+    // can alter this response as needed.
+    $response = new Response('');
     /** @var \Drupal\sms\Entity\SmsGateway $sms_gateway */
-    $sms_gateway = SmsGateway::load($gateway_id);
-    $acknowledgement = $sms_gateway
+    $sms_gateway = SmsGateway::load($gateway_name);
+    $reports = $sms_gateway
       ->getPlugin()
-      ->deliveryReport($this->requestStack->getCurrentRequest());
-    return new Response($acknowledgement);
+      ->parseDeliveryReports($this->requestStack->getCurrentRequest(), $response);
+    // Invoke the delivery report and SMS receipt hooks.
+    $this->moduleHandler->invokeAll('sms_delivery_report', [$reports, $response]);
+    $this->smsProvider->receipt($reports, []);
+    return $response;
   }
 
   /**
@@ -69,7 +92,9 @@ class DeliveryReportController implements ContainerInjectionInterface {
   public static function create(ContainerInterface $container) {
     return new static(
       $container->get('plugin.manager.sms_gateway'),
-      $container->get('request_stack')
+      $container->get('sms_provider'),
+      $container->get('request_stack'),
+      $container->get('module_handler')
     );
   }
 
diff --git a/src/DeliveryReportException.php b/src/DeliveryReportException.php
new file mode 100644
index 0000000..b81d5c2
--- /dev/null
+++ b/src/DeliveryReportException.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Drupal\sms;
+
+/**
+ * Exception thrown for any SMS delivery rpeort exceptions.
+ */
+class DeliveryReportException extends SmsException {}
diff --git a/src/Entity/SmsGateway.php b/src/Entity/SmsGateway.php
index 54d8f0f..da2edc1 100644
--- a/src/Entity/SmsGateway.php
+++ b/src/Entity/SmsGateway.php
@@ -92,6 +92,8 @@ class SmsGateway extends ConfigEntityBase implements SmsGatewayInterface, Entity
       $this->pluginCollection = new SmsGatewayPluginCollection(
         \Drupal::service('plugin.manager.sms_gateway'),
         $this->plugin,
+        $this->id,
+        // Add the configuration name so the plugin is aware of it.
         $this->settings
       );
     }
diff --git a/src/Message/SmsDeliveryReport.php b/src/Message/SmsDeliveryReport.php
new file mode 100644
index 0000000..49d6d13
--- /dev/null
+++ b/src/Message/SmsDeliveryReport.php
@@ -0,0 +1,209 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\sms\Message\SmsDeliveryReport.
+ */
+
+namespace Drupal\sms\Message;
+
+/**
+ * A value object that holds the SMS delivery report.
+ */
+class SmsDeliveryReport implements SmsDeliveryReportInterface {
+
+  /**
+   * The unique identifier for the message assigned by the gateway.
+   *
+   * Usually message IDs are returned by the gateway to identify a message sent
+   * and should be unique for a particular combination of message and recipient.
+   *
+   * @var string
+   */
+  protected $messageId;
+
+  /**
+   * The UNIX timestamp when the message was sent.
+   *
+   * @var string
+   */
+  protected $timeSent;
+
+  /**
+   * The UNIX timestamp when the message was delivered.
+   *
+   * @var string
+   */
+  protected $timeDelivered;
+
+  /**
+   * The recipient of the message.
+   * 
+   * @var string
+   */
+  protected $recipient;
+
+  /**
+   * The error code sent from the gateway.
+   *
+   * @var string
+   */
+  protected $gatewayErrorCode;
+
+  /**
+   * The error message sent from the gateway.
+   *
+   * @var string
+   */
+  protected $gatewayErrorMessage;
+
+  /**
+   * The SMS delivery status sent from the gateway.
+   *
+   * @var string
+   */
+  protected $gatewayStatus;
+
+  /**
+   * The standardized error code.
+   *
+   * @var string
+   */
+  protected $errorCode;
+
+  /**
+   * The standardized error message.
+   *
+   * @var string
+   */
+  protected $errorMessage;
+
+  /**
+   * The standardized SMS delivery status.
+   *
+   * @var string
+   */
+  protected $status;
+
+  /**
+   * Default values.
+   *
+   * @var array
+   */
+  protected static $defaults = [
+    'message_id' => '',
+    'recipient' => '',
+    'status' => self::STATUS_SENT,
+    'error_code' => 0,
+    'error_message' => '',
+    'gateway_status' => 'SENT',
+    'gateway_error_code' => '',
+    'gateway_error_message' => '',
+    'time_sent' => REQUEST_TIME,
+    'time_delivered' => REQUEST_TIME,
+  ];
+
+  /**
+   * Creates a new instance of an SMS delivery report.
+   *
+   * @param array $data
+   *   The data to instantiate the delivery report with. It should have the 
+   *   following keys.
+   *   - message_id: the essage ID from the gateway (default is '')
+   *   - recipient: the recipient number (single number, default is '')
+   *   - status: the delivery status (default is
+   *     SmsDeliveryReportInterface::STATUS_SENT)
+   *   - gateway_status: the delivery status from the gateway (default is 'SENT')
+   *   - send_time: the time the message was sent (default is REQUEST_TIME)
+   *   - delivered_time: the time the message was delivered (default is
+   *     REQUEST_TIME)
+   */
+  public function __construct($data) {
+    $data += static::$defaults;
+    $this->messageId = $data['message_id'];
+    $this->recipient = $data['recipient'];
+    $this->timeDelivered = $data['time_delivered'];
+    $this->timeSent = $data['time_sent'];
+    $this->status = $data['status'];
+    $this->errorCode = $data['error_code'];
+    $this->errorMessage = $data['error_message'];
+    $this->gatewayStatus = $data['gateway_status'];
+    $this->gatewayErrorCode = $data['gateway_error_code'];
+    $this->gatewayErrorMessage = $data['gateway_error_message'];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getMessageId() {
+    return $this->messageId;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getRecipient() {
+    return $this->recipient;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getTimeDelivered() {
+    return $this->timeDelivered;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getTimeSent() {
+    return $this->timeSent;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getStatus() {
+    return $this->status;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getError() {
+    return $this->errorCode;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getErrorMessage() {
+    return $this->errorMessage;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getGatewayStatus() {
+    return $this->gatewayStatus;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getGatewayError() {
+    return $this->gatewayErrorCode;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getGatewayErrorMessage() {
+    return $this->gatewayErrorMessage;
+  }
+
+  public function getArray() {
+    return (array) $this;
+  }
+
+}
diff --git a/src/Message/SmsDeliveryReportInterface.php b/src/Message/SmsDeliveryReportInterface.php
new file mode 100644
index 0000000..2323af7
--- /dev/null
+++ b/src/Message/SmsDeliveryReportInterface.php
@@ -0,0 +1,224 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\sms\Message\SmsDeliveryReportInterface
+ */
+
+namespace Drupal\sms\Message;
+
+/**
+ * Contains information about an SMS message.
+ */
+interface SmsDeliveryReportInterface {
+
+  // Delivery report status codes
+  // 0=Unknown, 2xx=Positive, 3xx=Positive/Neutral (context-dependent), 4xx=Negative
+
+  /**
+   * Status UNKNOWN.
+   *
+   * A message would have this status to indicate unknown status.
+   */
+  const STATUS_UNKNOWN = 0;
+
+  /**
+   * Status SENT.
+   *
+   * A message with this status indicates it was successfully sent.
+   */
+  const STATUS_SENT = 200;
+
+  /**
+   * Status DELIVERED.
+   *
+   * A message with this status indicates it was successfully delivered.
+   */
+  const STATUS_DELIVERED = 202;
+
+  /**
+   * Status QUEUED.
+   *
+   * A message with this status indicates it was successfully queued for sending.
+   */
+  const STATUS_QUEUED = 300;
+
+  /**
+   * Status PENDING.
+   *
+   * A message with this status indicates it is pending delivery.
+   */
+  const STATUS_PENDING = 302;
+
+  /**
+   * Status ERROR.
+   *
+   * A message with this status indicates it could not be sent (routing reasons).
+   */
+  const STATUS_ERROR = 400;
+
+  /**
+   * Status NO_CREDIT.
+   *
+   * A message with this status indicates it was not sent due to low credit.
+   */
+  const STATUS_NO_CREDIT = 402;
+
+  /**
+   * Status NOT_SENT.
+   *
+   * A message with this status indicates it was not sent.
+   */
+  const STATUS_NOT_SENT = 404;
+
+  /**
+   * Status NOT_DELIVERED.
+   *
+   * A message with this status indicates it was sent but not delivered.
+   */
+  const STATUS_NOT_DELIVERED = 406;
+
+  /**
+   * Status EXPIRED.
+   *
+   * A message with this status indicates it was sent but expired in the SMSC.
+   */
+  const STATUS_EXPIRED = 408;
+
+  /**
+   * Status REJECTED.
+   *
+   * A message with this status indicates it was rejected by the network.
+   */
+  const STATUS_REJECTED = 410;
+
+  /**
+   * Status INVALID_RECIPIENT.
+   *
+   * A message with this status indicates the recipient number was invalid.
+   */
+  const STATUS_INVALID_RECIPIENT = 412;
+
+  /**
+   * Status INVALID_SENDER.
+   *
+   * A message with this status indicates the sender ID was invalid.
+   */
+  const STATUS_INVALID_SENDER = 414;
+
+  /**
+   * Status ERROR_ROUTING.
+   *
+   * A message with this status there was a routing error.
+   */
+  const STATUS_ERROR_ROUTING = 420;
+
+  /**
+   * Gets the message ID for the message.
+   *
+   * Usually message IDs are returned by the gateway to identify a message sent
+   * and should be unique for a particular combination of message and recipient.
+   *
+   * @return string
+   */
+  public function getMessageId();
+
+  /**
+   * Gets the recipient for which the message was intended.
+   *
+   * @return string
+   */
+  public function getRecipient();
+
+  /**
+   * Gets the normalized delivery status of the message.
+   *
+   * @return int
+   *   The status code which matches the codes used for HTTP.
+   */
+  public function getStatus();
+
+  /**
+   * Gets the original delivery status as known to the SMS gateway.
+   *
+   * @return string
+   */
+  public function getGatewayStatus();
+
+  /**
+   * Gets the time the message was sent.
+   *
+   * @return int
+   *   The UNIX timestamp when the message was sent.
+   */
+  public function getTimeSent();
+
+  /**
+   * Gets the time the message was delivered.
+   *
+   * @return int
+   *   The UNIX timestamp when the message was delivered.
+   */
+  public function getTimeDelivered();
+
+  /**
+   * Returns the delivery report as a keyed array.
+   *
+   * @return array
+   *   An array with the following keys:
+   *   - status: the actual delivery status of the message per the STATUS_*
+   *     constants in this class.
+   *   - message_id: The message id if the message was successfully sent to that
+   *       recipient. An empty string means the message was not sent.
+   *   - error_code: The error code number for a specific message.
+   *   - error_message: The description of the error message.
+   *   - gateway_status: The original delivery status from the SMS gateway.
+   *   - gateway_error_code: The original error code from the SMS gateway.
+   *   - gateway_error_message: The original error message from the SMS gateway.
+   * @return mixed
+   */
+  public function getArray();
+
+  /**
+   * Gets the standardized error code in the event there is an error.
+   *
+   * If there is no error, this method returns 0.
+   *
+   * @return int
+   *
+   * @see \Drupal\sms\Message\SmsMessageInterface for the constants.
+   */
+  public function getError();
+
+  /**
+   * Gets the standardized error message in the event there is an error.
+   *
+   * If there is no error, this method returns an empty string.
+   *
+   * @return string
+   *
+   * @see \Drupal\sms\Message\SmsMessageInterface for the constants.
+   */
+  public function getErrorMessage();
+
+  /**
+   * Gets the gateway error code in the event there is an error.
+   *
+   * If there is no error, this method returns an empty string. These values are
+   * gateway dependent and would likely differ across different gateways.
+   *
+   * @return string
+   */
+  public function getGatewayError();
+
+  /**
+   * Gets the gateway error message in the event there is an error.
+   *
+   * If there is no error, this method returns and empty string. These strings
+   * are gateway dependent and would likely differ across different gateways.
+   *
+   * @return string
+   */
+  public function getGatewayErrorMessage();
+
+}
diff --git a/src/Message/SmsMessageResult.php b/src/Message/SmsMessageResult.php
index ae8a968..247f8de 100644
--- a/src/Message/SmsMessageResult.php
+++ b/src/Message/SmsMessageResult.php
@@ -41,11 +41,11 @@ class SmsMessageResult implements SmsMessageResultInterface {
   public $creditBalance;
 
   /**
-   * The message reports keyed by recipient number.
+   * The message delivery reports keyed by recipient number.
    *
-   * @var array
+   * @var \Drupal\sms\Message\SmsDeliveryReportInterface[]
    */
-  public $report;
+  public $reports;
 
   /**
    * Create a new message result based on data supplied in the array.
@@ -59,7 +59,7 @@ class SmsMessageResult implements SmsMessageResultInterface {
     $this->creditBalance = $data['credit_balance'];
     $this->creditsUsed = $data['credits_used'];
     $this->errorMessage = $data['error_message'];
-    $this->report = $data['report'];
+    $this->reports = $data['reports'];
   }
 
   /**
@@ -72,8 +72,8 @@ class SmsMessageResult implements SmsMessageResultInterface {
   /**
    * {@inheritdoc}
    */
-  public function getReport() {
-    return $this->report;
+  public function getReports() {
+    return $this->reports;
   }
 
   /**
@@ -99,7 +99,7 @@ class SmsMessageResult implements SmsMessageResultInterface {
       'error_message' => $this->errorMessage,
       'credits_used' => $this->creditsUsed,
       'credit_balance' => $this->creditBalance,
-      'report' => $this->report,
+      'reports' => $this->reports,
     );
   }
 
@@ -113,9 +113,9 @@ class SmsMessageResult implements SmsMessageResultInterface {
   /**
    * {@inheritdoc}
    */
-  public function getReportFor($recipient) {
-    if (isset($this->report[$recipient])) {
-      return $this->report[$recipient];
+  public function getReport($recipient) {
+    if (isset($this->reports[$recipient])) {
+      return $this->reports[$recipient];
     }
     else {
       return null;
@@ -131,7 +131,7 @@ class SmsMessageResult implements SmsMessageResultInterface {
       'error_message' => '',
       'credits_used' => 0,
       'credit_balance' => 0,
-      'report' => array(),
+      'reports' => [],
     );
   }
 
diff --git a/src/Message/SmsMessageResultInterface.php b/src/Message/SmsMessageResultInterface.php
index 1f89191..6a510e2 100644
--- a/src/Message/SmsMessageResultInterface.php
+++ b/src/Message/SmsMessageResultInterface.php
@@ -32,18 +32,11 @@ interface SmsMessageResultInterface {
   /**
    * Gets the delivery report for all recipients.
    *
-   * @return array
-   *   The report for all recipients. This report is an array keyed by the
-   *   recipients' numbers. The value is also an array with the following keys:
-   *   - status: true if message was successfully sent, false otherwise.
-   *   - message_id: The message id if the message was successfully sent to that
-   *       recipient. Zero means message was not sent to that recipient.
-   *   - error_code: The error code number for a specific message.
-   *   - error_message: The description of the error message.
-   *   - gateway_error_code: The original error code from the SMS gateway.
-   *   - gateway_error_message: The original error message from the SMS gateway.
+   * @return \Drupal\sms\Message\SmsDeliveryReportInterface[]
+   *   An array of delivery reports for all recipients keyed by the recipients'
+   *   number.
    */
-  public function getReport();
+  public function getReports();
 
   /**
    * Gets the credit balance after the SMS was sent.
@@ -70,14 +63,16 @@ interface SmsMessageResultInterface {
   public function toArray();
 
   /**
-   * Gets the specific report for a particular recipient.
+   * Gets the delivery report for a particular recipient.
    *
    * @param string $recipient
    *   The number of the recipient for which the report is to be retrieved.
-   * @return array
-   *   An array containing the message report
-   *   @link see SmsMessageResultInterface::getReport() @endlink
+   *
+   * @return \Drupal\sms\Message\SmsDeliveryReportInterface
+   *   A delivery report object.
+   *
+   * @see SmsMessageResultInterface::getReports()
    */
-  public function getReportFor($recipient);
+  public function getReport($recipient);
 
 }
diff --git a/src/Plugin/SmsGateway/LogGateway.php b/src/Plugin/SmsGateway/LogGateway.php
index 90a45ce..a76e97c 100644
--- a/src/Plugin/SmsGateway/LogGateway.php
+++ b/src/Plugin/SmsGateway/LogGateway.php
@@ -7,6 +7,8 @@
 
 namespace Drupal\sms\Plugin\SmsGateway;
 
+use Drupal\sms\Message\SmsDeliveryReport;
+use Drupal\sms\Message\SmsDeliveryReportInterface;
 use Drupal\sms\Plugin\SmsGatewayPluginBase;
 use Drupal\sms\Message\SmsMessageInterface;
 use Drupal\sms\Message\SmsMessageResult;
@@ -27,7 +29,14 @@ class LogGateway extends SmsGatewayPluginBase {
     $this->logger()->notice('SMS message sent to %number with the text: @message',
       ['%number' => implode(', ', $sms->getRecipients()), '@message' => $sms->getMessage()]);
     $return = ['status' => TRUE];
-    $return['report'] = array_fill_keys($sms->getRecipients(), ['status' => TRUE, 'message_id' => rand(1, 999999)]);
+    $return['reports'] = [];
+    foreach ($sms->getRecipients() as $number) {
+      $return['reports'][$number] = new SmsDeliveryReport([
+        'status' => SmsDeliveryReportInterface::STATUS_DELIVERED,
+        'recipient' => $number,
+        'gateway_status' => 'DELIVERED',
+      ]);
+    }
     return new SmsMessageResult($return);
   }
 
diff --git a/src/Plugin/SmsGatewayPluginBase.php b/src/Plugin/SmsGatewayPluginBase.php
index ae24e83..921b984 100644
--- a/src/Plugin/SmsGatewayPluginBase.php
+++ b/src/Plugin/SmsGatewayPluginBase.php
@@ -9,7 +9,9 @@ namespace Drupal\sms\Plugin;
 
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Plugin\PluginBase;
+use Drupal\Core\Url;
 use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
 
 /**
  * Base class for sms gateway plugins.
@@ -24,6 +26,13 @@ abstract class SmsGatewayPluginBase extends PluginBase implements SmsGatewayPlug
   protected $logger;
 
   /**
+   * The machine name of the gateway config entity owning this plugin instance.
+   *
+   * @var string
+   */
+  protected $gatewayName;
+
+  /**
    * Construct a new SmsGateway plugin
    *
    * @param array $configuration
@@ -41,6 +50,13 @@ abstract class SmsGatewayPluginBase extends PluginBase implements SmsGatewayPlug
   /**
    * {@inheritdoc}
    */
+  public function setGatewayName($machine_name) {
+    $this->gatewayName = $machine_name;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function getConfiguration() {
     return $this->configuration;
   }
@@ -111,8 +127,15 @@ abstract class SmsGatewayPluginBase extends PluginBase implements SmsGatewayPlug
   /**
    * {@inheritdoc}
    */
-  public function deliveryReport(Request $request) {
-    return;
+  public function parseDeliveryReports(Request $request, Response $response) {
+    return [];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function pullDeliveryReports(array $message_ids = NULL) {
+    return [];
   }
 
   /**
@@ -122,6 +145,15 @@ abstract class SmsGatewayPluginBase extends PluginBase implements SmsGatewayPlug
     return [];
   }
 
+  public function getDeliveryReportPath($absolute = TRUE) {
+    if (isset($this->gatewayName)) {
+      return Url::fromRoute('sms.delivery_report', ['gateway_name' => $this->gatewayName], ['absolute' => $absolute])->toString();
+    }
+    else {
+      return '';
+    }
+  }
+
   /**
    * Gets the Psr logger for this gateway.
    */
diff --git a/src/Plugin/SmsGatewayPluginCollection.php b/src/Plugin/SmsGatewayPluginCollection.php
index 4d3d6c0..0de4ef4 100644
--- a/src/Plugin/SmsGatewayPluginCollection.php
+++ b/src/Plugin/SmsGatewayPluginCollection.php
@@ -7,10 +7,49 @@
 
 namespace Drupal\sms\Plugin;
 
+use Drupal\Component\Plugin\PluginManagerInterface;
 use Drupal\Core\Plugin\DefaultSingleLazyPluginCollection;
 
 /**
- * Provides a container for lazily loading SMS Gateway plugins.
+ * Provides a container for lazily loading SMS Gateway plugin instances.
  */
 class SmsGatewayPluginCollection extends DefaultSingleLazyPluginCollection {
+
+  /**
+   * The machine name of the gateway config entity using this plugin collection.
+   *
+   * @var string
+   */
+  protected $gatewayName;
+
+  /**
+   * Constructs a new SearchPluginCollection.
+   *
+   * @param \Drupal\Component\Plugin\PluginManagerInterface $manager
+   *   The manager to be used for instantiating plugins.
+   * @param string $instance_id
+   *   The ID of the plugin instance.
+   * @param string $gateway_name
+   *   The machine name of the gateway config entity.
+   * @param array $configuration
+   *   An array of configuration.
+   */
+  public function __construct(PluginManagerInterface $manager, $instance_id, $gateway_name, array $configuration) {
+    parent::__construct($manager, $instance_id, $configuration);
+
+    $this->gatewayName = $gateway_name;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function initializePlugin($instance_id) {
+    parent::initializePlugin($instance_id);
+
+    $plugin_instance = $this->pluginInstances[$instance_id];
+    if ($plugin_instance instanceof SmsGatewayPluginInterface) {
+      $plugin_instance->setGatewayName($this->gatewayName);
+    }
+  }
+
 }
diff --git a/src/Plugin/SmsGatewayPluginInterface.php b/src/Plugin/SmsGatewayPluginInterface.php
index 5ec09fd..ee41d86 100644
--- a/src/Plugin/SmsGatewayPluginInterface.php
+++ b/src/Plugin/SmsGatewayPluginInterface.php
@@ -13,6 +13,7 @@ use Drupal\Component\Plugin\PluginInspectionInterface;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\sms\Message\SmsMessageInterface;
 use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
 
 /**
  * Default implementation of sms gateway plugin
@@ -112,7 +113,7 @@ interface SmsGatewayPluginInterface extends ConfigurablePluginInterface, PluginF
   const STATUS_ERR_OTHER = 500;
 
   /**
-   * Sends an sms and invokes the corresponding sms receipt method.
+   * Sends an SMS and invokes the corresponding sms receipt method.
    *
    * @param \Drupal\sms\Message\SmsMessageInterface $sms
    *   The sms to be sent.
@@ -132,12 +133,29 @@ interface SmsGatewayPluginInterface extends ConfigurablePluginInterface, PluginF
   public function balance();
 
   /**
-   * Handles delivery reports and invokes the corresponding sms_receipt method.
+   * Parses incoming delivery reports and returns the DeliveryReport objects.
    *
-   * @param \Symfony\Component\HttpFoundation\Request
+   * @param \Symfony\Component\HttpFoundation\Request $request
    *   Request object containing the delivery report in raw format.
+   * @param \Symfony\Component\HttpFoundation\Response $response
+   *   A HTTP response that will be sent back to the SMSC. The plugin can alter
+   *   the content of the response by @code$response->setContent()@endcode.
+   *
+   * @return \Drupal\sms\Message\SmsDeliveryReportInterface[]
+   *   An array of the delivery reports which have been received.
+   */
+  public function parseDeliveryReports(Request $request, Response $response);
+
+  /**
+   * Pulls delivery reports from the SMS gateway server.
+   *
+   * @param string[]|null $message_ids
+   *   The list of specific message_ids to poll. NULL to pull all reports.
+   *
+   * @return \Drupal\sms\Message\SmsDeliveryReportInterface[]
+   *   An array of the delivery reports which have been pulled.
    */
-  public function deliveryReport(Request $request);
+  public function pullDeliveryReports(array $message_ids = NULL);
 
   /**
    * Gets the last error message from the gateway.
@@ -174,4 +192,24 @@ interface SmsGatewayPluginInterface extends ConfigurablePluginInterface, PluginF
    */
   public function validateNumbers(array $numbers, array $options = []);
 
+  /**
+   * Gets the path for the delivery reports for this gateway instance.
+   *
+   * @param bool $absolute
+   *   Whether to return a relative or absolute path.
+   *
+   * @return string
+   *   The absolute delivery report url if $absolute is true (default); returns
+   *   the domain-relative path if $absolute is false.
+   */
+  public function getDeliveryReportPath($absolute = TRUE);
+
+  /**
+   * Sets the machine name of the config entity that owns this plugin instance.
+   *
+   * @param string $machine_name
+   *   The machine name of the config entity.
+   */
+  public function setGatewayName($machine_name);
+
 }
diff --git a/src/Provider/DefaultSmsProvider.php b/src/Provider/DefaultSmsProvider.php
index 2656a96..20d8b02 100644
--- a/src/Provider/DefaultSmsProvider.php
+++ b/src/Provider/DefaultSmsProvider.php
@@ -85,8 +85,7 @@ class DefaultSmsProvider implements SmsProviderInterface {
    *   The message result from the gateway.
    */
   protected function process(SmsMessageInterface $sms, array $options, SmsGatewayInterface $sms_gateway) {
-    return $sms_gateway->getPlugin()
-      ->send($sms, $options);
+    return $sms_gateway->getPlugin()->send($sms, $options);
   }
 
   /**
@@ -140,12 +139,12 @@ class DefaultSmsProvider implements SmsProviderInterface {
   /**
    * {@inheritdoc}
    */
-  public function receipt($number, $reference, $message_status = SmsGatewayPluginInterface::STATUS_UNKNOWN, array $options = array()) {
-    // @todo Implement rules event integration here for incoming SMS.
+  public function receipt(array $reports, array $options = []) {
+    // @todo Implement rules event integration here delivery report receipts.
     // Execute three phases.
-    $this->moduleHandler->invokeAll('sms_receipt', array('pre process', $number, $reference, $message_status, $options));
-    $this->moduleHandler->invokeAll('sms_receipt', array('process', $number, $reference, $message_status, $options));
-    $this->moduleHandler->invokeAll('sms_receipt', array('post process', $number, $reference, $message_status, $options));
+    $this->moduleHandler->invokeAll('sms_receipt', array('pre process', $reports, $options));
+    $this->moduleHandler->invokeAll('sms_receipt', array('process', $reports, $options));
+    $this->moduleHandler->invokeAll('sms_receipt', array('post process', $reports, $options));
   }
 
   /**
diff --git a/src/Provider/SmsProviderInterface.php b/src/Provider/SmsProviderInterface.php
index a8e24a6..7deb828 100644
--- a/src/Provider/SmsProviderInterface.php
+++ b/src/Provider/SmsProviderInterface.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\sms\Provider;
 
+use Drupal\sms\Message\SmsDeliveryReportInterface;
 use Drupal\sms\Plugin\SmsGatewayPluginInterface;
 use Drupal\sms\Message\SmsMessageInterface;
 
@@ -58,17 +59,11 @@ interface SmsProviderInterface {
    * The original gateway code and string will often be provided in the $options
    * array as 'gateway_message_status' and 'gateway_message_status_text'.
    *
-   * @param string $number
-   *   The sender's mobile number.
-   * @param string $reference
-   *   Unique message reference code, as provided when message is sent.
-   * @param int $message_status
-   *   (optional) An SMS Framework message status code, according to the defined
-   *   constants.
-   *   Defaults to \Drupal\sms\Plugin\SmsGatewayPluginInterface::STATUS_UNKNOWN.
+   * @param \Drupal\sms\Message\SmsDeliveryReportInterface[] $reports
+   *   An array of the delivery reports that have been received.
    * @param array $options
    *   (optional) Extended options passed by the receipt receiver.
    */
-  public function receipt($number, $reference, $message_status = SmsGatewayPluginInterface::STATUS_UNKNOWN, array $options = array());
+  public function receipt(array $reports, array $options = []);
 
 }
diff --git a/src/Tests/SmsFrameworkTestTrait.php b/src/Tests/SmsFrameworkTestTrait.php
index 099cf5c..43981de 100644
--- a/src/Tests/SmsFrameworkTestTrait.php
+++ b/src/Tests/SmsFrameworkTestTrait.php
@@ -11,6 +11,7 @@ use Drupal\Core\Entity\EntityInterface;
 use Drupal\sms\Entity\PhoneNumberSettingsInterface;
 use Drupal\sms\Entity\SmsGateway;
 use Drupal\Component\Utility\Unicode;
+use Drupal\sms\Message\SmsMessage;
 
 /**
  * Shared SMS Framework helpers for kernel and web tests.
@@ -38,7 +39,7 @@ trait SmsFrameworkTestTrait {
    *
    * @return \Drupal\sms\Message\SmsMessageInterface[]
    */
-  function getTestMessages() {
+  protected function getTestMessages() {
     return \Drupal::state()->get('sms_test_gateway.memory.send', []);
   }
 
@@ -48,7 +49,7 @@ trait SmsFrameworkTestTrait {
    * @return \Drupal\sms\Message\SmsMessageInterface|NULL
    *   The last SMS message, or FALSE if no messages have been sent.
    */
-  public function getLastTestMessage() {
+  protected function getLastTestMessage() {
     $sms_messages = \Drupal::state()->get('sms_test_gateway.memory.send', []);
     return end($sms_messages);
   }
@@ -56,11 +57,52 @@ trait SmsFrameworkTestTrait {
   /**
    * Resets SMS messages stored in memory by 'Memory' gateway.
    */
-  public function resetTestMessages() {
+  protected function resetTestMessages() {
     \Drupal::state()->set('sms_test_gateway.memory.send', []);
   }
 
   /**
+   * Gets all SMS reports for messages sent to 'Memory' gateway.
+   *
+   * @return \Drupal\sms\Message\SmsDeliveryReportInterface[]
+   */
+  protected function getTestMessageReports() {
+    return \Drupal::state()->get('sms_test_gateway.memory.report', []);
+  }
+
+  /**
+   * Gets the last SMS report for messages sent to 'Memory' gateway.
+   *
+   * @return \Drupal\sms\Message\SmsDeliveryReportInterface|false
+   *   The last SMS message, or FALSE if no messages have been sent.
+   */
+  protected function getLastTestMessageReport() {
+    $reports = \Drupal::state()->get('sms_test_gateway.memory.report', []);
+    return end($reports);
+  }
+
+  /**
+   * Gets an SMS report for message with message ID.
+   *
+   * @param string $message_id
+   *   The message ID.
+   *
+   * @return \Drupal\sms\Message\SmsDeliveryReportInterface
+   *   The last SMS message, or FALSE if no messages have been sent.
+   */
+  protected function getTestMessageReport($message_id) {
+    $reports = \Drupal::state()->get('sms_test_gateway.memory.report', []);
+    return $reports[$message_id];
+  }
+
+  /**
+   * Resets the SMS reports stored in memory by 'Memory' gateway.
+   */
+  protected function resetTestMessageReports() {
+    \Drupal::state()->set('sms_test_gateway.memory.report', []);
+  }
+
+  /**
    * Creates an entity, and optionally adds phone numbers.
    *
    * @param \Drupal\sms\Entity\PhoneNumberSettingsInterface $phone_number_settings
@@ -127,4 +169,29 @@ trait SmsFrameworkTestTrait {
     return reset($verifications);
   }
 
+  /**
+   * Generates a random SMS message by the specified user.
+   *
+   * @param int $uid
+   *   (optional) The user ID to generate the message as. Defaults to 1.
+   *
+   * @return \Drupal\sms\Message\SmsMessageInterface
+   */
+  protected function randomSmsMessage($uid = 1) {
+    return new SmsMessage($this->randomString(), $this->randomPhoneNumbers(), $this->randomString(), [], $uid);
+  }
+
+  /**
+   * Generates random phone numbers for tests.
+   *
+   * @return array
+   */
+  protected function randomPhoneNumbers() {
+    $numbers =[];
+    for ($i = 0; $i < rand(0,20); $i++) {
+      $numbers[] = '234' . rand(1000000, 9999999);
+    }
+    return $numbers;
+  }
+
 }
diff --git a/src/Tests/SmsFrameworkWebTest.php b/src/Tests/SmsFrameworkWebTest.php
index c485538..a60aeac 100644
--- a/src/Tests/SmsFrameworkWebTest.php
+++ b/src/Tests/SmsFrameworkWebTest.php
@@ -8,6 +8,9 @@
 namespace Drupal\sms\Tests;
 
 use Drupal\sms\Entity\SmsGateway;
+use Drupal\sms\Message\SmsDeliveryReportInterface;
+use Drupal\sms\Message\SmsMessageResultInterface;
+use Symfony\Component\HttpFoundation\Request;
 
 /**
  * Integration tests for the SMS Framework.
@@ -121,8 +124,55 @@ class SmsFrameworkWebTest extends SmsFrameworkWebTestBase {
     $result = sms_send($number, $message, $options);
     $this->assertTrue($result, 'Message successfully sent.');
 
-    $this->assertTrue(count($this->getTestMessages()) > $pre_count, 'Message sent to the correct gateway.'
-    );
+    $this->assertTrue(count($this->getTestMessages()) > $pre_count, 'Message sent to the correct gateway.');
+  }
+
+  /**
+   * Tests delivery reports integration.
+   */
+  public function testDeliveryReports() {
+    $user = $this->drupalCreateUser();
+    $this->drupalLogin($user);
+    $sms_message = $this->randomSmsMessage($user->id());
+
+    $result = $this->defaultSmsProvider->send($sms_message, ['gateway' => $this->testGateway->id()]);
+
+    $this->assertTrue($result instanceof SmsMessageResultInterface);
+    $this->assertEqual(count($sms_message->getRecipients()), count($result->getReports()));
+    $reports = $result->getReports();
+    $first_report = reset($reports);
+    $this->assertTrue($first_report instanceof SmsDeliveryReportInterface);
+    $this->assertEqual($first_report->getStatus(), SmsDeliveryReportInterface::STATUS_SENT);
+
+    // Get the delivery reports url and simulate push delivery report.
+    $url = $this->testGateway->getPlugin()->getDeliveryReportPath();
+    $delivered_time = REQUEST_TIME;
+    $delivery_report =<<<EOF
+{
+   "reports":[
+      {
+         "message_id":"{$first_report->getMessageId()}",
+         "recipient":"{$first_report->getRecipient()}",
+         "time_sent":{$first_report->getTimeSent()},
+         "time_delivered": $delivered_time,
+         "status": "800",
+         "gateway_status": "THIS_HAS_BEEN_DELIVERED",
+         "gateway_status_code": "202",
+         "gateway_status_description": "Delivered to Handset"
+      }
+   ]
+}
+EOF;
+    $this->drupalPost($url, 'application/json', ['delivery_report' => $delivery_report]);
+    $this->assertText('custom response content');
+    \Drupal::state()->resetCache();
+
+    // Get the stored report and verify that it was properly parsed.
+    $second_report = $this->getTestMessageReport($first_report->getMessageId());
+    $this->assertEqual($first_report->getMessageId(), $second_report->getMessageId());
+    $this->assertEqual("800", $second_report->getStatus());
+    $this->assertEqual("THIS_HAS_BEEN_DELIVERED", $second_report->getGatewayStatus());
+    $this->assertEqual($delivered_time, $second_report->getTimeDelivered());
   }
 
   /**
diff --git a/tests/modules/sms_test_gateway/src/Plugin/SmsGateway/Memory.php b/tests/modules/sms_test_gateway/src/Plugin/SmsGateway/Memory.php
index fd74a3f..95123d9 100644
--- a/tests/modules/sms_test_gateway/src/Plugin/SmsGateway/Memory.php
+++ b/tests/modules/sms_test_gateway/src/Plugin/SmsGateway/Memory.php
@@ -7,10 +7,16 @@
 
 namespace Drupal\sms_test_gateway\Plugin\SmsGateway;
 
+use Drupal\Component\Serialization\Json;
+use Drupal\Component\Utility\Random;
+use Drupal\sms\Message\SmsDeliveryReport;
+use Drupal\sms\Message\SmsDeliveryReportInterface;
 use Drupal\sms\Plugin\SmsGatewayPluginBase;
 use Drupal\sms\Message\SmsMessageInterface;
 use Drupal\sms\Message\SmsMessageResult;
 use Drupal\Core\Form\FormStateInterface;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
 
 /**
  * Defines a gateway storing transmitted SMS in memory.
@@ -62,7 +68,75 @@ class Memory extends SmsGatewayPluginBase {
     $state = \Drupal::state()->get('sms_test_gateway.memory.send', []);
     $state[] = $sms_message;
     \Drupal::state()->set('sms_test_gateway.memory.send', $state);
-    return new SmsMessageResult(['status' => TRUE]);
+
+    $reports = \Drupal::state()->get('sms_test_gateway.memory.report', []);
+    $latest_reports = $this->randomDeliveryReports($sms_message);
+    // Update the delivery reports.
+    $reports = $latest_reports + $reports;
+    \Drupal::state()->set('sms_test_gateway.memory.report', $reports);
+    return new SmsMessageResult([
+      'status' => TRUE,
+      'reports' => $latest_reports,
+    ]);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function parseDeliveryReports(Request $request, Response $response) {
+    $data = Json::decode($request->request->get('delivery_report'));
+    $latest_reports = [];
+    foreach ($data['reports'] as $report) {
+      $latest_reports[$report['message_id']] = new SmsDeliveryReport([
+        'recipient' => $report['recipient'],
+        'message_id' => $report['message_id'],
+        'time_sent' => $report['time_sent'],
+        'time_delivered' => $report['time_delivered'],
+        'status' => $report['status'],
+        'gateway' => $this->gatewayName,
+        'gateway_status' => $report['gateway_status'],
+        'gateway_status_code' => $report['gateway_status_code'],
+        'gateway_status_description' => $report['gateway_status_description'],
+      ]);
+    }
+
+    // Update the latest delivery reports in \Drupal::state().
+    $reports = \Drupal::state()->get('sms_test_gateway.memory.report', []);
+    $reports = $latest_reports + $reports;
+    \Drupal::state()->set('sms_test_gateway.memory.report', $reports);
+
+    // Set the response.
+    $response->setContent('custom response content');
+    return $latest_reports;
+  }
+
+  /**
+   * Generates random delivery reports for each of the recipients of a message.
+   *
+   * @param \Drupal\sms\Message\SmsMessageInterface $sms_message
+   *   The SMS message
+   *
+   * @return \Drupal\sms\Message\SmsDeliveryReportInterface[]
+   *   An array of delivery reports.
+   */
+  protected function randomDeliveryReports(SmsMessageInterface $sms_message) {
+    $random = new Random();
+    $reports = [];
+    foreach ($sms_message->getRecipients() as $number) {
+      $message_id = $random->name(16);
+      $reports[$message_id] = new SmsDeliveryReport([
+        'recipient' => $number,
+        'message_id' => $message_id,
+        'time_sent' => time(),
+        'time_delivered' => time() + rand(0, 10),
+        'status' => SmsDeliveryReportInterface::STATUS_SENT,
+        'gateway' => $this->gatewayName,
+        'gateway_status' => 'SENT',
+        'gateway_status_code' => '200',
+        'gateway_status_description' => 'Sent to memory gateway',
+      ]);
+    }
+    return $reports;
   }
 
   public function validateNumber($numbers) {
