### start Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/api-reference/daily-habit.md Start working on the habit, marking it as IN_PROGRESS. ```APIDOC ## start ### Description Start working on the habit (mark IN_PROGRESS). ### Method ```python def start() -> None ``` ``` -------------------------------- ### Complete Webhook Handling Example Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/api-reference/webhook.md This example demonstrates a full Flask application setup for handling Reclaim webhooks. It includes creating a webhook, setting up an endpoint to receive and verify payloads, parsing events, and managing webhooks. Ensure you replace placeholder values like API keys and secrets with your actual credentials. ```python from flask import Flask, request, jsonify from reclaim_sdk.resources.webhook import Webhook from reclaim_sdk.webhooks.payloads import parse_webhook_payload from reclaim_sdk.webhooks.signature import verify_signature from reclaim_sdk.exceptions import SignatureVerificationError from reclaim_sdk.client import ReclaimClient app = Flask(__name__) # Configure SDK ReclaimClient.configure(token="your_api_key") # ===== 1. Create webhook ===== webhook = Webhook( name="My Event Handler", url="https://myapp.com/webhooks/reclaim", events=["task.created", "task.updated", "task.completed", "habit.created"], secret="my_signing_secret_123", ) webhook.save() print(f"Created webhook {webhook.id}") # ===== 2. Handle incoming webhooks ===== @app.route("/webhooks/reclaim", methods=["POST"]) def handle_reclaim_webhook(): body = request.get_data() signature = request.headers.get("x-reclaim-signature", "") # Verify signature try: verify_signature(body, signature, webhook.secret) except SignatureVerificationError as e: print(f"Signature verification failed: {e}") return {"error": "Invalid signature"}, 401 # Parse event event = parse_webhook_payload(body) # Handle based on type if event.type == "task.created": print(f"📝 Task created: {event.task.title}") # ... handle task creation elif event.type == "task.updated": print(f"✏️ Task updated: {event.task.title}") elif event.type == "task.completed": print(f"✅ Task completed: {event.task.title}") elif event.type == "habit.created": print(f"🎯 Habit created: {event.habit.title}") return {"status": "ok"}, 200 # ===== 3. Manage webhooks ===== # List all webhooks = Webhook.list() for w in webhooks: print(f"{w.name}: {w.status}") # Update webhook = Webhook.get(webhook.id) webhook.events.append("task.deleted") webhook.save() # Suspend / delete webhook.delete() if __name__ == "__main__": app.run(port=5000) ``` -------------------------------- ### Documentation Navigation Guide Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/MANIFEST.txt A recommended path for users to navigate the Reclaim SDK documentation, starting from general overviews to specific technical details. ```APIDOC ## Documentation Navigation Follow this sequence for a comprehensive understanding of the Reclaim SDK: 1. **README.md**: Start here for an overall orientation and quick access guide. 2. **INDEX.md**: Provides a complete overview, quick start instructions, and a feature table. 3. **api-reference/*.md**: Jump to specific files within the `api-reference` directory for detailed method documentation on resources like `Task`, `DailyHabit`, `Hours`, `SmartMeeting`, `Webhook`, `Changelog`, and `ReclaimClient`. 4. **types.md**: Consult this file for definitions of all enums, nested models, and type definitions. 5. **configuration.md**: Find information on API token setup and environment variables. 6. **errors.md**: Refer to this document for details on exception types, error patterns, and recovery strategies. ``` -------------------------------- ### Install Development Dependencies Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/CLAUDE.md Installs the SDK in editable mode along with development tools like flake8 and black. ```bash pip install -e ".[dev]" ``` -------------------------------- ### start Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/api-reference/task.md Starts the task, moving it to the IN_PROGRESS status and beginning time tracking. ```APIDOC ## start ### Description Start the task (move to IN_PROGRESS, begin time tracking). ### Method ```python def start() -> None ``` ### Example ```python task.start() task.refresh() assert task.status == TaskStatus.IN_PROGRESS ``` ``` -------------------------------- ### Install Reclaim SDK Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/README.md Install the reclaim-sdk package using pip. ```bash pip install reclaim-sdk ``` -------------------------------- ### CI Workflow Setup Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/docs/superpowers/plans/2026-04-21-reclaim-api-parity.md This YAML file defines a GitHub Actions CI workflow that checks out code, sets up Python, installs dependencies, and runs linters and tests. ```yaml name: CI on: pull_request: branches: [master] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.12" - run: pip install -e ".[dev]" - run: flake8 reclaim_sdk - run: pytest tests/unit --cov=reclaim_sdk --cov-report=term-missing --cov-fail-under=90 ``` -------------------------------- ### Quick Start with Reclaim SDK Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/INDEX.md Demonstrates basic client configuration and usage of the Task resource for listing, creating, saving, starting, logging work, and marking tasks as complete. Requires an API key for configuration. ```python from reclaim_sdk.client import ReclaimClient from reclaim_sdk.resources.task import Task # Configure (one-time) ReclaimClient.configure(token="your_api_key") # Use resources tasks = Task.list() task = Task(title="My task", duration=2.0) task.save() task.start() task.log_work(60) task.mark_complete() ``` -------------------------------- ### Start and Stop a Task Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/api-reference/base-resource.md Use `start()` to move a resource to IN_PROGRESS and begin time tracking. Use `stop()` to pause time tracking. ```python task = Task.get(123) task.start() # Move to IN_PROGRESS task.stop() # Pause ``` -------------------------------- ### Test Habit Start Uses Habit Segment Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/docs/superpowers/plans/2026-04-21-reclaim-api-parity.md Verifies that the `start` method of `DailyHabit` correctly calls the planner API for starting a habit. ```python def test_habit_start_uses_habit_segment(client, mock_api): route = mock_api.post("/api/planner/start/habit/10").mock( return_value=httpx.Response(200, json={"taskOrHabit": {"id": 10, "type": "CUSTOM_DAILY"}}) ) h = DailyHabit(id=10, title="Run") h.start() assert route.called ``` -------------------------------- ### Start a Task Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/api-reference/task.md Initiates a task, moving it to the IN_PROGRESS status and starting time tracking. Refresh the task object after starting to see the updated status. ```python task.start() task.refresh() assert task.status == TaskStatus.IN_PROGRESS ``` -------------------------------- ### Custom Resource Example Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/api-reference/base-resource.md Demonstrates how to create, save, retrieve, update, and delete a custom resource by subclassing BaseResource. ```APIDOC ## Custom Resource Example This example shows how to define and use a new resource type by inheriting from `BaseResource`. ### Description This section illustrates the process of creating a new resource, `CustomResource`, which includes defining its endpoint, user parameter requirement, and fields with Pydantic. ### Method - `__init__`: Initializes the custom resource with provided name and value. - `save()`: Saves the resource to the API. - `get(id)`: Retrieves a resource by its ID. - `delete()`: Deletes the resource from the API. ### Endpoint - `/api/custom` (for the `CustomResource`) ### Parameters #### Path Parameters None explicitly defined for the resource creation itself, but `get` and `delete` operate on a resource ID. #### Query Parameters None explicitly defined. #### Request Body When saving or updating, the resource fields are sent. For `CustomResource`: - **name** (Optional[str]) - The name of the custom resource. - **value** (Optional[int]) - The custom value associated with the resource, aliased as `customValue` in the API. ### Request Example ```python # Creating a new custom resource resource = CustomResource(name="Test", value=42) resource.save() # Retrieving a resource by ID retrieved_resource = CustomResource.get(resource.id) # Updating a resource retrieved_resource.value = 100 retrieved_resource.save() # Deleting a resource retrieved_resource.delete() ``` ### Response #### Success Response (200) - **id** (str) - Server-assigned unique identifier for the resource. - **name** (Optional[str]) - The name of the custom resource. - **customValue** (Optional[int]) - The custom value associated with the resource. #### Response Example ```json { "id": "some-server-assigned-id", "name": "Test", "customValue": 42 } ``` ``` -------------------------------- ### StartStoppableMixin Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/api-reference/base-resource.md Provides methods to start and stop a resource, affecting its status and time tracking. ```APIDOC ## StartStoppableMixin ### Description Provides `start()` and `stop()` methods to manage the lifecycle of a resource. ### Methods #### `start()` - **Description**: Start the resource (move to IN_PROGRESS, begin time tracking). - **Signature**: `def start(self) -> None` #### `stop()` - **Description**: Stop the resource (pause time tracking). - **Signature**: `def stop(self) -> None` ### Example ```python task = Task.get(123) task.start() # Move to IN_PROGRESS task.stop() # Pause ``` ``` -------------------------------- ### Install Development Dependencies and Collect Tests Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/docs/superpowers/plans/2026-04-21-reclaim-api-parity.md Installs the SDK in development mode and runs `pytest --collect-only` to verify test collection without execution. ```bash pip install -e ".[dev]" pytest --collect-only 2>&1 | tail -5 ``` -------------------------------- ### Create Smart Meeting Request with Date Strings Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/configuration.md Example of creating a smart meeting request using date strings in YYYY-MM-DD format for the starting and ending parameters. ```python request = CreateSmartMeetingRequest( starting="2025-03-01", ending="2025-03-31", ... ) ``` -------------------------------- ### Resource Composition Example Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/docs/superpowers/specs/2026-04-21-reclaim-api-parity-design.md Illustrates how different resources compose base classes and mixins to inherit functionality. This pattern mirrors Reclaim's trait model. ```python Task(BaseResource, SnoozeableMixin, StartStoppableMixin, RestartableMixin, LogWorkableMixin, CompletableMixin, ClearExceptionsMixin, PlanWorkMixin) DailyHabit(BaseResource, StartStoppableMixin, RestartableMixin, ClearExceptionsMixin) Hours(BaseResource) # unchanged Webhook(BaseResource) # new, CRUD only ``` -------------------------------- ### Update Task Management Example Imports Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/docs/superpowers/plans/2026-04-21-reclaim-api-parity.md Modifies the import statement in `examples/task_management.py` to reflect the changes in `reclaim_sdk.resources.task` and `reclaim_sdk.enums`. ```python from reclaim_sdk.resources.task import Task from reclaim_sdk.enums import PriorityLevel, EventColor ``` -------------------------------- ### Planner Actions for Tasks Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/INDEX.md Perform various planner actions on a fetched task, such as starting it, logging work, adding time, snoozing, or marking it as complete. Ensure the task is fetched using `Task.get()` before applying these actions. ```python task = Task.get(123) task.start() task.log_work(60) task.add_time(0.5) task.snooze(SnoozeOption.TOMORROW) task.mark_complete() ``` -------------------------------- ### Start Daily Habit Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/api-reference/daily-habit.md Marks the habit as IN_PROGRESS, indicating that work has begun on it. ```python def start() -> None: """Start working on the habit (mark IN_PROGRESS).""" ``` -------------------------------- ### Task Resource Planner Actions Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/CLAUDE.md Shows how to perform planner actions on a Task resource, such as starting, stopping, marking complete, or adding time. These actions interact with the /api/planner/* endpoints. ```python task.start() task.stop() task.mark_complete() # done task.mark_incomplete() # unarchive task.add_time(hours=1) task.log_work(datetime.now(timezone.utc).isoformat(timespec='milliseconds') + 'Z') task.prioritize() task.clear_exceptions() ``` -------------------------------- ### Update Task Priority in Example Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/docs/superpowers/plans/2026-04-21-reclaim-api-parity.md Changes the `priority` argument in the `examples/task_management.py` to use `PriorityLevel.P3` instead of the deprecated `TaskPriority.P3`. ```python priority=PriorityLevel.P3 ``` -------------------------------- ### get Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/api-reference/base-resource.md Fetches a single resource by its unique identifier. This class method can optionally use a provided client instance or auto-create one. ```APIDOC ## get ### Description Fetch a single resource by ID. ### Method `@classmethod get(cls: Type[T], id: int, client: ReclaimClient = None) -> T` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters #### Path Parameters - **id** (int) - Required - Resource ID - **client** (ReclaimClient) - Optional - Client override (auto-creates if None) ### Request Example ```python task = Task.get(123) habit = DailyHabit.get(456) hours = Hours.get("550e8400-e29b-41d4-a716-446655440000") ``` ### Response #### Success Response (200) - **Resource instance** #### Response Example None ### Raises - `RecordNotFound` if resource doesn't exist - `AuthenticationError` if not authenticated ### Auto-injection If `USER_PARAM_REQUIRED` is True, the `user` query parameter is auto-injected from `client.current_user().get("id")` ``` -------------------------------- ### Task Planner Actions Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/api-reference/task.md Illustrates various planner actions for a task, including starting, logging work, adding time, planning specific work times, snoozing, and marking as complete. ```python # Planner actions task.start() task.log_work(60) # Log 1 hour task.add_time(0.5) # Add 30 min task.plan_work(datetime(2025, 3, 16, 10, 0, tzinfo=timezone.utc)) task.snooze(SnoozeOption.NEXT_WEEK) task.mark_complete() ``` -------------------------------- ### Implement StartStoppableMixin for Task Management Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/docs/superpowers/plans/2026-04-21-reclaim-api-parity.md Defines a mixin class to handle starting and stopping tasks. It abstracts the API call logic for these actions, making it reusable across different resource types. ```python from typing import ClassVar class StartStoppableMixin: _PLANNER_PATH_SEGMENT: ClassVar[str] = "task" def start(self) -> None: response = self._client.post( f"/api/planner/start/{self._PLANNER_PATH_SEGMENT}/{self.id}" ) payload = response.get("taskOrHabit", response) if isinstance(response, dict) else response self.__dict__.update(self.from_api_data(payload).__dict__) def stop(self) -> None: response = self._client.post( f"/api/planner/stop/{self._PLANNER_PATH_SEGMENT}/{self.id}" ) payload = response.get("taskOrHabit", response) if isinstance(response, dict) else response self.__dict__.update(self.from_api_data(payload).__dict__) ``` -------------------------------- ### Full Hours API Usage Example Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/api-reference/hours.md Demonstrates creating a custom 9-5 work hours scheme, listing all schemes, fetching and updating a scheme, and deleting a scheme using the Reclaim SDK. ```python from datetime import time from reclaim_sdk.resources.hours import Hours, TimeSchemePolicy, DayIntervals, Interval from reclaim_sdk.enums import Weekday, PolicyType, TimeSchemeFeature from reclaim_sdk.client import ReclaimClient ReclaimClient.configure(token="your_api_key") # Create a custom 9-5 scheme (9-12, 13-17 Mon-Fri, no weekends) monday_intervals = DayIntervals( intervals=[ Interval(start=time(9, 0), end=time(12, 0)), Interval(start=time(13, 0), end=time(17, 0)), ] ) policy = TimeSchemePolicy( day_hours={ Weekday.MONDAY: monday_intervals, Weekday.TUESDAY: monday_intervals, Weekday.WEDNESDAY: monday_intervals, Weekday.THURSDAY: monday_intervals, Weekday.FRIDAY: monday_intervals, }, start_of_week=Weekday.MONDAY, end_of_week=Weekday.FRIDAY, ) scheme = Hours( title="Standard work hours", policy_type=PolicyType.CUSTOM, policy=policy, features=[TimeSchemeFeature.TASK_ASSIGNMENT, TimeSchemeFeature.SMART_MEETING], ) scheme.save() print(f"Created: {scheme.id}") # List all schemes schemes = Hours.list() for s in schemes: print(f"{s.title}: {s.policy_type}") # Fetch and update scheme = Hours.get(scheme.id) scheme.title = "Flexible 9-5 (updated)" scheme.save() # Delete scheme.delete() ``` -------------------------------- ### Commit Refactoring Task Start/Stop Methods Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/docs/superpowers/plans/2026-04-21-reclaim-api-parity.md Stages and commits the changes related to moving the start and stop methods into the StartStoppableMixin. ```bash git add reclaim_sdk/mixins/start_stoppable.py reclaim_sdk/resources/task.py tests/unit/mixins/test_start_stoppable.py git commit --no-gpg-sign -m "refactor(task): move start/stop to StartStoppableMixin" ``` -------------------------------- ### Create Task at Specific Time - Python Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/docs/superpowers/plans/2026-04-21-reclaim-api-parity.md Implement the `create_at_time` class method in the `Task` class to create a task at a specified start time. It handles API calls and response parsing. ```python @classmethod def create_at_time( cls, task: "Task", start_time: datetime, client: ReclaimClient = None ) -> "Task": if client is None: client = ReclaimClient() params = {"startTime": start_time.astimezone(timezone.utc).isoformat().replace("+00:00", "Z")} data = client.post(cls.ENDPOINT + "/at-time", params=params, json=task.to_api_data()) # response shape: CreateTaskAtTimeView — contains the created task under "task" or is the task itself payload = data.get("task", data) if isinstance(data, dict) else data return cls.from_api_data(payload) ``` -------------------------------- ### Task.create_at_time Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/docs/superpowers/plans/2026-04-21-reclaim-api-parity.md Creates a task at a specified start time. This class method handles the API call to create a task and returns the created task object. ```APIDOC ## POST /api/tasks/at-time ### Description Creates a task at a specified start time. ### Method POST ### Endpoint /api/tasks/at-time ### Parameters #### Query Parameters - **startTime** (string) - Required - The ISO 8601 formatted start time for the task. #### Request Body - **task** (object) - Required - The task object to be created, serialized to API data format. ### Request Example ```json { "startTime": "2023-10-27T10:00:00Z", "title": "Example Task", "estimatedTime": 60 } ``` ### Response #### Success Response (200) - **task** (object) - The created task object, or the task object itself if the response is not wrapped. ### Response Example ```json { "task": { "id": "task-123", "title": "Example Task", "startTime": "2023-10-27T10:00:00Z", "estimatedTime": 60 } } ``` ``` -------------------------------- ### Test Task Start/Stop Functionality Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/docs/superpowers/plans/2026-04-21-reclaim-api-parity.md Tests the integration of Task start and stop methods with the planner API. Ensures that the correct API routes are called with the appropriate task ID. ```python import httpx from reclaim_sdk.resources.task import Task from reclaim_sdk.enums import PriorityLevel, TaskSource def test_task_start_hits_planner_start(client, mock_api): route = mock_api.post("/api/planner/start/task/42").mock( return_value=httpx.Response(200, json={"taskOrHabit": {"id": 42, "type": "TASK"}}) ) t = Task(id=42, title="x", priority=PriorityLevel.P3, taskSource=TaskSource.RECLAIM) t.start() assert route.called def test_task_stop_hits_planner_stop(client, mock_api): route = mock_api.post("/api/planner/stop/task/42").mock( return_value=httpx.Response(200, json={"taskOrHabit": {"id": 42, "type": "TASK"}}) ) t = Task(id=42, title="x", priority=PriorityLevel.P3, taskSource=TaskSource.RECLAIM) t.stop() assert route.called ``` -------------------------------- ### Example TimeSchemePolicy Usage Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/api-reference/hours.md Instantiates a TimeSchemePolicy to define working hours for Monday and Tuesday, with the work week starting and ending on specific days. Useful for setting up recurring schedules. ```python policy = TimeSchemePolicy( day_hours={ Weekday.MONDAY: DayIntervals( intervals=[ Interval(start=time(9, 0), end=time(12, 0)), Interval(start=time(13, 0), end=time(17, 0)), ] ), Weekday.TUESDAY: DayIntervals( intervals=[Interval(start=time(9, 0), end=time(17, 0))] ), # Wednesday-Friday inherited or omitted }, start_of_week=Weekday.MONDAY, end_of_week=Weekday.FRIDAY, ) ``` -------------------------------- ### Configure Live Test Fixtures Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/docs/superpowers/plans/2026-04-21-reclaim-api-parity.md Sets up session-scoped fixtures for live testing, including a client configured with a token from environment variables and a registry for cleaning up created resources. ```python import os import uuid import pytest from reclaim_sdk.client import ReclaimClient SDK_LIVE_PREFIX = f"[sdk-test-{uuid.uuid4().hex[:8]}]" @pytest.fixture(scope="session") def live_client(): token = os.environ.get("RECLAIM_TOKEN") if not token: pytest.skip("RECLAIM_TOKEN not set") return ReclaimClient.configure(token=token) @pytest.fixture(scope="session") def tracked_ids(): """Registry of resources created during the session. Cleaned up in finalizer.""" registry = {"tasks": [], "habits": [], "webhooks": []} yield registry from reclaim_sdk.resources.task import Task from reclaim_sdk.resources.habit import DailyHabit from reclaim_sdk.resources.webhook import Webhook errors = [] for task_id in registry["tasks"]: try: t = Task.get(task_id) t.delete() except Exception as e: errors.append(f"task {task_id}: {e}") for habit_id in registry["habits"]: try: h = DailyHabit.get(habit_id) h.delete() except Exception as e: errors.append(f"habit {habit_id}: {e}") for wh_id in registry["webhooks"]: try: w = Webhook.get(wh_id) w.delete() except Exception as e: errors.append(f"webhook {wh_id}: {e}") # paranoid sweep try: for t in Task.list(): if t.title and t.title.startswith(SDK_LIVE_PREFIX): t.delete() except Exception as e: errors.append(f"task sweep: {e}") if errors: raise RuntimeError("Live cleanup failures: " + "; ".join(errors)) @pytest.fixture def prefix(): return SDK_LIVE_PREFIX ``` -------------------------------- ### Run Live Mode Tests for Multiple Resources Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/docs/superpowers/plans/2026-04-21-reclaim-api-parity.md Command to execute all live-mode tests located in the `tests/live` directory. ```bash pytest tests/live -v ``` -------------------------------- ### Create Test Package Skeleton Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/docs/superpowers/plans/2026-04-21-reclaim-api-parity.md Initializes the directory structure and empty `__init__.py` files for the test suite. ```bash touch tests/__init__.py tests/unit/__init__.py tests/live/__init__.py mkdir -p tests/unit/mixins tests/unit/resources tests/unit/webhooks touch tests/unit/mixins/__init__.py tests/unit/resources/__init__.py tests/unit/webhooks/__init__.py ``` -------------------------------- ### Update BaseResource get Method Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/docs/superpowers/plans/2026-04-21-reclaim-api-parity.md Modifies the `get` classmethod in BaseResource to conditionally include the user parameter based on `USER_PARAM_REQUIRED`. ```python @classmethod def get(cls: Type[T], id: int, client: ReclaimClient = None) -> T: if client is None: client = ReclaimClient() params = {} if cls.USER_PARAM_REQUIRED: params["user"] = client.current_user().get("id") data = client.get(f"{cls.ENDPOINT}/{id}", params=params) return cls.from_api_data(data) ``` -------------------------------- ### Webhook Ingestion Example Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/docs/superpowers/specs/2026-04-21-reclaim-api-parity-design.md Example of consumer code for handling Reclaim webhooks. It verifies the signature and parses the webhook payload before processing the event. ```python from reclaim_sdk.webhooks import parse_webhook_payload, verify_signature @app.post("/reclaim-hook") def hook(request): verify_signature(request.body, request.headers["X-Reclaim-Signature"], SECRET) event = parse_webhook_payload(request.body) match event: case TaskWebhookEvent(): handle_task(event.task) ``` -------------------------------- ### Custom Resource Creation and Usage Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/api-reference/base-resource.md Demonstrates how to create a new resource type by subclassing BaseResource, defining its endpoint and parameters, and then using it for operations like saving, retrieving, updating, and deleting. ```python from reclaim_sdk.resources.base import BaseResource from reclaim_sdk.client import ReclaimClient from typing import ClassVar, Optional from pydantic import Field class CustomResource(BaseResource): ENDPOINT: ClassVar[str] = "/api/custom" USER_PARAM_REQUIRED: ClassVar[bool] = False name: Optional[str] = None value: Optional[int] = Field(None, alias="customValue") # Use it resource = CustomResource(name="Test", value=42) resource.save() print(resource.id) # Server-assigned resource = CustomResource.get(resource.id) resource.value = 100 resource.save() resource.delete() ``` -------------------------------- ### Perform HTTP GET Request Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/api-reference/reclaim-client.md Perform an HTTP GET request to a specific endpoint. Useful for retrieving data. Query parameters can be passed via the `params` argument. ```python current_user = client.get("/api/users/current") ``` -------------------------------- ### List, Create, Update, and Manage Smart Meetings Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/api-reference/smart-meeting.md Demonstrates the full lifecycle of a smart meeting, from listing existing meetings to creating, updating, and performing various planner actions like locking, skipping, rescheduling, moving, and clearing exceptions. It also shows how to delete the entire series. ```python from reclaim_sdk.resources.smart_meeting import ( SmartMeeting, CreateSmartMeetingRequest, PatchSmartMeetingRequest, Organizer, RecurrenceDefinition, ) from reclaim_sdk.enums import ( SmartSeriesEventType, DefenseAggression, TimePolicyType, Frequency, SnoozeOption, ) from datetime import datetime, timezone, timedelta # List all smart meetings meetings = SmartMeeting.list() # Create a recurring meeting meeting = SmartMeeting.create( CreateSmartMeetingRequest( title="Weekly 1:1", event_type=SmartSeriesEventType.ONE_ON_ONE, ideal_time="14:00:00", duration_min_mins=30, defense_aggression=DefenseAggression.HIGH, organizer=Organizer(time_policy_type=TimePolicyType.WORK), recurrence=RecurrenceDefinition( frequency=Frequency.WEEKLY, ideal_days=["MONDAY"], ), ) ) # Update the series meeting.update( PatchSmartMeetingRequest( title="Weekly 1:1 Sync", duration_min_mins=45, ) ) # Planner actions on instances meeting.lock() meeting.unlock() meeting.skip() meeting.reschedule(SnoozeOption.NEXT_WEEK) now = datetime.now(timezone.utc) new_start = now + timedelta(days=1) new_end = new_start + timedelta(hours=1) meeting.move(new_start, new_end) meeting.clear_exceptions() # Delete the series meeting.delete() ``` -------------------------------- ### Test User Injection for BaseResource List and Get Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/docs/superpowers/plans/2026-04-21-reclaim-api-parity.md Tests ensure that the user parameter is correctly injected when required for list and get operations on BaseResource subclasses. It also verifies that injection is skipped when not required. ```python from typing import ClassVar import httpx from pydantic import Field from reclaim_sdk.resources.base import BaseResource class _Sample(BaseResource): ENDPOINT: ClassVar[str] = "/api/sample" USER_PARAM_REQUIRED: ClassVar[bool] = True title: str | None = Field(None) def test_list_injects_user_when_required(client, mock_api): mock_api.get("/api/users/current").mock( return_value=httpx.Response(200, json={"id": 7}) ) route = mock_api.get("/api/sample").mock( return_value=httpx.Response(200, json=[]) ) _Sample.list() assert route.called assert "user" in dict(route.calls.last.request.url.params) def test_get_injects_user_when_required(client, mock_api): mock_api.get("/api/users/current").mock( return_value=httpx.Response(200, json={"id": 7}) ) route = mock_api.get("/api/sample/1").mock( return_value=httpx.Response(200, json={"id": 1, "title": "x"}) ) _Sample.get(1) assert "user" in dict(route.calls.last.request.url.params) def test_no_user_injection_when_not_required(client, mock_api): class _NoUser(BaseResource): ENDPOINT: ClassVar[str] = "/api/nouser" title: str | None = Field(None) route = mock_api.get("/api/nouser").mock(return_value=httpx.Response(200, json=[])) _NoUser.list() assert "user" not in dict(route.calls.last.request.url.params) ``` -------------------------------- ### Create and Save a Task Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/api-reference/task.md Demonstrates how to instantiate and save a new task with specified properties like title, notes, duration, priority, and event category. ```python from reclaim_sdk.resources.task import Task from reclaim_sdk.enums import TaskStatus, PriorityLevel, SnoozeOption from reclaim_sdk.client import ReclaimClient from datetime import datetime, timezone # Configure once ReclaimClient.configure(token="your_api_key") # Create a task task = Task( title="Implement auth", notes="Add JWT support", duration=4.0, # 4 hours priority=PriorityLevel.P1, event_category=TaskStatus.WORK, ) task.save() print(f"Created task {task.id}") ``` -------------------------------- ### Get Daily Habit Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/api-reference/daily-habit.md Retrieves a specific daily habit by its ID. ```APIDOC ## GET /daily-habits/{habit_id} ### Description Retrieves a specific daily habit by its ID. ### Method GET ### Endpoint /daily-habits/{habit_id} ### Parameters #### Path Parameters - **habit_id** (string) - Required - The unique identifier of the habit to retrieve. ### Response #### Success Response (200) - **habit** (object) - The daily habit object with all its properties. #### Response Example ```json { "id": "habit_12345", "title": "Morning meditation", "duration_min": 15, "enabled": true } ``` ``` -------------------------------- ### Build Source Distribution Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/CLAUDE.md Creates a source distribution (sdist) and a wheel binary for the package. This is typically done in CI. ```bash python setup.py sdist bdist_wheel ``` -------------------------------- ### ReclaimClient Configuration Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/CLAUDE.md Demonstrates how to configure the ReclaimClient, which acts as a singleton wrapper for httpx.Client. The token can be provided directly or resolved from the RECLAIM_TOKEN environment variable. ```python client = ReclaimClient() client.configure(token=os.environ.get("RECLAIM_TOKEN")) ``` -------------------------------- ### ReclaimClient.get Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/api-reference/reclaim-client.md Performs an HTTP GET request to a specified endpoint with optional query parameters. ```APIDOC ## get ### Description HTTP GET request. ### Method Signature ```python def get(endpoint: str, **kwargs) -> Dict[str, Any] ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters Table | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | endpoint | str | Yes | Path | | params | dict | No | Query parameters | ### Returns Parsed JSON response. ### Example ```python current_user = client.get("/api/users/current") ``` ``` -------------------------------- ### Move Smart Meeting Instance Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/api-reference/smart-meeting.md Moves a specific instance of a smart meeting to a new start and end time. ```APIDOC ## Move Smart Meeting Instance ### Description Moves a specific instance of a smart meeting to a new time. ### Method POST ### Endpoint /smart_meetings/{meeting_id}/instances/{instance_id}/move ### Parameters #### Path Parameters - **meeting_id** (string) - Required - The ID of the smart meeting series. - **instance_id** (string) - Required - The ID of the specific meeting instance to move. #### Request Body - **new_start** (datetime) - Required - The new start time for the meeting instance. - **new_end** (datetime) - Required - The new end time for the meeting instance. ``` -------------------------------- ### Interval Model Definition Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/types.md Represents a single time slot with start and end times. It can optionally include a duration. ```python class Interval(BaseModel): start: time end: time duration: Optional[float] = None ``` -------------------------------- ### Verify Reclaim Client Singleton Pattern Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/INDEX.md Demonstrates that the ReclaimClient follows a singleton pattern, ensuring all resources share the same client instance. ```python c1 = ReclaimClient() c2 = ReclaimClient() assert c1 is c2 # True ``` -------------------------------- ### Test Changelog All with Live Client Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/docs/superpowers/plans/2026-04-21-reclaim-api-parity.md Verifies that the `Changelog.all()` method returns a list when called with a live client. ```python import pytest from reclaim_sdk.resources.changelog import Changelog pytestmark = pytest.mark.live def test_changelog_all(live_client): assert isinstance(Changelog.all(), list) ``` -------------------------------- ### Run Full Test Suite Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/docs/superpowers/plans/2026-04-21-reclaim-api-parity.md Execute the unit tests with coverage reporting. Ensures all tests pass and coverage meets the minimum threshold. ```bash pytest tests/unit --cov=reclaim_sdk -v ``` -------------------------------- ### create_at_time Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/api-reference/task.md Create and immediately schedule a task for a specific point in time. Requires a Task object and a UTC datetime for scheduling. ```APIDOC ## create_at_time ### Description Create and immediately schedule a task for a specific time. ### Method `@classmethod` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **task** (Task) - Required - Unsaved task instance - **start_time** (datetime) - Required - When to schedule (UTC) - **client** (ReclaimClient) - Optional - Client override ### Response #### Success Response - **Task** - Created and scheduled `Task` ``` -------------------------------- ### Configure Reclaim SDK with configure Method Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/README.md Use the ReclaimClient.configure method to set up the client with your API token. This method can be used at any point before making API calls. ```python from reclaim_sdk.client import ReclaimClient ReclaimClient.configure(token="YOUR_API_KEY") ``` -------------------------------- ### SmartMeeting.list Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/api-reference/smart-meeting.md Retrieves a list of all smart meetings associated with the current user. Useful for getting an overview of all scheduled smart meetings. ```APIDOC ## list SmartMeetings ### Description List all smart meetings for the current user. ### Method `@classmethod list(client: ReclaimClient = None, **params) -> List["SmartMeeting"]` ### Parameters #### Query Parameters - **client** (ReclaimClient) - Optional - Client override - **params** - Optional - Additional parameters for filtering the list ### Response #### Success Response - **List[SmartMeeting]** - List of `SmartMeeting` instances ### Example ```python meetings = SmartMeeting.list() for m in meetings: print(f"{m.active_series.title}: {m.status}") ``` ``` -------------------------------- ### Get Daily Habit by ID Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/api-reference/daily-habit.md Fetches a single daily habit using its unique identifier. Requires the habit ID. ```python from reclaim_sdk.resources.habit import DailyHabit habit = DailyHabit.get(789) print(habit.title, habit.enabled) ``` -------------------------------- ### ReclaimClient.__new__ Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/api-reference/reclaim-client.md Returns the singleton instance of the ReclaimClient. Initializes from the RECLAIM_TOKEN environment variable if configure() has not been called. ```APIDOC ## __new__ ### Description Returns the singleton instance. Initializes from `RECLAIM_TOKEN` environment variable if `configure()` has not been called. ### Method Signature ```python def __new__(cls) -> "ReclaimClient" ``` ### Parameters None ### Raises `ValueError` if no token is provided via `configure()` or `RECLAIM_TOKEN` env var. ### Example ```python import os os.environ["RECLAIM_TOKEN"] = "your_api_key" # Automatically uses RECLAIM_TOKEN client = ReclaimClient() ``` ``` -------------------------------- ### Configure Reclaim Client with API Key Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/INDEX.md Configure the ReclaimClient using either an environment variable or the configure() method. Obtain your API key from the Reclaim.ai developer settings. ```python import os from reclaim_sdk.client import ReclaimClient # Method 1: Environment variable os.environ["RECLAIM_TOKEN"] = "your_api_key" client = ReclaimClient() # Method 2: configure() method ReclaimClient.configure(token="your_api_key") client = ReclaimClient() # Get API key: https://app.reclaim.ai/settings/developer ``` -------------------------------- ### Get a Single Time Scheme Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/api-reference/hours.md Fetch a specific time scheme by its unique ID. Raises RecordNotFound if the scheme does not exist. ```python from reclaim_sdk.resources.hours import Hours scheme = Hours.get("550e8400-e29b-41d4-a716-446655440000") print(scheme.title, scheme.policy_type) ``` -------------------------------- ### Commit Changes Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/docs/superpowers/plans/2026-04-21-reclaim-api-parity.md Stage and commit changes for the 0.7.0 release, including documentation, examples, CI configuration, and version bump. ```bash git add CHANGELOG.md README.md reclaim_sdk/__init__.py examples/ .github/workflows/ci.yml git commit --no-gpg-sign -m "chore: 0.7.0 release — docs, examples, CI, version bump" ``` -------------------------------- ### Daily Habit Management with Reclaim SDK Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/api-reference/daily-habit.md Demonstrates the full lifecycle of a daily habit, including creation, listing, fetching, modification, toggling, planner actions, and deletion. Ensure the ReclaimClient is configured with your API key before use. ```python from reclaim_sdk.resources.habit import DailyHabit from reclaim_sdk.enums import EventCategory, PriorityLevel from reclaim_sdk.client import ReclaimClient # Configure once ReclaimClient.configure(token="your_api_key") # Create a habit habit = DailyHabit( title="Morning meditation", description="10 min meditation", duration_min=10, duration_max=15, ideal_time="06:00:00", priority=PriorityLevel.P2, event_category=EventCategory.PERSONAL, ) habit.save() print(f"Created habit {habit.id}") # List habits all_habits = DailyHabit.list() for h in all_habits: print(f"{h.title}: enabled={h.enabled}") # Fetch and modify habit = DailyHabit.get(habit.id) habit.duration_min = 15 habit.save() # Toggle on/off habit.toggle(False) # Disable habit.toggle(True) # Re-enable # Planner actions habit.start() habit.stop() habit.clear_exceptions() # Delete habit.delete() ``` -------------------------------- ### Test Task Lifecycle with Live Client Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/docs/superpowers/plans/2026-04-21-reclaim-api-parity.md Tests the full lifecycle of a Task resource, including creation, updates, planner actions, and retrieval. Requires a live client and tracked IDs. ```python import pytest from datetime import datetime, timedelta, timezone from reclaim_sdk.resources.task import Task from reclaim_sdk.enums import PriorityLevel, TaskSource, SnoozeOption pytestmark = pytest.mark.live def test_task_full_lifecycle(live_client, tracked_ids, prefix): task = Task( title=f"{prefix} lifecycle", priority=PriorityLevel.P3, taskSource=TaskSource.RECLAIM, ) task.duration = 1.0 task.save() tracked_ids["tasks"].append(task.id) assert task.id is not None assert task.title.startswith(prefix) # update task.notes = "updated" task.save() task.refresh() assert task.notes == "updated" # planner actions task.start() task.stop() task.snooze(SnoozeOption.ONE_HOUR) task.clear_snooze() task.mark_complete() task.mark_incomplete() # found in list listed = [t.id for t in Task.list()] assert task.id in listed ``` -------------------------------- ### Get Webhook by ID Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/api-reference/webhook.md Fetches a single webhook subscription using its unique identifier. This is useful for retrieving the details of an existing webhook. ```APIDOC ## GET /api/team/current/webhooks/{id} ### Description Fetches a single webhook by its ID. ### Method GET ### Endpoint `/api/team/current/webhooks/{id}` ### Parameters #### Path Parameters - **id** (int) - Required - Webhook ID #### Query Parameters None ### Request Example None (GET request) ### Response #### Success Response (200) - **id** (int) - Webhook ID (server-assigned) - **created** (datetime) - Creation timestamp (server-assigned) - **updated** (datetime) - Last update timestamp (server-assigned) - **name** (str) - Display name (3-40 characters) - **url** (str) - Receiver URL (where Reclaim sends events) - **events** (list[str]) - Subscribed event types - **secret** (str) - HMAC signing secret (optional; for signature verification) - **status** (str) - Webhook status: ACTIVE, SUSPENDED, DISABLED, DOWNGRADED - **api_version** (str) - Webhook API version - **created_at** (datetime) - Creation timestamp (alternate field name) #### Response Example ```json { "id": 123, "created": "2023-10-27T10:00:00Z", "updated": "2023-10-27T10:00:00Z", "name": "Task Events", "url": "https://example.com/webhooks/tasks", "events": ["task.created", "task.updated"], "secret": "your_signing_secret", "status": "ACTIVE", "api_version": "v1", "created_at": "2023-10-27T10:00:00Z" } ``` ``` -------------------------------- ### Configure Reclaim SDK with Environment Variables Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/configuration.md Use this configuration to set up the ReclaimClient with your API token and base URL, which are read from environment variables. Ensure the RECLAIM_TOKEN environment variable is set. ```python # config.py import os from reclaim_sdk.client import ReclaimClient def configure_reclaim(): token = os.environ.get("RECLAIM_TOKEN") if not token: raise ValueError("RECLAIM_TOKEN environment variable not set") base_url = os.environ.get( "RECLAIM_BASE_URL", "https://api.app.reclaim.ai" ) ReclaimClient.configure(token=token, base_url=base_url) ``` ```python # main.py from config import configure_reclaim from reclaim_sdk.resources.task import Task configure_reclaim() tasks = Task.list() ``` -------------------------------- ### Get Current User Information Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/api-reference/reclaim-client.md Retrieve information about the currently authenticated user. This data is cached and corresponds to the response from the `/api/users/current` endpoint. ```python user = client.current_user() user_id = user.get("id") ``` -------------------------------- ### Handle SignatureVerificationError in Webhooks Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/errors.md Example of how to catch `SignatureVerificationError` when verifying webhook signatures. This is crucial for ensuring the integrity of incoming webhook data. ```python from reclaim_sdk.webhooks.signature import verify_signature from reclaim_sdk.exceptions import SignatureVerificationError @app.post("/webhooks/reclaim") def handle_webhook(request): body = request.get_data() signature = request.headers.get("x-reclaim-signature") try: verify_signature(body, signature, webhook_secret) except SignatureVerificationError as e: print(f"Signature mismatch: {e}") return {"error": "Unauthorized"}, 401 # Process webhook event = parse_webhook_payload(body) ... ``` -------------------------------- ### Move Meeting Instance Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/_autodocs/api-reference/smart-meeting.md Move a meeting instance to a new specified time slot. Requires both the new start and end times in UTC. ```APIDOC ## move ### Description Move an instance to a new time slot. ### Method Python Function Call ### Parameters #### Query Parameters - **start** (datetime) - Required - New start (UTC) - **end** (datetime) - Required - New end (UTC) ### Returns Action result with updated events/series (`SmartSeriesActionPlannedResult`) ### Request Example ```python from datetime import datetime, timezone, timedelta now = datetime.now(timezone.utc) new_start = now + timedelta(days=1, hours=2) new_end = new_start + timedelta(hours=1) result = meeting.move(new_start, new_end) ``` ``` -------------------------------- ### Test Habit Lifecycle with Live Client Source: https://github.com/labiso-gmbh/reclaim-sdk/blob/master/docs/superpowers/plans/2026-04-21-reclaim-api-parity.md Tests the lifecycle of a DailyHabit resource, including creation, saving, and toggling. Requires a live client and tracked IDs. ```python import pytest from reclaim_sdk.resources.habit import DailyHabit pytestmark = pytest.mark.live def test_habit_lifecycle(live_client, tracked_ids, prefix): h = DailyHabit(title=f"{prefix} habit") h.save() tracked_ids["habits"].append(h.id) h.toggle(enable=False) h.toggle(enable=True) ```