Here at SparkPost, I spend most of my time writing JavaScript. However, the first programming language I really enjoyed was Python. As a member of the dev relations team, I get to write some Python here and there. Whether it’s crunching data and generating reports with jupyter notebook or maintaining our python-sparkpost library, I look forward to spending some quality time with one of my favorite languages. If you are here, chances are you’ve got similar feelings about Python, and you probably want to know how you can use it with SparkPost. So let’s get started!

Installing & Setup

Regardless of which library or framework you’re using, you’ll need to install python-sparkpost:

pip install sparkpost

Once installed you can import and create an instance of the SparkPost class:

from sparkpost import SparkPost
sp = SparkPost('YOUR API KEY')

If you’d like to avoid putting your API key in code (we highly recommend storing it outside your code), the client library will detect the SPARKPOST_API_KEY environment variable.

Sending Email

Now that you have a SparkPost instance, you’re ready to send. There are quite a few options available for sending, but we’ll start with a simple example. Let’s send an email to a single recipient, specifying inline content:

    html='<p>Hello world</p>',
    subject='Hello from python-sparkpost'

The recipients argument can be a list containing a mix of strings and dictionaries or a single dictionary with one recipient. Following are some examples of valid values that can be passed to the recipients argument.

String with email only:


String with friendly from and email:

recipients=['"Fictitious Person" <>']


    'address': {
        'email': '',
        'name': 'John Doe'

It’s worth noting that under the hood, the library parses strings and ultimately converts them into the dictionary format before calling the SparkPost API.

There are more options available with transmissions, including specifying stored templates or recipient lists, cc and bcc, adding attachments, specifying a campaign, using substitution data, and much more. Check out the examples, docs for the Transmission class, and the Transmissions API documentation for more info.

Error Handling

We intercept any non-2xx responses from the SparkPost API and wrap them using the SparkPostAPIException  class. You can use this class in your code to catch API exceptions and extract information about the underlying error. We use the excellent requests library under the hood and expose requests’ response object through err.response.

from sparkpost import SparkPost
from sparkpost.exceptions import SparkPostAPIException

sp = SparkPost()

        text='Hello there',
        from_email='Testing <>',
        subject='Testing python-sparkpost exceptions'
except SparkPostAPIException as err:
    # http response status code
    # python requests library response object
    # list of formatted errors

The above code would output the following:

{u'errors': [{u'message': u'Invalid domain', u'code': u'7001', u'description':
u'Unconfigured Sending Domain <> '}]}
['Invalid domain Code: 7001 Description: Unconfigured Sending Domain
<>  \n']

Other Capabilities

The Transmissions class is essentially a wrapper with some syntactic sugar. It’s a subclass of the Resource class, which can be used directly to access the API. This comes in handy when you need to access an underlying API that we haven’t wrapped. Let’s use webhooks as an example:

import os

from sparkpost.base import Resource

#subclass the Resource class
class Webhooks(Resource):
    key = "webhooks"

    def list(self, **kwargs):
        results = self.request('GET', self.uri, **kwargs)
        return results

api_key = os.environ.get('SPARKPOST_API_KEY', None)
webhooks = Webhooks('', api_key)

# returns a list of webhooks for your account

Usage with Django

There are two ways to use SparkPost through Django. The python-sparkpost library includes a Django email backend (docs).

To configure Django to use SparkPost, put the following configuration in file.

EMAIL_BACKEND = 'sparkpost.django.email_backend.SparkPostEmailBackend'

Replace API_KEY with an actual API key with the “Send via SMTP” permission. We recommend reading the API key from the SPARKPOST_API_KEY environment variable using os.environ.get.

You can also use SPARKPOST_OPTIONS to set options that will apply to every transmission. For example:

    'track_opens': False,
    'track_clicks': False,
    'transactional': True,

Django is now configured to use the SparkPost email backend. You can send mail using Django’s send_mail method:

from django.core.mail import send_mail

    subject='Hello from SparkPost',
    message='Woo hoo! Sent from Django!',
    html_message='<p>Hello Rock stars!</p>',

You can also use the EmailMessage or EmailMultiAlternatives classes directly. That will give you access to more specific fields like template:

email = EmailMessage(
            "address": "",
            "substitution_data": {
                "key": "value"
email.template = 'template-id'

Alternatively, you can use the excellent django-anymail library, which provides a layer of abstraction on top of several email service providers. For usage instructions, consult the django-anymail documentation for SparkPost.

Usage with Flask

Using SparkPost with Flask is simple—use it like you would with any Python script. This simple example code shows the bare minimum for a Flask app that uses python-sparkpost, catching and returning any exceptions from the API:

from flask import Flask
from sparkpost import SparkPost
from sparkpost.exceptions import SparkPostAPIException

app = Flask(__name__)
sp = SparkPost()

def send_email():
            html='<p>Hello world</p>',
            subject='Hello from python-sparkpost'
        return "Message sent successfully"
    except SparkPostAPIException as err:
        return "<br>".join(err.errors)

if __name__ == "__main__":


We’ve tried to make using SparkPost with Python as simple and enjoyable as writing any other Python code. If you run into any issues or have any questions, feel free to submit an issue on the github repo or join us on our community Slack team in the #python channel. I’d love to hear from you and, selfishly, get the chance to talk about Python.

—Rich Leland
Director of Growth Engineering