Using the Django Package

The django-notifiedby package provides a Python interface for the NotifiedBy API, including full support for email flows, recipients, and flags. This page covers how to set up the package and use it to manage email flows from your Django application.

Installation

pip install django-notifiedby
pip install requests

Configuration

Add the following to your Django settings.py:

INSTALLED_APPS = [
    # ... your other apps
    'notifiedby',
]

EMAIL_BACKEND = "notifiedby.NotifiedByEmailBackend"
NOTIFIEDBY_API_KEY = "YOUR_API_KEY"

Note

Setting EMAIL_BACKEND makes NotifiedBy the default backend for all Django email sending, including send_mail(). This is optional if you only want to use the flow and recipient functions.

If you use custom encryption keys for email content, also add:

NOTIFIEDBY_ENCRYPTION_KEY = "your-encryption-key"

The API key and encryption key will be read automatically from your Django settings by all package functions.

Subscribing to a Flow

Use subscribe_to_flow() to add a recipient to an email flow. The recipient will be created automatically if they don’t already exist.

from notifiedby import subscribe_to_flow

subscribe_to_flow(
    flow_trigger='WELCOME_SIGNUP',
    email='user@example.com',
    first_name='John',
    last_name='Doe',
    flags=['new_user', 'free_plan']
)

Parameter

Required

Description

flow_trigger

Yes

The trigger keyword of the flow.

email

Yes

The recipient’s email address.

first_name

No

The recipient’s first name.

last_name

No

The recipient’s last name.

flags

No

A list of flag names to set on the recipient.

client

No

A custom NotifiedByClient instance (see email_flows/django_package:Using a Custom Client).

A common pattern is to subscribe users when they sign up, using a Django signal:

from django.db.models.signals import post_save
from django.dispatch import receiver
from django.contrib.auth.models import User
from notifiedby import subscribe_to_flow

@receiver(post_save, sender=User)
def on_user_created(sender, instance, created, **kwargs):
    if created:
        subscribe_to_flow(
            flow_trigger='WELCOME_SIGNUP',
            email=instance.email,
            first_name=instance.first_name,
            last_name=instance.last_name,
        )

Unsubscribing from a Flow

Use unsubscribe_from_flow() to stop a recipient from receiving further emails in a flow.

from notifiedby import unsubscribe_from_flow

unsubscribe_from_flow(
    flow_trigger='WELCOME_SIGNUP',
    email='user@example.com'
)

Listing Flow Subscriptions

Use list_flow_subscriptions() to retrieve all flow subscriptions for your team. Results are paginated.

from notifiedby import list_flow_subscriptions

result = list_flow_subscriptions(page=1)

print(f"Total subscriptions: {result['count']}")

for sub in result['results']:
    print(f"{sub['recipient_email']} - {sub['flow_name']} ({sub['status']})")

Each subscription in the results contains:

Field

Description

id

The subscription ID.

flow_name

The human-readable name of the flow.

flow_trigger

The trigger keyword of the flow.

recipient_email

The subscribed recipient’s email address.

status

One of active, completed, or cancelled.

current_step_order

The current step number in the sequence.

next_send_date

When the next step will be processed.

created_at

When the subscription was created.

updated_at

When the subscription was last updated.

Deleting All Subscriptions

Use delete_all_subscriptions() to remove all flow subscriptions for your team.

from notifiedby import delete_all_subscriptions

delete_all_subscriptions()

Warning

This deletes all subscriptions for your team and cannot be undone. Use with caution.

Managing Recipients

You can create and list recipients independently of flows.

Creating a Recipient

from notifiedby import create_recipient

recipient = create_recipient(
    email='user@example.com',
    first_name='John',
    last_name='Doe',
    flags=['premium', 'active']
)

If a recipient with that email already exists, their details will be updated.

Listing Recipients

from notifiedby import list_recipients

recipients = list_recipients()
for r in recipients:
    print(f"{r['email']} - {r['first_name']} {r['last_name']}")

Managing Recipient Flags

