Skip to main content

Python SDK for the Universal Ads Third Party API

Project description

Universal Ads SDK

A Python SDK for interacting with the Universal Ads Third Party API. This SDK provides a simple and intuitive interface for managing campaigns, ad sets, ads, creatives, pixels, media uploads, custom audiences, and performance reports.

Features

  • Creative Management: Create, read, update, and delete creatives
  • Campaign, Ad Set, and Ad Management: List, create, get, and update campaign resources
  • Pixel Access: List pixels, get pixel details, and retrieve pixel events
  • Media Upload: Upload and verify media files
  • Audience Management: Create and manage custom audiences for targeted advertising
  • Reports: Access campaign, adset, and ad performance data
  • Automatic Retries: Built-in retry logic for robust API interactions
  • Type Hints: Full type annotation support for better development experience

Installation

pip install universal-ads-sdk

Quick Start

1. Initialize the Client

from universal_ads_sdk import UniversalAdsClient

# Initialize the client with your API credentials
client = UniversalAdsClient(
    api_key="your-api-key",
    private_key_pem="""-----BEGIN PRIVATE KEY-----
your-private-key-content
-----END PRIVATE KEY-----"""
)

2. Upload Media

# Upload a media file (using new API format)
upload_info = client.upload_media(
    mime_type="image/jpeg",
    adaccount_id="3d49e08c-465d-4673-a445-d4ba3575f032",
    name="my-image.jpg"
)

# Use the presigned URL to upload your file
import requests
with open("/path/to/your/image.jpg", "rb") as f:
    requests.put(upload_info["upload_url"], data=f)

# Verify the upload
media = client.verify_media(upload_info["id"])
print(f"Media verified: {media['status']}")

# Get media information
media_info = client.get_media(upload_info["id"])
print(f"Media filename: {media_info['filename']}")

3. Create a Creative

# Create a new creative
creative = client.create_creative(
    adaccount_id="3d49e08c-465d-4673-a445-d4ba3575f032",
    name="My Creative",
    media_id="cc0f46c7-d9b9-4758-9479-17e1d77c5eea"
)
print(f"Created creative: {creative['id']}")

4. Create a Custom Audience

# Option 1: Create audience with uploaded media file
# First, upload a CSV or TXT file containing user identifiers (one per row)
upload_info = client.upload_media(
    mime_type="text/csv",
    adaccount_id="3d49e08c-465d-4673-a445-d4ba3575f032",
    name="users.csv"
)

# Upload the file to the presigned URL
import requests
with open("/path/to/users.csv", "rb") as f:
    requests.put(upload_info["upload_url"], data=f)

# Verify the upload
media = client.verify_media(upload_info["id"])

# Create a new custom audience using the uploaded media
audience = client.create_audience(
    adaccount_id="3d49e08c-465d-4673-a445-d4ba3575f032",
    name="My Custom Audience",
    segment_type="email",
    media_id=upload_info["id"],
    description="An audience for targeted advertising"
)
print(f"Created audience: {audience['id']}")

# Option 2: Create audience with users list directly (max 10,000 users)
audience = client.create_audience(
    adaccount_id="3d49e08c-465d-4673-a445-d4ba3575f032",
    name="My Custom Audience",
    segment_type="email",
    users=["user@example.com", "another@example.com"],
    description="An audience created with user list"
)

# Add or remove users from an existing audience
client.update_audience_users(
    audience_id=audience["id"],
    users=["user@example.com", "another@example.com"],
    remove=False
)

5. Get Performance Reports

# Get campaign performance report
report = client.get_campaign_report(
    adaccount_id="3d49e08c-465d-4673-a445-d4ba3575f032",
    start_date="2024-01-01T00:00:00",
    end_date="2024-01-31T23:59:59",
    date_aggregation="DAY",
    attribution_window="7_day"
)
print(f"Report contains {len(report['data'])} campaigns")

# Schedule an advanced report for asynchronous processing
scheduled_report = client.schedule_report(
    start_date="2024-01-01T00:00:00",
    end_date="2024-01-31T23:59:59",
    entity_level="campaign",
    adaccount_ids=["3d49e08c-465d-4673-a445-d4ba3575f032"],
    dimensions=["state", "dma"],
    time_aggregation="day"
)
print(f"Scheduled report ID: {scheduled_report['scheduled_report_id']}")

# Check scheduled report status
report_status = client.get_scheduled_report(scheduled_report['scheduled_report_id'])
print(f"Report status: {report_status['status']}")

6. Get Organizations and Ad Accounts

# Get all organizations
organizations = client.get_organizations(limit=50)
print(f"Found {len(organizations['data'])} organizations")

