A Python client library for the Follow Up Boss API
Project description
Follow Up Boss API Client
A comprehensive Python client library for the Follow Up Boss API, providing easy access to all Follow Up Boss endpoints with full type safety and thorough documentation.
Features
- Complete API Coverage: Support for all Follow Up Boss API endpoints
- Type Safety: Full type hints throughout the library
- Easy to Use: Simple, intuitive interface
- Well Documented: Comprehensive docstrings and examples
- Async Support: Built with modern Python async/await patterns
- Error Handling: Robust error handling and validation
- Extensible: Easy to extend for custom use cases
Installation
pip install follow-up-boss
Quick Start
from follow_up_boss import FollowUpBossApiClient
# Initialize the client
client = FollowUpBossApiClient(
api_key="your_api_key",
x_system="Your-System-Name",
x_system_key="your_system_key"
)
# Get all people
people = client.people.get_all()
# Create a new person
new_person = client.people.create({
"name": "John Doe",
"email": "john@example.com",
"phone": "555-123-4567"
})
# Update a person
updated_person = client.people.update(person_id, {
"name": "John Smith"
})
# Add tags to a person (merge with existing, de-duplicated)
from follow_up_boss.people import People
people_api = People(client)
people_api.add_tags(person_id, ["Zillow: Note Logged"]) # merge=True by default
# Replace tags entirely
people_api.add_tags(person_id, ["Only These"], merge=False)
# Delete a person
client.people.delete(person_id)
Environment Variables
You can also configure the client using environment variables:
FOLLOW_UP_BOSS_API_KEY=your_api_key
X_SYSTEM=Your-System-Name
X_SYSTEM_KEY=your_system_key
from follow_up_boss import FollowUpBossApiClient
# Client will automatically use environment variables
client = FollowUpBossApiClient()
API Resources
The client provides access to all Follow Up Boss API resources:
Core Resources
- People: Manage contacts and leads
- Deals: Track real estate transactions (Commission Field Guide)
- Events: Handle activities and interactions
- Tasks: Manage todo items and follow-ups
- Notes: Add and retrieve notes
- Appointments: Schedule and manage appointments
Communication
- Text Messages: Send and receive SMS
- Email Templates: Manage email templates
- Text Message Templates: Manage SMS templates
- Webhooks: Configure webhook endpoints
- Reactions: Handle message reactions
Organization
- Teams: Manage team structures
- Users: Handle user accounts
- Groups: Organize contacts into groups
- Pipelines: Manage sales pipelines
- Stages: Configure pipeline stages
- Smart Lists: Dynamic contact lists
Configuration
- Custom Fields: Define custom data fields
- Action Plans: Automated workflow templates
- Appointment Types: Configure appointment categories
- Appointment Outcomes: Track appointment results
Attachments & Files
- Person Attachments: File attachments for contacts
- Deal Attachments: File attachments for deals
Deals API - Commission Fields
The Deals API includes special handling for commission fields. Important: Commission fields must be passed as top-level parameters, not in custom_fields.
from follow_up_boss import Deals, DealsValidationError
deals_api = Deals(client)
# ✅ Correct - Commission fields as top-level parameters
deal = deals_api.create_deal(
name="123 Main Street",
stage_id=26,
price=450000,
commissionValue=13500.0,
agentCommission=9450.0,
teamCommission=4050.0
)
# ❌ Incorrect - This will raise DealsValidationError
try:
deal = deals_api.create_deal(
name="Deal Name",
stage_id=26,
custom_fields={'commissionValue': 13500} # This fails
)
except DealsValidationError as e:
print(f"Validation error: {e}")
Commission Helper Methods
# Set commission using helper method
commission_data = {
'total': 15000.0,
'agent': 10500.0,
'team': 4500.0
}
updated_deal = deals_api.set_deal_commission(deal_id, commission_data)
For complete commission field documentation, see the Commission Field Guide.
Advanced Usage
Error Handling
from follow_up_boss import FollowUpBossApiClient
from follow_up_boss.exceptions import ApiError, AuthenticationError
try:
client = FollowUpBossApiClient(api_key="invalid_key")
people = client.people.get_all()
except AuthenticationError:
print("Invalid API credentials")
except ApiError as e:
print(f"API Error: {e}")
Pagination
# Get all people with pagination
all_people = []
page = 1
while True:
response = client.people.get_all(page=page, limit=100)
people = response.get('people', [])
if not people:
break
all_people.extend(people)
page += 1
Get people in a Follow Up Boss list
from follow_up_boss import FollowUpBossApiClient
from follow_up_boss.people import People
client = FollowUpBossApiClient(
api_key="your_api_key",
x_system="Your-System-Name",
x_system_key="your_system_key",
)
people_api = People(client)
# Single page filtered by Smart List ID
page = people_api.list_people_by_list_id(154, limit=50)
# Fetch all pages (follows _metadata.next)
all_people = people_api.fetch_all_people_by_list_id(154, limit=100)
Note: Cursor pagination uses the _metadata.next token returned by the API.
Iterate all people with automatic pagination
The People.iter_people() helper yields people across all pages. It prefers cursor-based pagination via _metadata.next when available (e.g., when using listId) and automatically falls back to offset-based pagination.
from follow_up_boss.people import People
people_api = People(client)
# Iterate with a saved list filter (cursor-based)
for person in people_api.iter_people({"listId": 154, "limit": 200}):
print(person.get("id"))
# Iterate with offset-based pagination (no cursor)
for person in people_api.iter_people({"limit": 100, "offset": 0, "stage": "New"}):
process(person)
Consistent list_people shape
People.list_people(params) always returns a dictionary that includes at least:
{"people": [...], "count": int}
This provides a stable structure for downstream clients even when the API omits certain fields.
Rate limit metadata and explicit exceptions
The client exposes rate limit headers parsed from responses:
from follow_up_boss import FollowUpBossApiClient
client = FollowUpBossApiClient(api_key="...", x_system="...", x_system_key="...")
resp = client._get("people", params={"limit": 1})
print(resp.get("_rateLimit")) # {'limit': 120, 'remaining': 119, 'reset': 1710000000}
# Or access the last seen info directly
print(client.get_last_rate_limit())
Explicit exceptions simplify handling and retries:
from follow_up_boss import (
FollowUpBossApiClient,
FollowUpBossAuthError,
FollowUpBossRateLimitError,
FollowUpBossValidationError,
)
client = FollowUpBossApiClient(api_key="...")
try:
client._get("people", {"limit": 1})
except FollowUpBossRateLimitError as e:
# backoff/retry using e.status_code and rate limit info
pass
except FollowUpBossAuthError as e:
# refresh credentials
pass
except FollowUpBossValidationError as e:
# fix request
pass
Custom Headers
# Add custom headers to requests
client = FollowUpBossApiClient(
api_key="your_key",
custom_headers={
"X-Custom-Header": "custom_value"
}
)
Development
Setup
git clone https://github.com/theperrygroup/follow-up-boss.git
cd follow-up-boss
pip install -e ".[dev]"
Running Tests
pytest
Code Formatting
black follow_up_boss tests
isort follow_up_boss tests
Type Checking
mypy follow_up_boss
Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Add tests for your changes
- Ensure all tests pass (
pytest) - Format your code (
blackandisort) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Support
For questions, issues, or feature requests, please:
- Check the documentation
- Search existing issues
- Create a new issue if needed
Changelog
Version 0.2.0
- Major Commission Field Improvements: Added comprehensive commission field handling with validation
- Enhanced Error Messages: Context-specific error guidance for common mistakes
- New Validation System:
DealsValidationErrorfor deals-specific validation - Commission Helper Methods:
set_deal_commission()for easier commission management - Field Name Normalization: Consistent field naming between requests and responses
- Comprehensive Documentation: New commission field guide with examples and troubleshooting
- Enhanced Testing: Complete test coverage for all commission field scenarios
- Improved Developer Experience: Better error messages, helper properties, and validation
Version 0.2.6
- People.add_tags helper: Official method to append/replace tags using PUT /people/{id}
- Merge behavior with de-duplication and optional case-insensitive matching
- Avoids unsupported POST /people/{id}/tags endpoint (404)
- Docs: README examples updated for tag operations
- Tooling: Formatting and type checks updated
Version 0.2.7
- People: Added
list_people_by_list_idandfetch_all_people_by_list_idsupporting cursor pagination via_metadata.next.
Version 0.2.8
- People: Added
iter_people(params)iterator (cursor-first, offset fallback). - People:
list_people(params)now guarantees a consistent shape:{"people": [...], "count": int}. - Typing: Introduced
ListPeopleParams,Person, andPeopleListResponseTypedDicts.
Version 0.2.9
- Client: Added explicit exception subclasses for auth, rate limit, validation, not-found, and server errors.
- Client: Expose
_rateLimitmetadata on responses andget_last_rate_limit().
Version 0.1.2
- Removed appointment test log file logging
Version 0.1.1
- Updated website URL to https://theperry.group
Version 0.1.0
- Initial release
- Complete API coverage for all Follow Up Boss endpoints
- Full type safety with comprehensive type hints
- Comprehensive test suite
- Documentation and examples
Related Projects
- Follow Up Boss API Documentation
- Follow Up Boss - The official Follow Up Boss platform
Made with ❤️ by The Perry Group
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file follow_up_boss-0.2.9.tar.gz.
File metadata
- Download URL: follow_up_boss-0.2.9.tar.gz
- Upload date:
- Size: 68.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4ad7fd41c47cbf82335a2f31394de50c37485524a3dfd905de541fb83b1384fe
|
|
| MD5 |
6ef8c89eebeead61887b4b9e2158d31f
|
|
| BLAKE2b-256 |
c1cd6e5c2c99fa49069d5eb3c1c61717e73849bb30435b9b2e18c78b51590d54
|
File details
Details for the file follow_up_boss-0.2.9-py3-none-any.whl.
File metadata
- Download URL: follow_up_boss-0.2.9-py3-none-any.whl
- Upload date:
- Size: 87.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
34f89fe3d6cae7114425049040f296234a461ade18b3bd295f31e9490f36429e
|
|
| MD5 |
47586d7af7ce609405b6861a668894ce
|
|
| BLAKE2b-256 |
b427292143b53e5b95629763924c9c04b70d159819beef0c05a7149e3ed004f6
|