Repository: Stranger6667/postmarker
Pull request #44 (2016-10-09 12:16:53)

Status API

codecov-io: ## [Current coverage](https://codecov.io/gh/Stranger6667/postmarker/pull/44?src=pr) is 100% (diff: 100%)
> Merging [#44](https://codecov.io/gh/Stranger6667/postmarker/pull/44?src=pr) into [master](https://codecov.io/gh/Stranger6667/postmarker/branch/master?src=pr) will not change coverage

```diff
@@           master   #44   diff @@
===================================
  Files          10    11     +1   
  Lines         280   318    +38   
  Methods         0     0          
  Messages        0     0          
  Branches       33    35     +2   
===================================
+ Hits          280   318    +38   
  Misses          0     0          
  Partials        0     0          
```

> Powered by [Codecov](https://codecov.io?src=pr). Last update [142722c...f431f4c](https://codecov.io/gh/Stranger6667/postmarker/compare/142722ca135ce41d7d22b0e4c8e879f4e58f2c13...f431f4c38a1f534311bf48ff724b7d3e56aa0b9f?src=pr)

Patch:
diff --git a/README.rst b/README.rst
index 987356c..91534ae 100644
--- a/README.rst
+++ b/README.rst
@@ -74,10 +74,10 @@ Setup an email:
     >>> email.attach_binary(content=b'content', filename='readme.txt')
     >>> email.send()
 
-There a lot of features available. Check it out in our documentation! Just a few of them:
+There are a lot of features available. Check it out in our documentation! Just a few of them:
 
 - Support for sending Python email instances.
-- Bounces & Server API.
+- Bounces, Status & Server API.
 - Django email backend.
 
 Documentation
diff --git a/docs/changelog.rst b/docs/changelog.rst
index d0ba472..78f017f 100644
--- a/docs/changelog.rst
+++ b/docs/changelog.rst
@@ -3,6 +3,11 @@
 Changelog
 =========
 
+0.5.0 - TBA
+-----------
+
+- Status API. `#39`_
+
 0.4.0 - 09.10.2016
 ------------------
 
@@ -46,6 +51,7 @@ Changelog
 
 
 .. _#41: https://github.com/Stranger6667/postmarker/issues/41
+.. _#39: https://github.com/Stranger6667/postmarker/issues/39
 .. _#38: https://github.com/Stranger6667/postmarker/issues/38
 .. _#29: https://github.com/Stranger6667/postmarker/issues/29
 .. _#28: https://github.com/Stranger6667/postmarker/issues/28
diff --git a/docs/index.rst b/docs/index.rst
index cf4a3a9..b8854eb 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -18,6 +18,7 @@ Contents:
    emails
    bounces
    server
+   status
    django
    reference
    changelog
diff --git a/docs/status.rst b/docs/status.rst
new file mode 100644
index 0000000..cc1705d
--- /dev/null
+++ b/docs/status.rst
@@ -0,0 +1,45 @@
+.. _status:
+
+Status
+======
+
+Status API is available via ``status`` manager:
+
+.. code-block:: python
+
+    >>> postmark.status.get()
+    {'lastCheckDate': '2016-10-09T11:05:04Z', 'status': 'UP'}
+    >>> postmark.status.services
+    [
+        {'status': 'UP', 'url': '/services/api', 'name': 'API Response Time'},
+        {'status': 'UP', 'url': '/services/smtp', 'name': 'SMTP Response Time'},
+        {'status': 'UP', 'url': '/services/web', 'name': 'Web Response Time'},
+        {'status': 'UP', 'url': '/services/inbound', 'name': 'Inbound SMTP Response Time'}
+    ]
+    >>> postmark.status.availability
+    {
+        'fromDate': '2016-07-11T11:47:10.371Z',
+        'percentageUp': 0.9998308505688754,
+        'secondsDown': 5280,
+        'secondsUp': 31209723,
+        'toDate': '2016-10-09T11:47:10.372Z'
+    }
+    >>> postmark.status.delivery
+    [
+        {'missing': 0, 'spf': 1, 'spam': 0, 'inbox': 1, 'dkim': 1, 'name': 'AOL'},
+        {'missing': 0, 'spf': 1, 'spam': 0, 'inbox': 1, 'dkim': 1, 'name': 'Apple'},
+        {'missing': 0, 'spf': 1, 'spam': 0, 'inbox': 1, 'dkim': 1, 'name': 'Gmail'},
+        {'missing': 0, 'spf': 1, 'spam': 0, 'inbox': 1, 'dkim': 1, 'name': 'Hotmail'},
+        {'missing': 0, 'spf': 1, 'spam': 0, 'inbox': 1, 'dkim': 1, 'name': 'Yahoo!'}
+    ]
+
+Incidents are also available:
+
+.. code-block:: python
+
+    >>> postmark.incidents.last
+    <Incident: 1965>
+    >>> postmark.incidents.all
+    [<Incident: 1965>, ...]
+    >>> postmark.incidents.get(1965)
+    <Incident: 1965>
diff --git a/postmarker/__init__.py b/postmarker/__init__.py
index a932225..7b496d1 100644
--- a/postmarker/__init__.py
+++ b/postmarker/__init__.py
@@ -1,4 +1,4 @@
 # coding: utf-8
 
 
-__version__ = '0.4.0'
+__version__ = '0.5.0.dev'
diff --git a/postmarker/core.py b/postmarker/core.py
index eedf8fa..14fe02e 100644
--- a/postmarker/core.py
+++ b/postmarker/core.py
@@ -7,8 +7,11 @@ from .logging import get_logger
 from .models.bounces import BounceManager
 from .models.emails import EmailManager
 from .models.server import ServerManager
+from .models.status import StatusManager
 
 
+DEFAULT_API = 'https://api.postmarkapp.com/'
+STATUS_API = 'https://status.postmarkapp.com/api/1.0/'
 TEST_TOKEN = 'POSTMARK_API_TEST'
 
 
@@ -38,11 +41,11 @@ class PostmarkClient(with_metaclass(ClientMeta)):
     """
     Basic class for API clients. Provides basic functionality to make requests.
     """
-    root_url = 'https://api.postmarkapp.com/'
     _managers = (
         EmailManager,
         BounceManager,
         ServerManager,
+        StatusManager,
     )
 
     def __init__(self, token=None, verbosity=0):
@@ -72,17 +75,26 @@ class PostmarkClient(with_metaclass(ClientMeta)):
             self._session = requests.Session()
         return self._session
 
-    def _call(self, method, endpoint, data=None, **kwargs):
-        """
-        Low-level call to Postmark API.
-        """
-        headers = {
-            'X-Postmark-Server-Token': self.token,
-            'Accept': 'application/json',
-        }
-        url = urljoin(self.root_url, endpoint)
+    def call(self, method, endpoint, data=None, **kwargs):
+        return self._call(
+            method,
+            DEFAULT_API,
+            endpoint,
+            data,
+            {'X-Postmark-Server-Token': self.token},
+            **kwargs
+        )
+
+    def call_status(self, endpoint):
+        return self._call('GET', STATUS_API, endpoint)
+
+    def _call(self, method, root, endpoint, data=None, headers=None, **kwargs):
+        default_headers = {'Accept': 'application/json'}
+        if headers:
+            default_headers.update(headers)
+        url = urljoin(root, endpoint)
         self.logger.debug('Request: %s %s, Data: %s', method, url, data)
-        response = self.session.request(method, url, json=data, params=kwargs, headers=headers)
+        response = self.session.request(method, url, json=data, params=kwargs, headers=default_headers)
         self.logger.debug('Response: %s', response.text)
         response.raise_for_status()
         return response
diff --git a/postmarker/models/base.py b/postmarker/models/base.py
index 5d900f7..ac0a0e2 100644
--- a/postmarker/models/base.py
+++ b/postmarker/models/base.py
@@ -52,5 +52,5 @@ class ModelManager(object):
     def _init_instance(self, data):
         return self.model(manager=self, **data)
 
-    def _call(self, *args, **kwargs):
-        return self.client._call(*args, **kwargs)
+    def call(self, *args, **kwargs):
+        return self.client.call(*args, **kwargs)
diff --git a/postmarker/models/bounces.py b/postmarker/models/bounces.py
index 9eaf58d..c42735f 100644
--- a/postmarker/models/bounces.py
+++ b/postmarker/models/bounces.py
@@ -47,7 +47,7 @@ class BounceManager(ModelManager):
 
         :rtype: `dict`
         """
-        return self._call('GET', '/deliverystats').json()
+        return self.call('GET', '/deliverystats').json()
 
     @property
     def tags(self):
@@ -56,7 +56,7 @@ class BounceManager(ModelManager):
 
         :rtype: `list`
         """
-        return self._call('GET', '/bounces/tags').json()
+        return self.call('GET', '/bounces/tags').json()
 
     def get(self, id):
         """
@@ -65,7 +65,7 @@ class BounceManager(ModelManager):
         :param int id: Bounce ID.
         :rtype: :py:class:`Bounce`
         """
-        response = self._call('GET', '/bounces/%s' % id)
+        response = self.call('GET', '/bounces/%s' % id)
         return self._init_instance(response.json())
 
     def all(self, count=500, offset=0, type=None, inactive=None, emailFilter=None, tag=None, messageID=None,
@@ -85,7 +85,7 @@ class BounceManager(ModelManager):
         :return: A list of :py:class:`Bounce` instances.
         :rtype: `list`
         """
-        response = self._call(
+        response = self.call(
             'GET', '/bounces/', count=count, offset=offset, type=type, inactive=inactive, emailFilter=emailFilter,
             tag=tag, messageID=messageID, fromdate=fromdate, todate=todate
         )
@@ -99,7 +99,7 @@ class BounceManager(ModelManager):
         :return: Activation result and bounce data.
         :rtype: `dict`
         """
-        return self._call('PUT', '/bounces/%s/activate' % id).json()
+        return self.call('PUT', '/bounces/%s/activate' % id).json()
 
     def get_dump(self, id):
         """
@@ -109,5 +109,5 @@ class BounceManager(ModelManager):
         :return: Dump of SMTP data if it is available.
         :rtype: `str` or `None`
         """
-        dump = self._call('GET', '/bounces/%s/dump' % id).json()
+        dump = self.call('GET', '/bounces/%s/dump' % id).json()
         return dump.get('Body')
diff --git a/postmarker/models/emails.py b/postmarker/models/emails.py
index e46e13e..511f72b 100644
--- a/postmarker/models/emails.py
+++ b/postmarker/models/emails.py
@@ -206,13 +206,13 @@ class EmailManager(ModelManager):
         """
         Low-level send call. Does not apply any transformation to given data.
         """
-        return self._call('POST', '/email', data=kwargs).json()
+        return self.call('POST', '/email', data=kwargs).json()
 
     def _send_batch(self, *emails):
         """
         Low-level batch send call.
         """
-        return self._call('POST', '/email/batch', data=emails).json()
+        return self.call('POST', '/email/batch', data=emails).json()
 
     def send(self, message=None, From=None, To=None, Cc=None, Bcc=None, Subject=None, Tag=None, HtmlBody=None,
              TextBody=None, ReplyTo=None, Headers=None, TrackOpens=None, Attachments=None):
diff --git a/postmarker/models/server.py b/postmarker/models/server.py
index ca19601..c8cb81a 100644
--- a/postmarker/models/server.py
+++ b/postmarker/models/server.py
@@ -20,8 +20,8 @@ class ServerManager(ModelManager):
     model = Server
 
     def get(self):
-        response = self._call('GET', '/server')
+        response = self.call('GET', '/server')
         return self._init_instance(response.json())
 
     def edit(self, **kwargs):
-        return self._call('PUT', '/server', data=kwargs).json()
+        return self.call('PUT', '/server', data=kwargs).json()
diff --git a/postmarker/models/status.py b/postmarker/models/status.py
new file mode 100644
index 0000000..537ab72
--- /dev/null
+++ b/postmarker/models/status.py
@@ -0,0 +1,55 @@
+# coding: utf-8
+from .base import Model, ModelManager
+
+
+class Incident(Model):
+
+    def __str__(self):
+        return '%s: %s' % (self.__class__.__name__, self._data.get('id'))
+
+
+class IncidentsManager(ModelManager):
+    name = 'incidents'
+    model = Incident
+
+    def call(self, *args, **kwargs):
+        return self.client.call_status(*args, **kwargs)
+
+    @property
+    def last(self):
+        return self._init_instance(self.call('last_incident').json())
+
+    def all(self):
+        return [self._init_instance(incident) for incident in self.call('incidents').json()]
+
+    def get(self, id):
+        return self._init_instance(self.call('incidents/%s' % id).json())
+
+
+class StatusManager(ModelManager):
+    """
+    Gathers logic about Postmark systems status.
+    """
+    name = 'status'
+
+    def __init__(self, *args, **kwargs):
+        super(StatusManager, self).__init__(*args, **kwargs)
+        self.incidents = IncidentsManager(self.client)
+
+    def call(self, *args, **kwargs):
+        return self.client.call_status(*args, **kwargs)
+
+    def get(self):
+        return self.call('status').json()
+
+    @property
+    def services(self):
+        return self.call('services').json()
+
+    @property
+    def availability(self):
+        return self.call('services/availability').json()
+
+    @property
+    def delivery(self):
+        return self.call('delivery').json()
diff --git a/tox.ini b/tox.ini
index 3cce971..217f665 100644
--- a/tox.ini
+++ b/tox.ini
@@ -46,5 +46,6 @@ deps =
     pytest
     betamax
     betamax_serializers
+    Django
     py26,py27,py32,pypy,pypy3: mock
 commands = pytest --record {posargs:tests}
\ No newline at end of file


Test patch:
diff --git a/tests/cassettes/status.json b/tests/cassettes/status.json
new file mode 100644
index 0000000..a56f4ca
--- /dev/null
+++ b/tests/cassettes/status.json
@@ -0,0 +1,463 @@
+{
+  "http_interactions": [
+    {
+      "recorded_at": "2016-10-09T11:48:47",
+      "request": {
+        "body": {
+          "base64_string": "",
+          "encoding": "utf-8"
+        },
+        "headers": {
+          "Accept": [
+            "application/json"
+          ],
+          "Accept-Encoding": [
+            "gzip, deflate"
+          ],
+          "Connection": [
+            "keep-alive"
+          ],
+          "User-Agent": [
+            "python-requests/2.11.1"
+          ]
+        },
+        "method": "GET",
+        "uri": "https://status.postmarkapp.com/api/1.0/status"
+      },
+      "response": {
+        "body": {
+          "base64_string": "eyJzdGF0dXMiOiJVUCIsImxhc3RDaGVja0RhdGUiOiIyMDE2LTEwLTA5VDExOjQ4OjIxWiJ9",
+          "encoding": "utf-8"
+        },
+        "headers": {
+          "Connection": [
+            "Keep-Alive"
+          ],
+          "Content-Length": [
+            "54"
+          ],
+          "Content-Type": [
+            "application/json; charset=utf-8"
+          ],
+          "Date": [
+            "Sun, 09 Oct 2016 11:48:47 GMT"
+          ],
+          "ETag": [
+            "W/\"36-5N8CTENaD1N6zoXR6J7pHA\""
+          ],
+          "Keep-Alive": [
+            "timeout=5, max=100"
+          ],
+          "Server": [
+            "Apache"
+          ],
+          "Vary": [
+            "Accept-Encoding"
+          ],
+          "X-Powered-By": [
+            "Express"
+          ]
+        },
+        "status": {
+          "code": 200,
+          "message": "OK"
+        },
+        "url": "https://status.postmarkapp.com/api/1.0/status"
+      }
+    },
+    {
+      "recorded_at": "2016-10-09T11:48:47",
+      "request": {
+        "body": {
+          "base64_string": "",
+          "encoding": "utf-8"
+        },
+        "headers": {
+          "Accept": [
+            "application/json"
+          ],
+          "Accept-Encoding": [
+            "gzip, deflate"
+          ],
+          "Connection": [
+            "keep-alive"
+          ],
+          "User-Agent": [
+            "python-requests/2.11.1"
+          ]
+        },
+        "method": "GET",
+        "uri": "https://status.postmarkapp.com/api/1.0/last_incident"
+      },
+      "response": {
+        "body": {
+          "base64_string": "eyJpZCI6IjE5NjUiLCJ0eXBlIjoiREVHUkFERUQiLCJjcmVhdGVkX2F0IjoiMjAxNi0xMC0wOFQwMjoxMTowMCswMDowMCIsInVwZGF0ZWRfYXQiOiIyMDE2LTEwLTA4VDAyOjMxOjAwKzAwOjAwIiwidGl0bGUiOiJEZWxheWluZyBpbiBpbmJvdW5kIGFuZCBvdXRib3VuZCBwcm9jZXNzaW5nIiwidXBkYXRlcyI6W3siYm9keSI6IldlJ3JlIHF1ZXVlaW5nIHVwIG1lc3NhZ2VzIHRvIGJlIHByb2Nlc3NlZCwgYWZmZWN0aW5nIGluYm91bmQgYW5kIG91dGJvdW5kIHRyYWZmaWMuIFdlJ3JlIHdvcmtpbmcgdG8gcmVzb2x2ZSBBU0FQLiIsInN0YXR1cyI6IkludmVzdGlnYXRpbmciLCJ0aW1lc3RhbXAiOiIyMDE2LTEwLTA4VDAyOjExOjAwKzAwOjAwIn0seyJib2R5IjoiT3V0Ym91bmQgYW5kIGluYm91bmQgbWVzc2FnZXMgc2hvdWxkIGJlIGJhY2sgdG8gZ2V0dGluZyBwcm9jZXNzZWQgaW1tZWRpYXRlbHkgYW5kIHNhdmVkIGpvYnMgYXJlIGFsbCBwcm9jZXNzZWQuIFdlJ3JlIGNvbnRpbnVpbmcgdG8gbW9uaXRvciB0aGUgc2l0dWF0aW9uLiIsInN0YXR1cyI6IlBlbmRpbmciLCJ0aW1lc3RhbXAiOiIyMDE2LTEwLTA4VDAyOjIwOjAwKzAwOjAwIn0seyJib2R5IjoiVGhlIGlzc3VlIGhhcyBiZWVuIHJlc29sdmVkIGFuZCBhbGwgcXVldWVzIGFyZSBiYWNrIHRvIG5vcm1hbC4iLCJzdGF0dXMiOiJSZXNvbHZlZCIsInRpbWVzdGFtcCI6IjIwMTYtMTAtMDhUMDI6MzE6MDArMDA6MDAifV0sInJlc29sdmVkX2F0IjoiMjAxNi0xMC0wOFQwMjozMTowMCswMDowMCIsImJvZHkiOiIifQ==",
+          "encoding": "utf-8"
+        },
+        "headers": {
+          "Connection": [
+            "Keep-Alive"
+          ],
+          "Content-Length": [
+            "781"
+          ],
+          "Content-Type": [
+            "application/json; charset=utf-8"
+          ],
+          "Date": [
+            "Sun, 09 Oct 2016 11:48:47 GMT"
+          ],
+          "ETag": [
+            "W/\"30d-U5ySgFTulxAwoNUxdLcbyg\""
+          ],
+          "Keep-Alive": [
+            "timeout=5, max=99"
+          ],
+          "Server": [
+            "Apache"
+          ],
+          "Vary": [
+            "Accept-Encoding"
+          ],
+          "X-Powered-By": [
+            "Express"
+          ]
+        },
+        "status": {
+          "code": 200,
+          "message": "OK"
+        },
+        "url": "https://status.postmarkapp.com/api/1.0/last_incident"
+      }
+    },
+    {
+      "recorded_at": "2016-10-09T11:48:47",
+      "request": {
+        "body": {
+          "base64_string": "",
+          "encoding": "utf-8"
+        },
+        "headers": {
+          "Accept": [
+            "application/json"
+          ],
+          "Accept-Encoding": [
+            "gzip, deflate"
+          ],
+          "Connection": [
+            "keep-alive"
+          ],
+          "User-Agent": [
+            "python-requests/2.11.1"
+          ]
+        },
+        "method": "GET",
+        "uri": "https://status.postmarkapp.com/api/1.0/incidents"
+      },
+      "response": {
+        "body": {
+          "base64_string": "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",
+          "encoding": "utf-8"
+        },
+        "headers": {
+          "Connection": [
+            "Keep-Alive"
+          ],
+          "Content-Encoding": [
+            "gzip"
+          ],
+          "Content-Type": [
+            "application/json; charset=utf-8"
+          ],
+          "Date": [
+            "Sun, 09 Oct 2016 11:48:47 GMT"
+          ],
+          "ETag": [
+            "W/\"903e-CNe6Jy97dSnr9Wf4+NYx/A\""
+          ],
+          "Keep-Alive": [
+            "timeout=5, max=98"
+          ],
+          "Server": [
+            "Apache"
+          ],
+          "Transfer-Encoding": [
+            "chunked"
+          ],
+          "Vary": [
+            "Accept-Encoding"
+          ],
+          "X-Powered-By": [
+            "Express"
+          ]
+        },
+        "status": {
+          "code": 200,
+          "message": "OK"
+        },
+        "url": "https://status.postmarkapp.com/api/1.0/incidents"
+      }
+    },
+    {
+      "recorded_at": "2016-10-09T11:48:48",
+      "request": {
+        "body": {
+          "base64_string": "",
+          "encoding": "utf-8"
+        },
+        "headers": {
+          "Accept": [
+            "application/json"
+          ],
+          "Accept-Encoding": [
+            "gzip, deflate"
+          ],
+          "Connection": [
+            "keep-alive"
+          ],
+          "User-Agent": [
+            "python-requests/2.11.1"
+          ]
+        },
+        "method": "GET",
+        "uri": "https://status.postmarkapp.com/api/1.0/incidents/1965"
+      },
+      "response": {
+        "body": {
+          "base64_string": "eyJpZCI6IjE5NjUiLCJ0eXBlIjoiREVHUkFERUQiLCJjcmVhdGVkX2F0IjoiMjAxNi0xMC0wOFQwMjoxMTowMCswMDowMCIsInVwZGF0ZWRfYXQiOiIyMDE2LTEwLTA4VDAyOjMxOjAwKzAwOjAwIiwidGl0bGUiOiJEZWxheWluZyBpbiBpbmJvdW5kIGFuZCBvdXRib3VuZCBwcm9jZXNzaW5nIiwidXBkYXRlcyI6W3siYm9keSI6IldlJ3JlIHF1ZXVlaW5nIHVwIG1lc3NhZ2VzIHRvIGJlIHByb2Nlc3NlZCwgYWZmZWN0aW5nIGluYm91bmQgYW5kIG91dGJvdW5kIHRyYWZmaWMuIFdlJ3JlIHdvcmtpbmcgdG8gcmVzb2x2ZSBBU0FQLiIsInN0YXR1cyI6IkludmVzdGlnYXRpbmciLCJ0aW1lc3RhbXAiOiIyMDE2LTEwLTA4VDAyOjExOjAwKzAwOjAwIn0seyJib2R5IjoiT3V0Ym91bmQgYW5kIGluYm91bmQgbWVzc2FnZXMgc2hvdWxkIGJlIGJhY2sgdG8gZ2V0dGluZyBwcm9jZXNzZWQgaW1tZWRpYXRlbHkgYW5kIHNhdmVkIGpvYnMgYXJlIGFsbCBwcm9jZXNzZWQuIFdlJ3JlIGNvbnRpbnVpbmcgdG8gbW9uaXRvciB0aGUgc2l0dWF0aW9uLiIsInN0YXR1cyI6IlBlbmRpbmciLCJ0aW1lc3RhbXAiOiIyMDE2LTEwLTA4VDAyOjIwOjAwKzAwOjAwIn0seyJib2R5IjoiVGhlIGlzc3VlIGhhcyBiZWVuIHJlc29sdmVkIGFuZCBhbGwgcXVldWVzIGFyZSBiYWNrIHRvIG5vcm1hbC4iLCJzdGF0dXMiOiJSZXNvbHZlZCIsInRpbWVzdGFtcCI6IjIwMTYtMTAtMDhUMDI6MzE6MDArMDA6MDAifV0sImJvZHkiOiIiLCJyZXNvbHZlZF9hdCI6IjIwMTYtMTAtMDhUMDI6MzE6MDArMDA6MDAifQ==",
+          "encoding": "utf-8"
+        },
+        "headers": {
+          "Connection": [
+            "Keep-Alive"
+          ],
+          "Content-Length": [
+            "781"
+          ],
+          "Content-Type": [
+            "application/json; charset=utf-8"
+          ],
+          "Date": [
+            "Sun, 09 Oct 2016 11:48:48 GMT"
+          ],
+          "ETag": [
+            "W/\"30d-epNBwXh6OrUXu6VxsPKNFA\""
+          ],
+          "Keep-Alive": [
+            "timeout=5, max=97"
+          ],
+          "Server": [
+            "Apache"
+          ],
+          "Vary": [
+            "Accept-Encoding"
+          ],
+          "X-Powered-By": [
+            "Express"
+          ]
+        },
+        "status": {
+          "code": 200,
+          "message": "OK"
+        },
+        "url": "https://status.postmarkapp.com/api/1.0/incidents/1965"
+      }
+    },
+    {
+      "recorded_at": "2016-10-09T11:48:48",
+      "request": {
+        "body": {
+          "base64_string": "",
+          "encoding": "utf-8"
+        },
+        "headers": {
+          "Accept": [
+            "application/json"
+          ],
+          "Accept-Encoding": [
+            "gzip, deflate"
+          ],
+          "Connection": [
+            "keep-alive"
+          ],
+          "User-Agent": [
+            "python-requests/2.11.1"
+          ]
+        },
+        "method": "GET",
+        "uri": "https://status.postmarkapp.com/api/1.0/services"
+      },
+      "response": {
+        "body": {
+          "base64_string": "W3sibmFtZSI6IkFQSSBSZXNwb25zZSBUaW1lIiwic3RhdHVzIjoiVVAiLCJ1cmwiOiIvc2VydmljZXMvYXBpIn0seyJuYW1lIjoiU01UUCBSZXNwb25zZSBUaW1lIiwic3RhdHVzIjoiVVAiLCJ1cmwiOiIvc2VydmljZXMvc210cCJ9LHsibmFtZSI6IldlYiBSZXNwb25zZSBUaW1lIiwic3RhdHVzIjoiVVAiLCJ1cmwiOiIvc2VydmljZXMvd2ViIn0seyJuYW1lIjoiSW5ib3VuZCBTTVRQIFJlc3BvbnNlIFRpbWUiLCJzdGF0dXMiOiJVUCIsInVybCI6Ii9zZXJ2aWNlcy9pbmJvdW5kIn1d",
+          "encoding": "utf-8"
+        },
+        "headers": {
+          "Connection": [
+            "Keep-Alive"
+          ],
+          "Content-Length": [
+            "276"
+          ],
+          "Content-Type": [
+            "application/json; charset=utf-8"
+          ],
+          "Date": [
+            "Sun, 09 Oct 2016 11:48:48 GMT"
+          ],
+          "ETag": [
+            "W/\"114-kO7V9l/yeC/wHw8NLMUAIw\""
+          ],
+          "Keep-Alive": [
+            "timeout=5, max=96"
+          ],
+          "Server": [
+            "Apache"
+          ],
+          "Vary": [
+            "Accept-Encoding"
+          ],
+          "X-Powered-By": [
+            "Express"
+          ]
+        },
+        "status": {
+          "code": 200,
+          "message": "OK"
+        },
+        "url": "https://status.postmarkapp.com/api/1.0/services"
+      }
+    },
+    {
+      "recorded_at": "2016-10-09T11:48:48",
+      "request": {
+        "body": {
+          "base64_string": "",
+          "encoding": "utf-8"
+        },
+        "headers": {
+          "Accept": [
+            "application/json"
+          ],
+          "Accept-Encoding": [
+            "gzip, deflate"
+          ],
+          "Connection": [
+            "keep-alive"
+          ],
+          "User-Agent": [
+            "python-requests/2.11.1"
+          ]
+        },
+        "method": "GET",
+        "uri": "https://status.postmarkapp.com/api/1.0/services/availability"
+      },
+      "response": {
+        "body": {
+          "base64_string": "eyJmcm9tRGF0ZSI6IjIwMTYtMDctMTFUMTE6NDc6MTAuMzcxWiIsInRvRGF0ZSI6IjIwMTYtMTAtMDlUMTE6NDc6MTAuMzcyWiIsInNlY29uZHNVcCI6MzEyMDk3MjMsInNlY29uZHNEb3duIjo1MjgwLCJwZXJjZW50YWdlVXAiOjAuOTk5ODMwODUwNTY4ODc1NH0=",
+          "encoding": "utf-8"
+        },
+        "headers": {
+          "Connection": [
+            "Keep-Alive"
+          ],
+          "Content-Length": [
+            "149"
+          ],
+          "Content-Type": [
+            "application/json; charset=utf-8"
+          ],
+          "Date": [
+            "Sun, 09 Oct 2016 11:48:48 GMT"
+          ],
+          "ETag": [
+            "W/\"95-Wp5kdnTJlzpAZQWzWbI4Ag\""
+          ],
+          "Keep-Alive": [
+            "timeout=5, max=95"
+          ],
+          "Server": [
+            "Apache"
+          ],
+          "Vary": [
+            "Accept-Encoding"
+          ],
+          "X-Powered-By": [
+            "Express"
+          ]
+        },
+        "status": {
+          "code": 200,
+          "message": "OK"
+        },
+        "url": "https://status.postmarkapp.com/api/1.0/services/availability"
+      }
+    },
+    {
+      "recorded_at": "2016-10-09T11:48:48",
+      "request": {
+        "body": {
+          "base64_string": "",
+          "encoding": "utf-8"
+        },
+        "headers": {
+          "Accept": [
+            "application/json"
+          ],
+          "Accept-Encoding": [
+            "gzip, deflate"
+          ],
+          "Connection": [
+            "keep-alive"
+          ],
+          "User-Agent": [
+            "python-requests/2.11.1"
+          ]
+        },
+        "method": "GET",
+        "uri": "https://status.postmarkapp.com/api/1.0/delivery"
+      },
+      "response": {
+        "body": {
+          "base64_string": "W3sibmFtZSI6IkFPTCIsImRraW0iOjEsImluYm94IjoxLCJtaXNzaW5nIjowLCJzcGFtIjowLCJzcGYiOjF9LHsibmFtZSI6IkFwcGxlIiwiZGtpbSI6MSwiaW5ib3giOjEsIm1pc3NpbmciOjAsInNwYW0iOjAsInNwZiI6MX0seyJuYW1lIjoiR21haWwiLCJka2ltIjoxLCJpbmJveCI6MSwibWlzc2luZyI6MCwic3BhbSI6MCwic3BmIjoxfSx7Im5hbWUiOiJIb3RtYWlsIiwiZGtpbSI6MSwiaW5ib3giOjEsIm1pc3NpbmciOjAsInNwYW0iOjAsInNwZiI6MX0seyJuYW1lIjoiWWFob28hIiwiZGtpbSI6MSwiaW5ib3giOjEsIm1pc3NpbmciOjAsInNwYW0iOjAsInNwZiI6MX1d",
+          "encoding": "utf-8"
+        },
+        "headers": {
+          "Connection": [
+            "Keep-Alive"
+          ],
+          "Content-Length": [
+            "327"
+          ],
+          "Content-Type": [
+            "application/json; charset=utf-8"
+          ],
+          "Date": [
+            "Sun, 09 Oct 2016 11:48:48 GMT"
+          ],
+          "ETag": [
+            "W/\"147-KirPH/cGGHjoGYDN8HMDAA\""
+          ],
+          "Keep-Alive": [
+            "timeout=5, max=94"
+          ],
+          "Server": [
+            "Apache"
+          ],
+          "Vary": [
+            "Accept-Encoding"
+          ],
+          "X-Powered-By": [
+            "Express"
+          ]
+        },
+        "status": {
+          "code": 200,
+          "message": "OK"
+        },
+        "url": "https://status.postmarkapp.com/api/1.0/delivery"
+      }
+    }
+  ],
+  "recorded_with": "betamax/0.8.0"
+}
\ No newline at end of file
diff --git a/tests/helpers.py b/tests/helpers.py
index adf0333..31e9e74 100644
--- a/tests/helpers.py
+++ b/tests/helpers.py
@@ -26,7 +26,7 @@ def replace_real_credentials(cassette_dir, production_token, test_token):
             data = json.load(fp)
         rewrite_required = False
         for record in data['http_interactions']:
-            if record['request']['headers']['X-Postmark-Server-Token'] == [production_token]:
+            if record['request']['headers'].get('X-Postmark-Server-Token') == [production_token]:
                 record['request']['headers']['X-Postmark-Server-Token'] = [test_token]
                 rewrite_required = True
         if rewrite_required:
diff --git a/tests/models/test_status.py b/tests/models/test_status.py
new file mode 100644
index 0000000..cd85d34
--- /dev/null
+++ b/tests/models/test_status.py
@@ -0,0 +1,88 @@
+# coding: utf-8
+from postmarker.models.status import Incident
+
+
+CASSETTE_NAME = 'status'
+
+LAST_INCIDENT = {
+    'body': '',
+    'created_at': '2016-10-08T02:11:00+00:00',
+    'id': '1965',
+    'resolved_at': '2016-10-08T02:31:00+00:00',
+    'title': 'Delaying in inbound and outbound processing',
+    'type': 'DEGRADED',
+    'updated_at': '2016-10-08T02:31:00+00:00',
+    'updates': [
+        {
+            'status': 'Investigating',
+            'body': "We're queueing up messages to be processed, affecting inbound and outbound traffic. "
+                    "We're working to resolve ASAP.",
+            'timestamp': '2016-10-08T02:11:00+00:00'
+        },
+        {
+            'status': 'Pending',
+            'body': "Outbound and inbound messages should be back to getting processed immediately and "
+                    "saved jobs are all processed. We're continuing to monitor the situation.",
+            'timestamp': '2016-10-08T02:20:00+00:00'
+        },
+        {
+            'status': 'Resolved',
+            'body': 'The issue has been resolved and all queues are back to normal.',
+            'timestamp': '2016-10-08T02:31:00+00:00'
+        }
+    ]
+}
+
+
+def test_status(postmark):
+    assert postmark.status.get() == {
+        'lastCheckDate': '2016-10-09T11:48:21Z',
+        'status': 'UP'
+    }
+
+
+def test_last_incident(postmark):
+    incident = postmark.status.incidents.last
+    assert isinstance(incident, Incident)
+    assert incident.as_dict() == LAST_INCIDENT
+    assert str(incident) == 'Incident: 1965'
+
+
+def test_incidents(postmark):
+    incidents = postmark.status.incidents.all()
+    assert all(isinstance(incident, Incident) for incident in incidents)
+
+
+def test_get_incident(postmark):
+    incident = postmark.status.incidents.get(1965)
+    assert isinstance(incident, Incident)
+    assert incident.as_dict() == LAST_INCIDENT
+
+
+def test_services(postmark):
+    assert postmark.status.services == [
+        {'status': 'UP', 'url': '/services/api', 'name': 'API Response Time'},
+        {'status': 'UP', 'url': '/services/smtp', 'name': 'SMTP Response Time'},
+        {'status': 'UP', 'url': '/services/web', 'name': 'Web Response Time'},
+        {'status': 'UP', 'url': '/services/inbound', 'name': 'Inbound SMTP Response Time'}
+    ]
+
+
+def test_availability(postmark):
+    assert postmark.status.availability == {
+        'fromDate': '2016-07-11T11:47:10.371Z',
+        'percentageUp': 0.9998308505688754,
+        'secondsDown': 5280,
+        'secondsUp': 31209723,
+        'toDate': '2016-10-09T11:47:10.372Z'
+    }
+
+
+def test_delivery(postmark):
+    assert postmark.status.delivery == [
+        {'missing': 0, 'spf': 1, 'spam': 0, 'inbox': 1, 'dkim': 1, 'name': 'AOL'},
+        {'missing': 0, 'spf': 1, 'spam': 0, 'inbox': 1, 'dkim': 1, 'name': 'Apple'},
+        {'missing': 0, 'spf': 1, 'spam': 0, 'inbox': 1, 'dkim': 1, 'name': 'Gmail'},
+        {'missing': 0, 'spf': 1, 'spam': 0, 'inbox': 1, 'dkim': 1, 'name': 'Hotmail'},
+        {'missing': 0, 'spf': 1, 'spam': 0, 'inbox': 1, 'dkim': 1, 'name': 'Yahoo!'}
+    ]
diff --git a/tests/test_core.py b/tests/test_core.py
index b7d7ae1..5d59bc4 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -10,7 +10,7 @@ from postmarker.models.bounces import BounceManager
 class TestClient:
 
     def test_server_client(self, postmark, api_token, patched_request):
-        postmark._call('GET', 'endpoint')
+        postmark.call('GET', 'endpoint')
         patched_request.assert_called_with(
             'GET',
             'https://api.postmarkapp.com/endpoint',