Skip to main content

Python client for Salesforce Marketing Cloud (SFMC) API

Project description

pysfmc

A modern, type-safe Python client library for Salesforce Marketing Cloud (SFMC) API.

Features

  • 🔄 Sync & Async: Full support for both synchronous and asynchronous operations
  • 🔐 Auto Authentication: Automatic OAuth2 token management with refresh
  • 📝 Type Safety: Comprehensive Pydantic models for request/response validation
  • 🚀 Modern: Built with httpx, supports Python 3.10+
  • ⚡ Rate Limiting: Built-in rate limiting and error handling
  • 🎯 Assets API: Complete support for Content Builder (Categories, Query, Content)

Implemented endpoints

As of right now, only parts of the Content Builder REST API is implemented:

HTTP Method Resource Description Supported
GET /asset/v1/content/assets Gets an asset collection with filtering and pagination.
GET /asset/v1/content/assets/{id} Gets an asset by ID.
POST /asset/v1/content/assets Inserts an asset.
PUT /asset/v1/content/assets/{id} Updates a full asset.
PATCH /asset/v1/content/assets/{id} Updates part of an asset deleted in the last 30 days.
DELETE /asset/v1/content/assets/{id} Deletes an asset.
GET /asset/v1/content/assets/{id}/file Gets the binary file for an asset.
GET /asset/v1/content/assets/salutations Gets the default header and footer for an account.
GET /asset/v1/content/assets/{id}/salutations Gets the header and footer for a message.
GET /asset/v1/content/assets/{id}/channelviews/{viewname} Returns the requested channel view's compiled HTML for the asset.
POST /asset/v1/content/categories Inserts a category.
GET /asset/v1/content/categories Gets a collection of categories.
GET /asset/v1/content/categories/{id} Gets a category by ID.
PUT /asset/v1/content/categories/{id} Updates a category by ID.
DELETE /asset/v1/content/categories/{id} Deletes a category by ID.

Installation

Install using uv (recommended):

uv add pysfmc

Or with pip:

pip install pysfmc

Quick Start

1. Environment Setup

Create a .env file in your project root:

cp .env.example .env

Configure your SFMC credentials:

SFMC_CLIENT_ID=your_client_id
SFMC_CLIENT_SECRET=your_client_secret
SFMC_ACCOUNT_ID=your_account_id
SFMC_SUBDOMAIN=your_subdomain

2. Basic Usage

from pysfmc import SFMCClient
from dotenv import load_dotenv

# Load environment variables
load_dotenv()

# Synchronous client
with SFMCClient() as client:
    # Get categories
    categories = client.assets.categories.get_categories(page_size=10)
    print(f"Found {categories.count} categories")

    for category in categories.items:
        print(f"- {category.name} (ID: {category.id})")

3. Async Usage

import asyncio
from pysfmc import AsyncSFMCClient
from dotenv import load_dotenv

async def main():
    load_dotenv()

    async with AsyncSFMCClient() as client:
        # Query assets with filters
        assets = await client.assets.query.get_assets(
            filter_expr="Name like 'newsletter'",
            order_by="createdDate desc",
            page_size=5
        )

        print(f"Found {assets.count} matching assets")
        for asset in assets.items:
            print(f"- {asset.name} (Type: {asset.asset_type.name})")

if __name__ == "__main__":
    asyncio.run(main())

Core Features

Assets Categories API

Manage Content Builder categories (folders):

with SFMCClient() as client:
    # Get all categories with pagination
    categories = client.assets.categories.get_categories(
        page=1,
        page_size=20,
        order_by="name asc"
    )

    # Get specific category
    category = client.assets.categories.get_category_by_id(12345)

    # Create new category
    new_category = client.assets.categories.create_category(
        name="My New Folder",
        parent_id=4793,
        description="Created via pysfmc"
    )

    # Filter by parent (only supported filter)
    root_categories = client.assets.categories.get_categories(
        parent_id=0  # Root level categories
    )

Assets Query API

Search and filter assets with advanced queries:

