diff --git a/.coveragerc b/.coveragerc
index ff5bb876b8a3e55fe16441d8766d74499760adc2..d1125c591469996ddb2ac77d8fed5c30de32bbe5 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -693,6 +693,7 @@ omit =
     homeassistant/components/route53.py
     homeassistant/components/scene/hunterdouglas_powerview.py
     homeassistant/components/scene/lifx_cloud.py
+    homeassistant/components/sensor/aftership.py
     homeassistant/components/sensor/airvisual.py
     homeassistant/components/sensor/alpha_vantage.py
     homeassistant/components/sensor/ambient_station.py
diff --git a/homeassistant/components/sensor/aftership.py b/homeassistant/components/sensor/aftership.py
new file mode 100644
index 0000000000000000000000000000000000000000..eb5188a95cb869c39508e4edfa8d11c7fc33ac81
--- /dev/null
+++ b/homeassistant/components/sensor/aftership.py
@@ -0,0 +1,128 @@
+"""
+Support for non-delivered packages recorded in AfterShip.
+
+For more details about this platform, please refer to the documentation at
+https://www.home-assistant.io/components/sensor.aftership/
+"""
+from datetime import timedelta
+import logging
+
+import voluptuous as vol
+
+from homeassistant.components.sensor import PLATFORM_SCHEMA
+from homeassistant.const import ATTR_ATTRIBUTION, CONF_API_KEY, CONF_NAME
+from homeassistant.helpers.aiohttp_client import async_get_clientsession
+import homeassistant.helpers.config_validation as cv
+from homeassistant.helpers.entity import Entity
+from homeassistant.util import Throttle
+
+REQUIREMENTS = ['pyaftership==0.1.2']
+
+_LOGGER = logging.getLogger(__name__)
+
+ATTRIBUTION = 'Information provided by AfterShip'
+
+CONF_SLUG = 'slug'
+CONF_TITLE = 'title'
+CONF_TRACKING_NUMBER = 'tracking_number'
+
+DEFAULT_NAME = 'aftership'
+
+ICON = 'mdi:package-variant-closed'
+
+MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=30)
+
+PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
+    vol.Required(CONF_API_KEY): cv.string,
+    vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
+})
+
+
+async def async_setup_platform(
+        hass, config, async_add_entities, discovery_info=None):
+    """Set up the AfterShip sensor platform."""
+    from pyaftership.tracker import Tracking
+
+    apikey = config[CONF_API_KEY]
+    name = config[CONF_NAME]
+
+    session = async_get_clientsession(hass)
+    aftership = Tracking(hass.loop, session, apikey)
+
+    await aftership.get_trackings()
+
+    if not aftership.meta or aftership.meta['code'] != 200:
+        _LOGGER.error("No tracking data found. Check API key is correct: %s",
+                      aftership.meta)
+        return
+
+    async_add_entities([AfterShipSensor(aftership, name)], True)
+
+
+class AfterShipSensor(Entity):
+    """Representation of a AfterShip sensor."""
+
+    def __init__(self, aftership, name):
+        """Initialize the sensor."""
+        self._attributes = {}
+        self._name = name
+        self._state = None
+        self.aftership = aftership
+
+    @property
+    def name(self):
+        """Return the name of the sensor."""
+        return self._name
+
+    @property
+    def state(self):
+        """Return the state of the sensor."""
+        return self._state
+
+    @property
+    def unit_of_measurement(self):
+        """Return the unit of measurement of this entity, if any."""
+        return 'packages'
+
+    @property
+    def device_state_attributes(self):
+        """Return attributes for the sensor."""
+        return self._attributes
+
+    @property
+    def icon(self):
+        """Icon to use in the frontend."""
+        return ICON
+
+    @Throttle(MIN_TIME_BETWEEN_UPDATES)
+    async def async_update(self):
+        """Get the latest data from the AfterShip API."""
+        await self.aftership.get_trackings()
+
+        if not self.aftership.meta:
+            _LOGGER.error("Unknown errors when querying")
+            return
+        if self.aftership.meta['code'] != 200:
+            _LOGGER.error(
+                "Errors when querying AfterShip. %s", str(self.aftership.meta))
+            return
+
+        status_to_ignore = {'delivered'}
+        status_counts = {}
+        not_delivered_count = 0
+
+        for tracking in self.aftership.trackings['trackings']:
+            status = tracking['tag'].lower()
+            name = tracking['tracking_number']
+            status_counts[status] = status_counts.get(status, 0)+1
+            if status not in status_to_ignore:
+                not_delivered_count += 1
+            else:
+                _LOGGER.debug("Ignoring %s as it has status: %s", name, status)
+
+        self._attributes = {
+            ATTR_ATTRIBUTION: ATTRIBUTION,
+            **status_counts
+        }
+
+        self._state = not_delivered_count
diff --git a/requirements_all.txt b/requirements_all.txt
index ec85e22da17dccfafb28dde31566d6b893314d61..412b274b08f5023c161752a50c39622725e707db 100644
--- a/requirements_all.txt
+++ b/requirements_all.txt
@@ -881,6 +881,9 @@ pyW800rf32==0.1
 # homeassistant.components.ads
 pyads==2.2.6
 
+# homeassistant.components.sensor.aftership
+pyaftership==0.1.2
+
 # homeassistant.components.sensor.airvisual
 pyairvisual==2.0.1