Skip to main content
Glama
quickstart.md11.6 kB
# Quickstart: API-Level Response Summarization **Feature**: `009-add-api-level` **Date**: 2025-10-29 --- ## Overview This guide provides a quick reference for implementing and using the API-level response summarization feature. --- ## For Developers ### Implementation Checklist #### Phase 1: Data Models - [ ] Create `src/models/summarized.py` with SummarizedListing and SummarizedBooking - [ ] Extend `src/models/pagination.py` PageMetadata with `note` field - [ ] Add Pydantic validators for ISO 8601 dates - [ ] Write unit tests for model validation #### Phase 2: Route Modifications - [ ] Modify `src/api/routes/listings.py`: - Add `summary: bool` query parameter to `get_listings()` - Add conditional response logic (summary vs. full) - Add logging for summary mode usage - [ ] Modify `src/api/routes/bookings.py`: - Add `summary: bool` query parameter to booking list endpoint - Add conditional response logic - Add logging for summary mode usage - [ ] Update route response_model to use Union types #### Phase 3: Testing - [ ] Write unit tests for summarized models - [ ] Write integration tests for `/api/listings?summary=true` - [ ] Write integration tests for `/api/reservations?summary=true` - [ ] Write integration tests for detail endpoints with summary parameter (verify ignored) - [ ] Validate response size reduction (80-90%) - [ ] Validate backward compatibility (no summary parameter) #### Phase 4: Documentation - [ ] Update OpenAPI docs (auto-generated via FastAPI) - [ ] Update README.md with summary parameter examples - [ ] Add CHANGELOG.md entry - [ ] Update MCP tool descriptions ### Quick Implementation Example **Step 1**: Create summarized models ```python # src/models/summarized.py from pydantic import BaseModel, Field class SummarizedListing(BaseModel): """Summarized property listing.""" id: int = Field(..., description="Unique property listing ID") name: str = Field(..., description="Property display name") city: str | None = Field(None, description="City location") country: str | None = Field(None, description="Country location") bedrooms: int = Field(..., ge=0, description="Number of bedrooms") status: str = Field(..., description="Availability status") class SummarizedBooking(BaseModel): """Summarized booking.""" id: int guestName: str checkIn: str # ISO 8601 YYYY-MM-DD checkOut: str # ISO 8601 YYYY-MM-DD listingId: int status: str totalPrice: float ``` **Step 2**: Extend PageMetadata ```python # src/models/pagination.py class PageMetadata(BaseModel): total: int limit: int offset: int | None = None note: str | None = None # NEW FIELD ``` **Step 3**: Modify route handler ```python # src/api/routes/listings.py from src.models.summarized import SummarizedListing @router.get( "/listings", response_model=PaginatedResponse[dict] | PaginatedResponse[SummarizedListing], summary="Get all property listings", tags=["Listings"], ) async def get_listings( summary: bool = Query(False, description="Return summarized response"), limit: int = Query(50, ge=1, le=200), cursor: str | None = Query(None), client: HostawayClient = Depends(get_authenticated_client), request: Request = None, # For logging correlation_id ) -> PaginatedResponse[dict] | PaginatedResponse[SummarizedListing]: """Get listings with optional summarization.""" # Fetch full data from Hostaway API raw_response = await client.get_listings(limit=limit, offset=offset) items = raw_response.get("items", []) total_count = raw_response.get("count", 0) if summary: # Log summary usage logger.info( "Summary mode request", extra={ "endpoint": "/api/listings", "summary": True, "organization_id": client.organization_id, "correlation_id": request.state.correlation_id, } ) # Transform to summarized items summarized_items = [ SummarizedListing( id=item["id"], name=item["name"], city=item.get("city"), country=item.get("country"), bedrooms=item.get("bedrooms", 0), status="Available" if item.get("isActive") else "Inactive" ) for item in items ] return PaginatedResponse[SummarizedListing]( items=summarized_items, nextCursor=encode_cursor({"offset": offset + limit}), metadata=PageMetadata( total=total_count, limit=limit, offset=offset, note="Use GET /api/listings/{id} to see full property details" ) ) # Return full response (existing logic) return PaginatedResponse[dict]( items=items, nextCursor=encode_cursor({"offset": offset + limit}), metadata=PageMetadata(total=total_count, limit=limit, offset=offset) ) ``` **Step 4**: Write tests ```python # tests/integration/test_listings_summary.py async def test_listings_with_summary_true(client): """Test GET /api/listings?summary=true returns summarized response.""" response = await client.get("/api/listings?summary=true&limit=10") assert response.status_code == 200 data = response.json() assert "items" in data assert "metadata" in data assert data["metadata"]["note"] is not None # Verify summarized fields only first_item = data["items"][0] assert set(first_item.keys()) == {"id", "name", "city", "country", "bedrooms", "status"} async def test_listings_without_summary_returns_full(client): """Test backward compatibility - no summary parameter.""" response = await client.get("/api/listings?limit=10") assert response.status_code == 200 data = response.json() first_item = data["items"][0] # Full response includes more fields assert "description" in first_item or "amenities" in first_item assert len(first_item.keys()) > 6 # More than summarized fields ``` --- ## For API Consumers ### Using the Summary Parameter #### Basic Usage ```bash # Get summarized property list (compact response) curl "http://72.60.233.157:8080/api/listings?summary=true&limit=10" \ -H "X-API-Key: your_api_key" # Get full property list (default behavior) curl "http://72.60.233.157:8080/api/listings?limit=10" \ -H "X-API-Key: your_api_key" ``` #### With MCP (Claude Desktop) ```python # MCP tool invocation (via Claude Desktop) list_properties(limit=10, summary=True) ``` #### Response Examples **Summarized Response** (summary=true): ```json { "items": [ { "id": 12345, "name": "Luxury Villa in Seminyak", "city": "Seminyak", "country": "Indonesia", "bedrooms": 3, "status": "Available" }, { "id": 12346, "name": "Beachfront Apartment", "city": "Canggu", "country": "Indonesia", "bedrooms": 2, "status": "Inactive" } ], "nextCursor": "eyJvZmZzZXQiOjEwfQ==", "metadata": { "total": 150, "limit": 10, "offset": 0, "note": "Use GET /api/listings/{id} to see full property details" } } ``` **Full Response** (summary=false or absent): ```json { "items": [ { "id": 12345, "name": "Luxury Villa in Seminyak", "city": "Seminyak", "country": "Indonesia", "bedrooms": 3, "isActive": true, "description": "Stunning 3-bedroom villa with private pool...", "amenities": ["Pool", "WiFi", "Kitchen", "Air Conditioning"], "pricePerNight": 250.00, "currency": "USD", "minimumStay": 3, "maxGuests": 6, "availabilityCalendar": [...] // ... many more fields } ], "nextCursor": "eyJvZmZzZXQiOjEwfQ==", "metadata": { "total": 150, "limit": 10, "offset": 0 } } ``` ### When to Use Summary Mode **Use `summary=true` when**: - Browsing or filtering large lists - Building UI dropdowns or selection menus - Working with AI assistants (context window limits) - Mobile apps with bandwidth constraints - Displaying search results **Use full response (no summary parameter) when**: - Displaying detailed property pages - Generating booking confirmations - Exporting data for analytics - Integrating with external systems requiring full data ### Accessing Full Details After browsing with `summary=true`, retrieve full details for specific items: ```bash # Step 1: Browse with summary curl "http://72.60.233.157:8080/api/listings?summary=true&limit=10" \ -H "X-API-Key: your_api_key" # Step 2: Get full details for selected property curl "http://72.60.233.157:8080/api/listings/12345" \ -H "X-API-Key: your_api_key" ``` --- ## Performance Comparison ### Response Sizes | Endpoint | Mode | Items | Response Size | Reduction | |----------|------|-------|---------------|-----------| | /api/listings | Full | 10 | ~150KB | - | | /api/listings | Summary | 10 | ~15KB | ~90% | | /api/listings | Full | 50 | ~750KB | - | | /api/listings | Summary | 50 | ~75KB | ~90% | ### Response Times | Endpoint | Mode | Items | Time (95th percentile) | |----------|------|-------|------------------------| | /api/listings | Full | 10 | 500-700ms | | /api/listings | Summary | 10 | 400-600ms | *Note: Summary mode is slightly faster due to reduced serialization overhead.* --- ## Troubleshooting ### Issue: Summary parameter ignored **Symptom**: Using `summary=true` on detail endpoint returns full data **Solution**: This is expected behavior. Detail endpoints (e.g., `/api/listings/123`) always return full data, even with `summary=true`. The parameter is silently ignored to maintain simplicity. ### Issue: Response still too large **Symptom**: Summarized response exceeds expected size **Checklist**: - Verify `summary=true` parameter is included - Check response contains only 6 fields per item (Listings) or 7 fields (Bookings) - Verify `metadata.note` field is present (indicates summary mode) - If still large, consider reducing `limit` parameter (e.g., `limit=5`) ### Issue: Missing fields in summary response **Symptom**: Need additional fields not included in summary **Solution**: Summary mode provides fixed essential fields only. To access additional fields: 1. Use full response mode (no `summary` parameter) 2. Or fetch specific item details via detail endpoint **Out of Scope**: Custom field selection (e.g., `fields=id,name,city`) is not supported. --- ## Next Steps ### For Developers 1. Review `research.md` for technical decisions 2. Review `data-model.md` for entity definitions 3. Review `contracts/api-specification.yaml` for OpenAPI spec 4. Proceed to `/speckit.tasks` to generate implementation tasks ### For API Consumers 1. Test summary parameter with your integration 2. Update client code to use `summary=true` for list operations 3. Monitor response sizes and performance improvements 4. Provide feedback on essential fields selection --- ## Related Documentation - **Specification**: `specs/009-add-api-level/spec.md` - **Research**: `specs/009-add-api-level/research.md` - **Data Model**: `specs/009-add-api-level/data-model.md` - **API Contract**: `specs/009-add-api-level/contracts/api-specification.yaml` - **Constitution**: `.specify/memory/constitution.md` --- ## Support For questions or issues: - Review OpenAPI docs at `/docs` endpoint - Check logs for summary mode usage (INFO level) - Create GitHub issue for bugs or feature requests

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/darrentmorgan/hostaway-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server