# Get all ad accounts
adaccounts = client.get_adaccounts(limit=50)
print(f"Found {len(adaccounts['data'])} ad accounts")

API Reference

Client Initialization

UniversalAdsClient(
    api_key: str,                    # Your API key
    private_key_pem: str,            # Your private key in PEM format
    base_url: Optional[str] = None,  # API base URL (defaults to production)
    timeout: int = 30,               # Request timeout in seconds
    max_retries: int = 3,            # Maximum retry attempts
    headers: Optional[Dict[str, str]] = None  # Optional headers added to every request
)

Creative Management

Get All Creatives

creatives = client.get_creatives(
    adaccount_id="account-id",  # Optional: filter by account
    campaign_id="campaign-id",  # Optional: filter by campaign
    adset_id="adset-id",        # Optional: filter by adset
    ad_id="ad-id",              # Optional: filter by ad
    limit=50,                    # Optional: limit results
    offset=0,                    # Optional: pagination offset
    sort="name_asc"              # Optional: sort order
)

Get Specific Creative

creative = client.get_creative("creative-id")

Create Creative

creative = client.create_creative(
    adaccount_id="account-id",
    name="Creative Name",
    media_id="media-id"
)

Update Creative

creative = client.update_creative(
    "creative-id",
    name="New Name"
)

Delete Creative

client.delete_creative("creative-id")

Media Management

Upload Media

# New API format
upload_info = client.upload_media(
    mime_type="image/jpeg",
    adaccount_id="account-id",
    name="my-image.jpg"
)

Get Media

media = client.get_media("media-id")

Verify Media

media = client.verify_media("media-id")

Reporting

Campaign Report

report = client.get_campaign_report(
    adaccount_id="account-id",      # Required
    start_date="2024-01-01T00:00:00",  # Optional (YYYY-MM-DDTHH:MM:SS)
    end_date="2024-01-31T23:59:59",    # Optional (YYYY-MM-DDTHH:MM:SS)
    campaign_ids=["id1", "id2"],   # Optional
    adset_ids=["id1", "id2"],       # Optional
    ad_ids=["id1", "id2"],          # Optional
    date_aggregation="DAY",         # Optional: HOUR, DAY, LIFETIME, TOTAL
    attribution_window="7_day",     # Optional: 7_day, 14_day, 30_day
    limit=100,                      # Optional
    offset=0                        # Optional
)

Adset Report

report = client.get_adset_report(
    adaccount_id="account-id",      # Required
    start_date="2024-01-01T00:00:00",  # Optional (YYYY-MM-DDTHH:MM:SS)
    end_date="2024-01-31T23:59:59",    # Optional (YYYY-MM-DDTHH:MM:SS)
    campaign_ids=["id1", "id2"],   # Optional
    adset_ids=["id1", "id2"],       # Optional
    ad_ids=["id1", "id2"],          # Optional
    date_aggregation="DAY",          # Optional: HOUR, DAY, LIFETIME, TOTAL
    attribution_window="7_day",      # Optional: 7_day, 14_day, 30_day
    limit=100,                       # Optional
    offset=0                         # Optional
)

Ad Report

report = client.get_ad_report(
    adaccount_id="account-id",      # Required
    start_date="2024-01-01T00:00:00",  # Optional (YYYY-MM-DDTHH:MM:SS)
    end_date="2024-01-31T23:59:59",    # Optional (YYYY-MM-DDTHH:MM:SS)
    campaign_ids=["id1", "id2"],   # Optional
    adset_ids=["id1", "id2"],       # Optional
    ad_ids=["id1", "id2"],          # Optional
    date_aggregation="DAY",          # Optional: HOUR, DAY, LIFETIME, TOTAL
    attribution_window="7_day",     # Optional: 7_day, 14_day, 30_day
    limit=100,                       # Optional
    offset=0                         # Optional
)

Schedule Report

scheduled_report = client.schedule_report(
    start_date="2024-01-01T00:00:00",
    end_date="2024-01-31T23:59:59",
    entity_level="campaign",         # campaign, adset, or ad
    adaccount_ids=["account-id"],
    campaign_ids=["id1", "id2"],    # Optional
    adset_ids=["id1", "id2"],       # Optional
    ad_ids=["id1", "id2"],          # Optional
    dimensions=["state", "dma"],     # Optional: device_type, dma, state, zip_code
    time_aggregation="day",          # Optional: hour, day, or total
    attribution_window="7_day",      # Optional: 7_day, 14_day, 30_day
    limit=50000                      # Optional, default: 100000
)

Get Scheduled Report

report_status = client.get_scheduled_report("scheduled-report-id")

Campaign Management

Get All Campaigns

