Installation
Copy
pip install foxreach
Quick Start
Copy
from foxreach import FoxReach, LeadCreate
client = FoxReach(api_key="otr_your_api_key")
# Create a lead
lead = client.leads.create(LeadCreate(
email="[email protected]",
first_name="Jane",
last_name="Smith",
company="Acme Corp",
))
print(f"Created: {lead.id}")
# List leads
page = client.leads.list(search="jane", page_size=25)
for lead in page:
print(f"{lead.email} — {lead.company}")
# Check pagination info
print(f"Page {page.meta.page}/{page.meta.total_pages}, {page.meta.total} total")
client.close()
Configuration
Copy
client = FoxReach(
api_key="otr_...", # required
base_url="https://api.foxreach.io/api/v1", # default
timeout=30.0, # seconds, default
max_retries=3, # retries on 429, default
)
Copy
export FOXREACH_API_KEY=otr_your_api_key
Copy
import os
from foxreach import FoxReach
client = FoxReach(api_key=os.environ["FOXREACH_API_KEY"])
Resources
Leads
Copy
from foxreach import LeadCreate, LeadUpdate
# List with filters
page = client.leads.list(page=1, page_size=50, search="acme", status="active")
# Get by ID
lead = client.leads.get("cld_abc123")
# Create
lead = client.leads.create(LeadCreate(
email="[email protected]",
first_name="Jane",
company="Acme Corp",
tags=["enterprise"],
))
# Update
lead = client.leads.update("cld_abc123", LeadUpdate(company="New Corp"))
# Delete
client.leads.delete("cld_abc123")
Campaigns
Copy
from foxreach import CampaignCreate, CampaignUpdate
# List
page = client.campaigns.list(status="active")
# Create (starts in draft)
campaign = client.campaigns.create(CampaignCreate(
name="Q1 Outreach",
timezone="America/New_York",
daily_limit=50,
))
# Update
client.campaigns.update("cmp_xyz789", CampaignUpdate(daily_limit=100))
# Lifecycle
client.campaigns.start("cmp_xyz789")
client.campaigns.pause("cmp_xyz789")
# Add leads and accounts
client.campaigns.add_leads("cmp_xyz789", ["cld_1", "cld_2"])
client.campaigns.add_accounts("cmp_xyz789", ["acc_1"])
# Delete (must be draft)
client.campaigns.delete("cmp_xyz789")
Sequences
Copy
from foxreach import SequenceCreate, SequenceUpdate
# List steps for a campaign
steps = client.campaigns.sequences.list("cmp_xyz789")
# Add a step
step = client.campaigns.sequences.create("cmp_xyz789", SequenceCreate(
subject="Quick question about {{company}}",
body="Hi {{firstName}}, ...",
delay_days=0,
))
# Update
client.campaigns.sequences.update("cmp_xyz789", "seq_1", SequenceUpdate(delay_days=3))
# Delete
client.campaigns.sequences.delete("cmp_xyz789", "seq_1")
Templates
Copy
from foxreach import TemplateCreate, TemplateUpdate
page = client.templates.list()
template = client.templates.get("tpl_abc123")
template = client.templates.create(TemplateCreate(name="Cold Intro", body="Hi {{firstName}}"))
client.templates.update("tpl_abc123", TemplateUpdate(name="Updated name"))
client.templates.delete("tpl_abc123")
Email Accounts
Copy
page = client.email_accounts.list()
account = client.email_accounts.get("acc_abc123")
client.email_accounts.delete("acc_abc123")
Inbox
Copy
from foxreach import ThreadUpdate
# List unread threads
threads = client.inbox.list_threads(is_read=False, category="interested")
# Get a thread
thread = client.inbox.get("rpl_abc123")
# Mark as read and categorize
client.inbox.update("rpl_abc123", ThreadUpdate(is_read=True, category="interested"))
Analytics
Copy
# Dashboard overview
overview = client.analytics.overview()
print(f"Leads: {overview.total_leads}, Reply rate: {overview.reply_rate}%")
# Campaign stats with daily breakdown
stats = client.analytics.campaign("cmp_xyz789")
print(f"Sent: {stats.sent}, Replied: {stats.replied}")
for day in stats.daily_stats:
print(f" {day.date}: {day.sent} sent, {day.replied} replied")
Pagination
List endpoints returnPaginatedResponse objects:
Copy
page = client.leads.list(page=1, page_size=50)
# Iterate current page
for lead in page:
print(lead.email)
# Check pagination metadata
print(f"Page {page.meta.page}/{page.meta.total_pages}")
# Get next page
if page.has_next_page():
next_page = page.next_page()
# Auto-paginate through ALL results
for lead in client.leads.list(page_size=100).auto_paging_iter():
print(lead.email)
Async Support
All operations are available asynchronously viaAsyncFoxReach:
Copy
import asyncio
from foxreach import AsyncFoxReach, LeadCreate
async def main():
async with AsyncFoxReach(api_key="otr_your_api_key") as client:
# Create a lead
lead = await client.leads.create(LeadCreate(email="[email protected]"))
# Auto-paginate
async for lead in (await client.leads.list()).auto_paging_iter():
print(lead.email)
# Analytics
overview = await client.analytics.overview()
print(f"Total leads: {overview.total_leads}")
asyncio.run(main())
Error Handling
Copy
from foxreach import (
FoxReach,
FoxReachError,
AuthenticationError,
NotFoundError,
RateLimitError,
ValidationError,
BadRequestError,
ServerError,
ConnectionError,
)
try:
lead = client.leads.get("cld_nonexistent")
except NotFoundError:
print("Lead not found")
except AuthenticationError:
print("Invalid API key")
except RateLimitError as e:
print(f"Rate limited. Retry after {e.retry_after}s")
except ValidationError as e:
print(f"Validation failed: {e.response_body}")
except ServerError as e:
print(f"Server error ({e.status_code})")
except FoxReachError as e:
print(f"API error: {e}")
The SDK automatically retries on
429 Too Many Requests responses (up to max_retries times) with the delay specified in the Retry-After header.Source Code
- GitHub: foxreach/foxreach-python-sdk
- PyPI:
pip install foxreach