# Bloomy Bloomy is a Python SDK for interacting with the Bloom Growth API, providing easy access to users, meetings, todos, goals, scorecards, issues, and headlines. It offers both synchronous and asynchronous clients with comprehensive Pydantic models for type-safe data handling. The SDK supports multiple authentication methods including direct API key initialization, environment variables (BG_API_KEY), and configuration files. It features bulk operations for creating multiple resources efficiently, context manager support for proper connection handling, and a clean object-oriented interface organized around resource types (users, meetings, todos, goals, scorecards, issues, headlines). ## Client Initialization The Client class is the main entry point for synchronous interactions with the Bloom Growth API. It automatically loads API keys from environment variables or configuration files if not provided directly. ```python from bloomy import Client, Configuration # Direct API key initialization client = Client(api_key="your-api-key-here") # Using environment variable BG_API_KEY client = Client() # Configure API key with username and password config = Configuration() config.configure_api_key("username", "password", store_key=True) client = Client() # Using context manager for automatic cleanup with Client(api_key="your-api-key") as client: user = client.user.details() print(f"Hello, {user.name}") # Custom base URL and timeout client = Client( api_key="your-api-key", base_url="https://app.bloomgrowth.com/api/v1", timeout=60.0 ) ``` ## Async Client Initialization The AsyncClient provides asynchronous access to all Bloom Growth API operations for better performance in async applications. ```python import asyncio from bloomy import AsyncClient async def main(): # Using async context manager (recommended) async with AsyncClient(api_key="your-api-key") as client: user = await client.user.details() meetings = await client.meeting.list() print(f"Hello {user.name}, you have {len(meetings)} meetings") # Without context manager client = AsyncClient(api_key="your-api-key") try: user = await client.user.details() finally: await client.close() asyncio.run(main()) ``` ## User Operations User operations provide methods to retrieve user details, search for users, list all users, and access direct reports and positions. ```python from bloomy import Client client = Client(api_key="your-api-key") # Get current user details user = client.user.details() print(f"User: {user.name}, ID: {user.id}") # Get specific user with additional details user = client.user.details( user_id=123, include_direct_reports=True, include_positions=True ) for report in user.direct_reports: print(f"Direct report: {report.name}") for position in user.positions: print(f"Position: {position.name}") # Get user with all details using shorthand user = client.user.details(user_id=123, include_all=True) # Search for users results = client.user.search("john") for result in results: print(f"Found: {result.name} ({result.email})") # List all users users = client.user.list() for user in users: print(f"{user.name} - {user.position}") # List all users including placeholders users = client.user.list(include_placeholders=True) # Get direct reports for a user reports = client.user.direct_reports(user_id=123) # Get positions for a user positions = client.user.positions(user_id=123) ``` ## Meeting Operations Meeting operations allow listing, creating, deleting meetings, and accessing meeting details including attendees, issues, todos, and metrics. ```python from bloomy import Client client = Client(api_key="your-api-key") # List all meetings for current user meetings = client.meeting.list() for meeting in meetings: print(f"Meeting: {meeting.name} (ID: {meeting.id})") # List meetings for specific user meetings = client.meeting.list(user_id=456) # Get detailed meeting information details = client.meeting.details(meeting_id=123) print(f"Meeting: {details.name}") print(f"Attendees: {len(details.attendees)}") print(f"Issues: {len(details.issues)}") print(f"Todos: {len(details.todos)}") # Get meeting details including closed items details = client.meeting.details(meeting_id=123, include_closed=True) # Create a new meeting result = client.meeting.create( title="Weekly Team Meeting", add_self=True, attendees=[456, 789] ) print(f"Created meeting ID: {result['meeting_id']}") # Delete a meeting client.meeting.delete(meeting_id=123) # Get meeting attendees attendees = client.meeting.attendees(meeting_id=123) for attendee in attendees: print(f"Attendee: {attendee.name}") # Get meeting issues issues = client.meeting.issues(meeting_id=123, include_closed=False) # Get meeting todos todos = client.meeting.todos(meeting_id=123, include_closed=False) # Get meeting metrics metrics = client.meeting.metrics(meeting_id=123) for metric in metrics: print(f"{metric.title}: {metric.value}/{metric.target}") # Bulk create meetings result = client.meeting.create_many([ {"title": "Weekly Team Meeting", "attendees": [2, 3]}, {"title": "1:1 Meeting", "add_self": False} ]) print(f"Created {len(result.successful)} meetings") for error in result.failed: print(f"Failed at index {error.index}: {error.error}") # Bulk get meeting details result = client.meeting.get_many([123, 456, 789]) for meeting in result.successful: print(f"{meeting.name} - {len(meeting.attendees)} attendees") ``` ## Todo Operations Todo operations provide CRUD functionality for managing todos, including creation, completion, updates, and bulk operations. ```python from bloomy import Client client = Client(api_key="your-api-key") # List todos for current user todos = client.todo.list() for todo in todos: print(f"Todo: {todo.name}, Due: {todo.due_date}, Complete: {todo.complete}") # List todos for specific user todos = client.todo.list(user_id=456) # List todos for a meeting todos = client.todo.list(meeting_id=123) # Get todo details todo = client.todo.details(todo_id=789) print(f"Todo: {todo.name}") # Create a user todo new_todo = client.todo.create( title="Complete project proposal", due_date="2024-12-31", notes="Include budget estimates" ) print(f"Created todo ID: {new_todo.id}") # Create a meeting todo meeting_todo = client.todo.create( title="Follow up on action items", meeting_id=123, due_date="2024-12-15", user_id=456 ) # Complete a todo completed = client.todo.complete(todo_id=789) print(f"Completed: {completed.complete}") # Update a todo updated = client.todo.update( todo_id=789, title="Updated title", due_date="2024-12-25" ) # Bulk create todos result = client.todo.create_many([ {"title": "Task 1", "meeting_id": 123, "due_date": "2024-12-31"}, {"title": "Task 2", "meeting_id": 123, "user_id": 456} ]) print(f"Created {len(result.successful)} todos") for error in result.failed: print(f"Failed at index {error.index}: {error.error}") ``` ## Goal Operations Goal operations (also known as "Rocks") provide functionality for creating, updating, archiving, and managing goals with status tracking. ```python from bloomy import Client, GoalStatus client = Client(api_key="your-api-key") # List active goals for current user goals = client.goal.list() for goal in goals: print(f"Goal: {goal.title}, Status: {goal.status}") # List goals including archived response = client.goal.list(archived=True) print(f"Active goals: {len(response.active)}") print(f"Archived goals: {len(response.archived)}") # Create a new goal new_goal = client.goal.create( title="Increase sales by 20%", meeting_id=123, user_id=456 ) print(f"Created goal ID: {new_goal.id}") # Update goal status using enum (recommended) client.goal.update(goal_id=789, status=GoalStatus.ON_TRACK) # Update goal status using string client.goal.update(goal_id=789, status="on") # on, off, or complete # Update goal title and accountable user client.goal.update( goal_id=789, title="Updated Goal Title", accountable_user=456, status=GoalStatus.COMPLETE ) # Archive a goal client.goal.archive(goal_id=789) # Restore an archived goal client.goal.restore(goal_id=789) # Delete a goal client.goal.delete(goal_id=789) # Bulk create goals result = client.goal.create_many([ {"title": "Q1 Revenue Target", "meeting_id": 123}, {"title": "Product Launch", "meeting_id": 123, "user_id": 456} ]) print(f"Created {len(result.successful)} goals") for error in result.failed: print(f"Failed at index {error.index}: {error.error}") ``` ## Scorecard Operations Scorecard operations provide methods to retrieve and update scorecard metrics, including week-based filtering and scoring. ```python from bloomy import Client client = Client(api_key="your-api-key") # Get current week information week = client.scorecard.current_week() print(f"Week {week.week_number}: {week.week_start} to {week.week_end}") # List scorecards for current user scorecards = client.scorecard.list() for item in scorecards: print(f"{item.title}: {item.value}/{item.target}") # List scorecards for specific user scorecards = client.scorecard.list(user_id=456) # List scorecards for a meeting scorecards = client.scorecard.list(meeting_id=123) # List scorecards including empty values scorecards = client.scorecard.list(show_empty=True) # List scorecards for previous week scorecards = client.scorecard.list(week_offset=-1) # List scorecards for next week scorecards = client.scorecard.list(week_offset=1) # Get a single scorecard item item = client.scorecard.get(measurable_id=123) if item: print(f"{item.title}: {item.value}/{item.target}") # Get scorecard item for previous week item = client.scorecard.get(measurable_id=123, week_offset=-1) # Update a score for current week success = client.scorecard.score(measurable_id=123, score=95.5) print(f"Score updated: {success}") # Update a score for previous week success = client.scorecard.score(measurable_id=123, score=88.0, week_offset=-1) ``` ## Issue Operations Issue operations provide CRUD functionality for managing issues, including creation, completion, updates, and bulk operations. ```python from bloomy import Client client = Client(api_key="your-api-key") # List issues for current user issues = client.issue.list() for issue in issues: print(f"Issue: {issue.title}, Meeting: {issue.meeting_title}") # List issues for specific user issues = client.issue.list(user_id=456) # List issues for a meeting issues = client.issue.list(meeting_id=123) # Get issue details issue = client.issue.details(issue_id=789) print(f"Issue: {issue.title}") print(f"Created: {issue.created_at}") print(f"Owner: {issue.user_name}") # Create an issue new_issue = client.issue.create( meeting_id=123, title="Server performance degradation", notes="Response times increased by 50%" ) print(f"Created issue ID: {new_issue.id}") # Create an issue assigned to specific user new_issue = client.issue.create( meeting_id=123, title="Review security audit", user_id=456 ) # Update an issue updated = client.issue.update( issue_id=789, title="Updated Issue Title", notes="Additional context" ) # Complete/solve an issue completed = client.issue.complete(issue_id=789) print(f"Completed at: {completed.completed_at}") # Bulk create issues result = client.issue.create_many([ {"meeting_id": 123, "title": "Issue 1", "notes": "Details"}, {"meeting_id": 123, "title": "Issue 2", "user_id": 456} ]) print(f"Created {len(result.successful)} issues") for error in result.failed: print(f"Failed at index {error.index}: {error.error}") ``` ## Headline Operations Headline operations provide methods for creating, updating, listing, and deleting headlines associated with meetings. ```python from bloomy import Client client = Client(api_key="your-api-key") # List headlines for current user headlines = client.headline.list() for headline in headlines: print(f"Headline: {headline.title}") print(f"Meeting: {headline.meeting_details.title}") print(f"Owner: {headline.owner_details.name}") # List headlines for specific user headlines = client.headline.list(user_id=456) # List headlines for a meeting headlines = client.headline.list(meeting_id=123) # Get headline details headline = client.headline.details(headline_id=789) print(f"Headline: {headline.title}") print(f"Created: {headline.created_at}") print(f"Archived: {headline.archived}") # Create a headline new_headline = client.headline.create( meeting_id=123, title="Product launch successful", notes="Exceeded targets by 15%" ) print(f"Created headline ID: {new_headline.id}") # Create a headline with specific owner new_headline = client.headline.create( meeting_id=123, title="New partnership announcement", owner_id=456 ) # Update a headline client.headline.update(headline_id=789, title="Updated headline title") # Delete a headline client.headline.delete(headline_id=789) ``` ## Error Handling The SDK provides specific exception classes for different error scenarios, enabling precise error handling in applications. ```python from bloomy import Client from bloomy.exceptions import ( BloomyError, ConfigurationError, AuthenticationError, APIError ) try: client = Client() # May raise ConfigurationError if no API key except ConfigurationError as e: print(f"Configuration error: {e}") # Handle missing API key try: client = Client(api_key="invalid-key") user = client.user.details() except AuthenticationError as e: print(f"Authentication failed: {e}") # Handle invalid credentials try: meeting = client.meeting.details(meeting_id=99999) except APIError as e: print(f"API error: {e}") print(f"Status code: {e.status_code}") # Handle API errors (404, 500, etc.) try: client.todo.update(todo_id=123) # No fields provided except ValueError as e: print(f"Validation error: {e}") # Catch all Bloomy errors try: client.goal.create(title="Goal", meeting_id=123) except BloomyError as e: print(f"Bloomy error occurred: {e}") ``` ## Configuration Management The Configuration class handles API key management with support for environment variables, configuration files, and username/password authentication. ```python from bloomy import Configuration from bloomy.exceptions import AuthenticationError, ConfigurationError # Create configuration (loads from env or file automatically) config = Configuration() print(f"API Key loaded: {config.api_key is not None}") # Create configuration with explicit API key config = Configuration(api_key="your-api-key") # Configure API key using username and password config = Configuration() try: config.configure_api_key( username="your-username", password="your-password", store_key=True # Saves to ~/.bloomy/config.yaml ) print(f"API key configured: {config.api_key[:10]}...") except AuthenticationError as e: print(f"Authentication failed: {e}") # Configuration file location: ~/.bloomy/config.yaml # Format: # version: 1 # api_key: your-api-key-here ``` ## Summary Bloomy SDK is ideal for building integrations with Bloom Growth for business management applications. Common use cases include automating meeting management, tracking team goals and performance metrics through scorecards, managing action items (todos), and handling team communication through headlines and issues. The SDK supports batch operations for efficient bulk data processing and provides both sync and async interfaces. Integration patterns typically involve initializing a client with API credentials, using resource-specific operations (client.user, client.meeting, client.todo, etc.), handling responses through Pydantic models for type safety, and implementing error handling using the exception hierarchy. The bulk operations (create_many, get_many) are particularly useful for data migration and synchronization tasks, returning BulkCreateResult objects that separate successful operations from failures for comprehensive error handling.