Skip to main content

Official Python SDK for sed.sh API - URL shortening, malware scanning, disposable email, mock APIs, and PDF reports

Project description

sed.sh Python SDK

Official Python client library for sed.sh API - providing URL shortening, malware scanning, disposable email, mock APIs, and PDF report generation.

PyPI version Python Versions License: MIT

Features

  • Links: Create, manage, and track shortened URLs with optional password protection
  • Malware Scanner: Scan files for malware using AWS GuardDuty
  • Disposable Inbox: Create temporary email addresses for testing
  • Mock APIs: Create mock HTTP endpoints for testing and development
  • PDF Reports: Generate PDF documents from HTML templates with JSON data
  • Both Sync and Async: Full support for synchronous and asynchronous operations
  • CLI Tool: Command-line interface for all services
  • Type Hints: Full typing support for better IDE autocomplete
  • 🆕 Mailosaur Compatibility: Drop-in replacement for Mailosaur SDK - migrate by just changing imports!

Installation

pip install sed-sh

Quick Start

Synchronous Usage

from sed_sh import SedSH

# Initialize client with API key
client = SedSH(api_key="your_api_key_here")

# Create a short link
link = client.links.create("https://example.com/very/long/url")
print(f"Short URL: {link['shortUrl']}")

# Scan a file for malware
scan = client.malware.scan_file("/path/to/file.pdf")
print(f"Scan status: {scan['status']}")

# Create a disposable inbox
inbox = client.inbox.create()
print(f"Email address: {inbox['email']}")

# Create a mock API endpoint
endpoint = client.routes.create_endpoint(
    name="Test API",
    method="POST",
    path="/api/test",
    response_status=200,
    response_body='{"success": true}'
)
print(f"Mock URL: {endpoint['url']}")

# Generate a PDF from template
template = client.reports.create_template(
    name="Invoice",
    html="<h1>Invoice for {{customer}}</h1>"
)
pdf = client.reports.generate_pdf(
    template['templateId'],
    {"customer": "John Doe"}
)
print(f"PDF URL: {pdf['downloadUrl']}")

Asynchronous Usage

import asyncio
from sed_sh import AsyncSedSH

async def main():
    # Initialize async client
    client = AsyncSedSH(api_key="your_api_key_here")

    # Create a short link
    link = await client.links.create("https://example.com")
    print(f"Short URL: {link['shortUrl']}")

    # Scan a file
    scan = await client.malware.scan_file("/path/to/file.pdf")
    print(f"Scan status: {scan['status']}")

    # Close the session when done
    await client.close()

asyncio.run(main())

Using Context Managers

# Sync context manager
with SedSH(api_key="your_api_key") as client:
    link = client.links.create("https://example.com")
    print(link['shortUrl'])

# Async context manager
async with AsyncSedSH(api_key="your_api_key") as client:
    link = await client.links.create("https://example.com")
    print(link['shortUrl'])

Authentication

The SDK supports multiple authentication methods:

1. Constructor Parameter

client = SedSH(api_key="your_api_key")

2. Environment Variable

export SEDSH_API_KEY="your_api_key"
client = SedSH()  # Automatically uses SEDSH_API_KEY

3. Config File

Create ~/.sedsh/config.json:

{
  "api_key": "your_api_key",
  "base_url": "https://api.sed.sh"
}
client = SedSH()  # Automatically loads from config file

CLI Usage

The SDK includes a command-line interface:

# Set API key
export SEDSH_API_KEY="your_api_key"

# Links
sedsh links create https://example.com
sedsh links create https://example.com --password secret123
sedsh links list
sedsh links delete abc12

# Malware
sedsh malware scan /path/to/file.pdf

# Inbox
sedsh inbox create
sedsh inbox list
sedsh inbox messages <inbox-code>
sedsh inbox delete <inbox-code>

# Routes
sedsh routes create "Test API" POST /api/test --status 200 --body '{"ok": true}'
sedsh routes list
sedsh routes delete <endpoint-id>

# Reports
sedsh reports create-template "Invoice" /path/to/template.html
sedsh reports generate <template-id> '{"customer": "John"}'
sedsh reports list-templates

API Reference

Links Service

# Create a link
link = client.links.create(
    target_url="https://example.com",
    password="optional_password"  # Optional
)

# List all links
links = client.links.list()

# Delete a link
client.links.delete(code="abc12")

Malware Service

