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.2.1.tar.gz (86.7 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.2.1-py3-none-any.whl (67.9 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: sed_sh-0.2.1.tar.gz
  • Upload date:
  • Size: 86.7 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.2.1.tar.gz
Algorithm Hash digest
SHA256 6723bf66417976e10a53dc1081e7b18f261750445b044b010fbf8a1d59a0e453
MD5 c077847f805f7ca27f0b40a9d2a6b16a
BLAKE2b-256 210d4c1d698c29b6cd5eb728c6975841eb87524c40ed8c0774410c210584253e

See more details on using hashes here.

File details

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

File metadata

  • Download URL: sed_sh-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 67.9 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.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 34863b0fd1ddefb37dd654d33b8b04c9c790b4c5bb53fe4e7d7cf53fa03c450b
MD5 087026edca30fd0997237eceb5a19632
BLAKE2b-256 3a8977d468ce52f9d912d642056ee380aa722091c0fc54441efe8834ce4b5a4a

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