with SFMCClient() as client:
    # Basic asset search
    assets = client.assets.query.get_assets(page_size=10)

    # Filter by name
    email_assets = client.assets.query.get_assets(
        filter_expr="Name like 'email'"
    )

    # Filter by asset type
    templates = client.assets.query.get_assets(
        filter_expr="assetType.name eq 'templatebasedemail'"
    )

    # Complex filtering with date ranges
    recent_assets = client.assets.query.get_assets(
        filter_expr="createdDate gte '2024-01-01'",
        order_by="createdDate desc",
        page_size=20
    )

    # Get specific fields only
    minimal_assets = client.assets.query.get_assets(
        fields="id,name,assetType,createdDate",
        page_size=50
    )

    # Get asset by ID
    asset = client.assets.query.get_asset_by_id(141754)
    print(f"Asset: {asset.name}")
    print(f"Type: {asset.asset_type.name}")
    print(f"Created: {asset.created_date}")

Advanced Async Operations

import asyncio
from pysfmc import AsyncSFMCClient

async def fetch_multiple_categories(client, category_ids):
    """Fetch multiple categories concurrently."""
    tasks = [
        client.assets.categories.get_category_by_id(cat_id)
        for cat_id in category_ids
    ]
    return await asyncio.gather(*tasks)

async def main():
    async with AsyncSFMCClient() as client:
        # Get category IDs
        categories = await client.assets.categories.get_categories(page_size=5)
        category_ids = [cat.id for cat in categories.items]

        # Fetch all categories concurrently
        detailed_categories = await fetch_multiple_categories(client, category_ids)

        for category in detailed_categories:
            print(f"Category: {category.name} (Enterprise: {category.enterprise_id})")

Error Handling

The library provides structured exception handling:

from pysfmc import SFMCClient
from pysfmc.exceptions import (
    SFMCAuthenticationError,
    SFMCRateLimitError,
    SFMCNotFoundError,
    SFMCServerError
)

with SFMCClient() as client:
    try:
        category = client.assets.categories.get_category_by_id(99999)
    except SFMCNotFoundError:
        print("Category not found")
    except SFMCAuthenticationError:
        print("Authentication failed - check credentials")
    except SFMCRateLimitError as e:
        print(f"Rate limited - retry after {e.retry_after} seconds")
    except SFMCServerError:
        print("SFMC server error - try again later")

Configuration

Environment Variables

All configuration uses the SFMC_ prefix:

# Required
SFMC_CLIENT_ID=your_app_client_id
SFMC_CLIENT_SECRET=your_app_client_secret
SFMC_ACCOUNT_ID=your_account_mid
SFMC_SUBDOMAIN=your_tenant_subdomain

# Optional
SFMC_CLIENT__TIMEOUT=30.0
SFMC_RATE_LIMIT__REQUESTS_PER_MINUTE=2500
SFMC_DEBUG=false

Programmatic Configuration

from pysfmc import SFMCClient, SFMCSettings

# Custom settings
settings = SFMCSettings(
    client_id="your_client_id",
    client_secret="your_client_secret",
    account_id="your_account_id",
    subdomain="your_subdomain"
)

with SFMCClient(settings=settings) as client:
    # Use client with custom settings
    pass

Development

Setup Development Environment

# Clone repository
git clone <repo-url>
cd pysfmc

# Install with development dependencies
uv sync --group dev

# Run tests
uv run pytest

Running Examples

# Set up environment
cp .env.example .env
# Edit .env with your credentials

The examples folder is there to answer your questions

Requirements

  • Python 3.9+

License

This project is licensed under the MIT License.

Support

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pysfmc-0.1.1.tar.gz (59.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pysfmc-0.1.1-py3-none-any.whl (22.0 kB view details)

Uploaded Python 3

File details

Details for the file pysfmc-0.1.1.tar.gz.

File metadata

  • Download URL: pysfmc-0.1.1.tar.gz
  • Upload date:
  • Size: 59.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.8.4

File hashes

Hashes for pysfmc-0.1.1.tar.gz
Algorithm Hash digest
SHA256 90444c389b4a869328665b101c0849b2ca3ee7e2598552f61bfe9590e6e5f3b1
MD5 79c51c84d9f160dfea3818b879a640d5
BLAKE2b-256 f3cbbc15d6ae10e36f20902ba4d841b289d39915911b8876624d34b8f4ac7c28

See more details on using hashes here.

File details

Details for the file pysfmc-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: pysfmc-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 22.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.8.4

File hashes

Hashes for pysfmc-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 4c5cc24dcedcba286fab6b08170b901fb87c393e0b2d0d6452bc4b67213f4ffc
MD5 97310462db8e18c6250760c4e20e279d
BLAKE2b-256 334ff18d474ed09714163d16c9e3835547b52d9259c33e81ee4935099dc77132

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page