Flags let you tag recipients for segmentation and flow branching. You can set and clear flags at any time.

Setting Flags

from notifiedby import set_recipient_flags

set_recipient_flags(
    email='user@example.com',
    flags=['premium', 'onboarded']
)

Clearing Flags

from notifiedby import clear_recipient_flags

clear_recipient_flags(
    email='user@example.com',
    flags=['trial']
)

Querying Sent Emails

The package also provides functions to query emails that have been sent.

from notifiedby import get_email_detail, list_emails, get_delivery_status

# Get details of a specific email by ID
email = get_email_detail(email_id='JDT')

# List sent emails (paginated)
emails = list_emails(page=1)

# Get delivery status of a specific email
status = get_delivery_status(email_id='JDT')

Error Handling

All functions raise exceptions from the notifiedby.exceptions module when something goes wrong.

from notifiedby import subscribe_to_flow
from notifiedby.exceptions import (
    NotifiedByError,
    NotifiedByConfigError,
    NotifiedByAPIError,
    NotifiedByValidationError,
    NotifiedByAuthError,
    NotifiedByNotFoundError,
)

try:
    subscribe_to_flow(
        flow_trigger='WELCOME_SIGNUP',
        email='user@example.com',
    )
except NotifiedByConfigError:
    # Missing API key in Django settings
    print("Check your NOTIFIEDBY_API_KEY setting")
except NotifiedByValidationError as e:
    # Bad request (400) - e.g. flow not found, already subscribed
    print(f"Validation error: {e}")
except NotifiedByAuthError:
    # Authentication failed (401/403)
    print("Invalid API key or feature not enabled")
except NotifiedByNotFoundError:
    # Resource not found (404)
    print("Not found")
except NotifiedByAPIError as e:
    # Other API error
    print(f"API error ({e.status_code}): {e}")
except NotifiedByError:
    # Network or other error
    print("Something went wrong")

The exception hierarchy:

  • NotifiedByError – Base exception for all errors.
    • NotifiedByConfigError – Missing or invalid configuration (e.g. no API key).

    • NotifiedByAPIError – An error response from the API.
      • NotifiedByValidationError – HTTP 400 (bad request).

      • NotifiedByAuthError – HTTP 401 or 403 (authentication/authorisation failure).

      • NotifiedByNotFoundError – HTTP 404 (resource not found).

Using a Custom Client

By default, all functions create a NotifiedByClient that reads your API key from Django settings. You can pass a custom client if you need to use a different API key or base URL (useful for testing or multi-tenant setups).

from notifiedby import NotifiedByClient, subscribe_to_flow

client = NotifiedByClient(
    api_key='your-other-api-key',
    base_url='http://localhost:8000'
)

subscribe_to_flow(
    flow_trigger='WELCOME_SIGNUP',
    email='test@example.com',
    client=client
)

All flow, recipient, and flag functions accept an optional client parameter.

Complete Example

Here is a complete example showing a typical integration – subscribing users on signup, managing flags when they upgrade, and unsubscribing when they cancel.

from notifiedby import (
    subscribe_to_flow,
    unsubscribe_from_flow,
    set_recipient_flags,
    clear_recipient_flags,
)

# When a user signs up
def on_user_signup(user):
    subscribe_to_flow(
        flow_trigger='WELCOME_SIGNUP',
        email=user.email,
        first_name=user.first_name,
        last_name=user.last_name,
        flags=['free_plan'],
    )

# When a user upgrades to premium
def on_user_upgrade(user):
    set_recipient_flags(email=user.email, flags=['premium'])
    clear_recipient_flags(email=user.email, flags=['free_plan'])
    subscribe_to_flow(
        flow_trigger='PREMIUM_ONBOARDING',
        email=user.email,
    )

# When a user cancels
def on_user_cancel(user):
    unsubscribe_from_flow(
        flow_trigger='PREMIUM_ONBOARDING',
        email=user.email,
    )
    subscribe_to_flow(
        flow_trigger='REENGAGE_INACTIVE',
        email=user.email,
    )