campaigns = client.get_campaigns(
    adaccount_id="account-id",             # Required
    campaign_ids=["campaign-1"],           # Optional: filter by campaign IDs
    name="Spring Campaign",                # Optional
    status=["active", "paused"],           # Optional: single string also accepted
    campaign_type="performance",           # Optional: performance, content_select
    include_archived=False,                # Optional
    limit=50,                              # Optional
    offset=0,                              # Optional
    sort="id_asc"                          # Optional
)

Create / Update Campaign

campaign = client.create_campaign(
    adaccount_id="account-id",
    name="Spring Campaign",
    objective="web_conversions"
)

updated = client.update_campaign(campaign["id"], name="Spring Campaign v2")

Ad Set Management

Get All Ad Sets

adsets = client.get_adsets(
    adaccount_id="account-id",             # Required
    campaign_ids=["campaign-id"],          # Optional
    adset_ids=["adset-id"],                # Optional
    name="Adults 25-44",                   # Optional
    status=["active", "paused"],           # Optional
    include_archived=False,                # Optional
    limit=50,                              # Optional
    offset=0,                              # Optional
    sort="id_asc"                          # Optional
)

Create / Update Ad Set

adset = client.create_adset(
    adaccount_id="account-id",
    campaign_id="campaign-id",
    name="Adults 25-44"
)

updated = client.update_adset(adset["id"], name="Adults 25-54")

Ad Management

Get All Ads

ads = client.get_ads(
    adaccount_id="account-id",             # Required
    campaign_ids=["campaign-id"],          # Optional
    adset_ids=["adset-id"],                # Optional
    ad_ids=["ad-id"],                      # Optional
    status=["active", "paused"],           # Optional
    include_archived=False,                # Optional
    limit=50,                              # Optional
    offset=0                               # Optional
)

Create / Update Ad

ad = client.create_ad(
    adaccount_id="account-id",
    adset_id="adset-id",
    creative_id="creative-id",
    name="Homepage Hero Ad"
)

updated = client.update_ad(ad["id"], name="Homepage Hero Ad v2")

Pixel Endpoints

Get Pixels

pixels = client.get_pixels(
    adaccount_id="account-id",  # Required
    limit=50,                   # Optional
    offset=0                    # Optional
)
pixel = client.get_pixel("pixel-id")
events = client.get_pixel_events("pixel-id", limit=100, offset=0)

Audience Management

Audience File Format Requirements

When creating or updating audiences with media_id, you need to upload a media file containing user data. The file must meet these requirements:

  • File Format: CSV or TXT files only
  • Structure: Single column format (one identifier per row)
  • Encoding: UTF-8 encoding
  • File Size: Maximum 25MB
  • Content:
    • For email audiences: Each row must contain a valid email address
    • For other audience types: Each row contains a single identifier (e.g., IP address, Blockgraph ID, Experian LUID, Liveramp ID)

Example CSV file for email audiences:

user1@example.com
user2@example.com
user3@example.com

Example TXT file for email audiences:

user1@example.com
user2@example.com
user3@example.com

Upload Process:

  1. Upload your file using the upload_media() method to get a media_id
  2. Use the media_id when creating an audience or updating audience users
  3. The file will be validated automatically

Get All Audiences

audiences = client.get_audiences(
    adaccount_id="account-id",       # Required
    name="Audience Name",            # Optional: filter by name
    status="active",                 # Optional: filter by status
    limit=50,                        # Optional: limit results
    offset=0,                        # Optional: pagination offset
    sort="name_asc"                  # Optional: sort order
)

Get Specific Audience

audience = client.get_audience("audience-id")

Create Audience

# Option 1: Create audience with media file
# Note: media_id must reference a CSV or TXT file uploaded via upload_media()
# The file must contain one identifier per row (see Audience File Format Requirements above)
audience = client.create_audience(
    adaccount_id="account-id",
    name="Audience Name",
    segment_type="email",              # email, ctv, ip_address, mobile_ad_id, etc.
    media_id="media-id",                # From upload_media() response
    description="Optional description", # Optional
)

# Option 2: Create audience with users list (max 10,000 users)
audience = client.create_audience(
    adaccount_id="account-id",
    name="Audience Name",
    segment_type="email",
    users=["user1@example.com", "user2@example.com"],
    description="Optional description"  # Optional
)

Update Audience

audience = client.update_audience(
    "audience-id",
    name="Updated Audience Name",
    description="Updated description"
)

Update Audience Users

# Add users to an audience
client.update_audience_users(
    audience_id="audience-id",
    users=["user1@example.com", "user2@example.com"],
    remove=False  # Set to True to remove users instead
)