# Scan a file
scan = client.malware.scan_file(
    file_path="/path/to/file.pdf"
)
# Returns: {'scanId': '...', 'status': 'pending', 'fileName': '...'}

# Note: Scan results are sent via email notification

Inbox Service

# Create an inbox
inbox = client.inbox.create()

# List all inboxes
inboxes = client.inbox.list()

# Get messages for an inbox
messages = client.inbox.get_messages(inbox_code="inbox_123")

# Get a specific message
message = client.inbox.get_message(
    inbox_code="inbox_123",
    message_id="msg_456"
)

# Delete a message
client.inbox.delete_message(
    inbox_code="inbox_123",
    message_id="msg_456"
)

# Delete an inbox
client.inbox.delete(inbox_code="inbox_123")

Routes Service

# Create a mock endpoint
endpoint = client.routes.create_endpoint(
    name="User API",
    method="POST",
    path="/api/users",
    response_status=200,
    response_body='{"success": true}',
    response_headers={"Content-Type": "application/json"},  # Optional
    response_delay=0,  # Optional, milliseconds
    enabled=True  # Optional
)

# Create a forward endpoint (proxy mode)
endpoint = client.routes.create_endpoint(
    name="Proxy API",
    method="GET",
    path="/api/proxy",
    forward_mode=True,
    forward_url="https://api.example.com/endpoint"
)

# List endpoints
endpoints = client.routes.list_endpoints()

# Update an endpoint
updated = client.routes.update_endpoint(
    endpoint_id="endpoint_123",
    name="Updated API",
    response_status=201
)

# Toggle endpoint enabled/disabled
client.routes.toggle_endpoint(
    endpoint_id="endpoint_123",
    enabled=False
)

# Get requests received by endpoints
requests = client.routes.get_requests()

# Get details of a specific request
request_details = client.routes.get_request(request_id="req_123")

# Delete an endpoint
client.routes.delete_endpoint(endpoint_id="endpoint_123")

Reports Service

# Create a template
template = client.reports.create_template(
    name="Invoice Template",
    html="<h1>Invoice #{{invoice_number}}</h1>",
    expiry_hours=24  # Optional, max 24
)

# List templates
templates = client.reports.list_templates()

# Get template HTML
html = client.reports.get_template(template_id="tpl_123")

# Generate PDF from template
pdf = client.reports.generate_pdf(
    template_id="tpl_123",
    data={
        "invoice_number": "INV-001",
        "customer": "John Doe",
        "amount": "$100.00"
    }
)
# Returns: {'downloadUrl': '...', 'generationId': '...', 'expiresAt': ...}

# List recent PDF generations
generations = client.reports.list_generations()

# Delete a template
client.reports.delete_template(template_id="tpl_123")

Error Handling

from sed_sh import SedSH
from sed_sh.exceptions import (
    SedSHError,
    AuthenticationError,
    RateLimitError,
    ResourceNotFoundError,
    InvalidRequestError,
)

client = SedSH(api_key="your_api_key")

try:
    link = client.links.create("https://example.com")
except AuthenticationError as e:
    print(f"Invalid API key: {e}")
except RateLimitError as e:
    print(f"Rate limit exceeded: {e}")
except ResourceNotFoundError as e:
    print(f"Resource not found: {e}")
except InvalidRequestError as e:
    print(f"Invalid request: {e}")
except SedSHError as e:
    print(f"API error: {e}")

Important Notes

⚠️ This SDK does NOT include automatic retries or request timeouts. You should implement these in your application if needed:

# Example: Manual retry logic
from time import sleep

def create_link_with_retry(client, url, max_retries=3):
    for attempt in range(max_retries):
        try:
            return client.links.create(url)
        except SedSHError as e:
            if attempt == max_retries - 1:
                raise
            sleep(2 ** attempt)  # Exponential backoff

⚠️ This SDK does NOT perform client-side input validation. Invalid inputs will be caught by the API and return appropriate errors.

Configuration Options

client = SedSH(
    api_key="your_api_key",          # API key (required if not in env/config)
    base_url="https://api.sed.sh",   # API base URL (optional)
    timeout=30,                       # Request timeout in seconds (optional)
)

Development

# Clone the repository
git clone https://github.com/triellocom/sed-sh-sdk.git
cd sed-sh-sdk/python

# Install in development mode
pip install -e ".[dev]"

# Run tests
pytest

# Format code
black sed_sh/

# Type checking
mypy sed_sh/

Mailosaur Compatibility Adapter

Migrating from Mailosaur? The sed.sh SDK includes a drop-in replacement adapter that allows you to migrate with minimal code changes.

Quick Migration (30 seconds)

# BEFORE: Using Mailosaur
# from mailosaur import MailosaurClient
# from mailosaur.models import SearchCriteria

# AFTER: Using sed.sh (just change the import!)
from sed_sh.adapters.mailosaur import MailosaurClient, SearchCriteria

# Everything else stays the same!
mailosaur = MailosaurClient(api_key=os.environ['SEDSH_API_KEY'])

# Generate test email
test_email = mailosaur.servers.generate_email_address()

# Wait for email
criteria = SearchCriteria()
criteria.sent_to = test_email

server_id = test_email.split('@')[0]
message = mailosaur.messages.get(server_id, criteria, timeout=30000)

# Extract verification link
if message['html']['links']:
    verify_link = message['html']['links'][0]['href']
    print(f"Verification link: {verify_link}")

# Extract OTP code
if message['text']['codes']:
    otp = message['text']['codes'][0]
    print(f"OTP: {otp}")

What Changed

  • ✅ Import statement: from sed_sh.adapters.mailosaur import ...
  • ✅ API key: Use SEDSH_API_KEY instead of MAILOSAUR_API_KEY
  • ✅ Email generation: Use generate_email_address() (no wildcard domain)

What Stayed the Same

  • ✅ All API methods: messages.get(), servers.list(), etc.
  • SearchCriteria usage
  • ✅ Message structure and data access
  • ✅ Your test logic

Complete Migration Guide

See MAILOSAUR_MIGRATION.md for:

  • Complete before/after examples
  • API compatibility matrix
  • Pytest integration patterns
  • Troubleshooting guide
  • Migration example script

Examples

See the examples/ directory for complete examples:

  • links_sync.py - Synchronous link management
  • links_async.py - Asynchronous link management
  • malware_sync.py - File scanning
  • inbox_sync.py - Disposable email management
  • routes_sync.py - Mock API endpoint creation
  • reports_sync.py - PDF generation
  • mailosaur_migration_example.py - NEW: Mailosaur compatibility demonstration

Requirements

  • Python 3.8 or higher
  • requests >= 2.25.0
  • aiohttp >= 3.8.0
  • click >= 8.0.0

License

MIT License - see LICENSE file for details.

Support

Links

Testing

The SDK includes a comprehensive test suite using pytest.

Running Tests

# Install development dependencies
pip install -e .[dev]

# Run all tests
make test

# Run with coverage
make test-cov

# Run integration tests (requires API key)
export SEDSH_API_KEY="your-api-key"
make test-integration

Test Structure

  • tests/test_exceptions.py - Exception handling tests
  • tests/test_client.py - Client initialization tests
  • tests/test_services_integration.py - API integration tests

See README_TESTING.md for detailed testing documentation.

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

sed_sh-0.7.0.tar.gz (87.4 kB view details)

Uploaded Source

Built Distribution

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

sed_sh-0.7.0-py3-none-any.whl (70.3 kB view details)

Uploaded Python 3

File details

Details for the file sed_sh-0.7.0.tar.gz.

File metadata

  • Download URL: sed_sh-0.7.0.tar.gz
  • Upload date:
  • Size: 87.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for sed_sh-0.7.0.tar.gz
Algorithm Hash digest
SHA256 24cf488d26d8dfeb583b72a8e9379265effd52fe2543c950285ead7d4bb4382b
MD5 f5087d3d065cc99c5ff2bda902f3c1e5
BLAKE2b-256 424642f5e02a94bcb74eeecff06727aa125f7a60838dcc75a3393aa3bcb7b94b

See more details on using hashes here.

File details

Details for the file sed_sh-0.7.0-py3-none-any.whl.

File metadata

  • Download URL: sed_sh-0.7.0-py3-none-any.whl
  • Upload date:
  • Size: 70.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for sed_sh-0.7.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7a425cd161974a67111547fbe8ab7ac792df2f11f3e57dc5d64b2585887d0957
MD5 762a6c45c4e7afdb54337b072e0f571d
BLAKE2b-256 5ac83984d6965536b4a3a327630028ffd017dd1c36ff120df9e2949b145b2aef

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