# Remove users from an audience
client.update_audience_users(
    audience_id="audience-id",
    users=["user1@example.com"],
    remove=True
)

# Update audience users using uploaded media
client.update_audience_users(
    audience_id="audience-id",
    media_id="new-media-id",
    remove=False
)

Delete Audience

client.delete_audience("audience-id")

Me Endpoints

Get Organizations

organizations = client.get_organizations(
    limit=50,    # Optional: limit results (default: 10, max: 100)
    offset=0     # Optional: pagination offset (default: 0)
)

Get Ad Accounts

adaccounts = client.get_adaccounts(
    limit=50,                                      # Optional: limit results (default: 10, max: 100)
    offset=0,                                      # Optional: pagination offset (default: 0)
    organization_ids=["org-id-1", "org-id-2"],    # Optional: repeatable organization_id query filters
    authorization_statuses=["authorized"]          # Optional: authorized, not_authorized
)

Error Handling

The SDK provides specific exception types for different error scenarios:

from universal_ads_sdk import UniversalAdsError, AuthenticationError, APIError

try:
    creative = client.create_creative(...)
except AuthenticationError as e:
    print(f"Authentication failed: {e}")
except APIError as e:
    print(f"API error {e.status_code}: {e}")
    print(f"Response data: {e.response_data}")
except UniversalAdsError as e:
    print(f"SDK error: {e}")

Configuration

Environment Variables

You can also initialize the client using environment variables:

import os
from universal_ads_sdk import UniversalAdsClient

client = UniversalAdsClient(
    api_key=os.getenv("UNIVERSAL_ADS_API_KEY"),
    private_key_pem=os.getenv("UNIVERSAL_ADS_PRIVATE_KEY")
)

Custom Base URL

For testing or development, you can use a custom base URL:

client = UniversalAdsClient(
    api_key="your-api-key",
    private_key_pem="your-private-key",
    base_url="https://staging-api.universalads.com/v1"
)

Authentication

The SDK uses request signing for secure API access. Each request is signed with your private key and includes:

Requirements

  • Python 3.8+
  • requests >= 2.25.0
  • cryptography >= 3.4.0
  • urllib3 >= 1.26.0

Security

API Credentials

  • Never commit API credentials to version control
  • Use environment variables for production deployments
  • Test files with credentials are excluded from git via .gitignore

Environment Variables (Recommended)

export UNIVERSAL_ADS_API_KEY="your-api-key"
export UNIVERSAL_ADS_PRIVATE_KEY="your-private-key-pem"
import os
from universal_ads_sdk import UniversalAdsClient

client = UniversalAdsClient(
    api_key=os.getenv("UNIVERSAL_ADS_API_KEY"),
    private_key_pem=os.getenv("UNIVERSAL_ADS_PRIVATE_KEY")
)

Development

Running Tests

The SDK includes test templates in the tests/ directory. For security, use environment variables:

# Set up environment variables
cp env.template .env
# Edit .env with your credentials
pip install python-dotenv  # Optional, for better .env support

# Quick test (basic validation)
python tests/test_template.py

# Comprehensive test (all endpoints)
python tests/comprehensive_test.py

See tests/README.md for detailed testing information.

For development testing with pytest:

pip install -e ".[dev]"
pytest

Code Formatting

black universal_ads_sdk/
flake8 universal_ads_sdk/

Support

License

This project is licensed under the MIT License - see the LICENSE file for details.

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

universal_ads_sdk-2.1.2.tar.gz (27.2 kB view details)

Uploaded Source

Built Distribution

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

universal_ads_sdk-2.1.2-py3-none-any.whl (25.3 kB view details)

Uploaded Python 3

File details

Details for the file universal_ads_sdk-2.1.2.tar.gz.

File metadata

  • Download URL: universal_ads_sdk-2.1.2.tar.gz
  • Upload date:
  • Size: 27.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.4

File hashes

Hashes for universal_ads_sdk-2.1.2.tar.gz
Algorithm Hash digest
SHA256 e5ff3cbfc68d9130b4578d39c0dc9a6e570232a20628313060190b24ecf6b0b4
MD5 ec6b5492e021be32db2e7fad9fe9fb26
BLAKE2b-256 8d63c2e345714677a0975fbe770d6454fe4aa9d64c7a9f0d412683815a7888a4

See more details on using hashes here.

File details

Details for the file universal_ads_sdk-2.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for universal_ads_sdk-2.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 9bb5d1e6b7f4b086929a07482d1da595277ad1059e31843f7505f81c28759017
MD5 3fb84d3a57f7f74eceda160ed0ab5015
BLAKE2b-256 f0525b397ee92b8429a9611f8b3a99ba543acc197cbf18aecbb9f1389669c7c0

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