Common Patterns
Hướng dẫn các pattern thường dùng khi tích hợp với External API.
Pagination
Tất cả list endpoints hỗ trợ pagination qua query params:
GET /api/v1/external/listings?page=1&limit=20
Response:
{
"items": [
{ "id": "uuid", "name": "Villa Đà Lạt" }
],
"total": 100,
"page": 1,
"limit": 20,
"total_pages": 5
}
Best Practice: Sử dụng cursor-based pagination nếu available để tránh skip items khi có changes trong khi paginate.
Filtering
Một số endpoints hỗ trợ filtering:
Filter theo Teams
Listings:
# Lấy từ tất cả teams trong token
GET /api/v1/external/listings
# Filter theo teams cụ thể (JSON array string)
GET /api/v1/external/listings?team_ids=[1,2,3]
Bookings:
# Lấy từ tất cả teams
GET /api/v1/external/bookings
# Filter theo teams và customer
GET /api/v1/external/bookings?team_ids=[1,2]&user_id=200
Lưu ý:
- Format
team_ids: JSON array string"[1,2,3]" - Chỉ các teams hợp lệ (thuộc token) mới được sử dụng
- Nếu không có
team_ids, API trả về từ tất cả teams trong token
Filter khác
# Lọc theo status
GET /api/v1/external/listings?state=ACTIVE
# Lọc bookings theo state
GET /api/v1/external/bookings?state=CONFIRMED
# Lọc theo location
GET /api/v1/external/listings?country_code=VN&province_code=SG
Sorting
GET /api/v1/external/listings?sort_by=created_at&sort_order=desc
Error Handling
Error Response Format
{
"code": "LISTING_NOT_FOUND",
"message": "Listing not found",
"details": {}
}
Common Error Codes
| Code | HTTP Status | Description |
|---|---|---|
VALIDATION_ERROR | 400 | Request body không hợp lệ |
EXTERNAL_INVALID_REQUEST | 400 | Invalid request format (e.g., invalid team_ids JSON) |
EXTERNAL_INVALID_STATE | 400 | Invalid state value |
EXTERNAL_INVALID_DATE_FORMAT | 400 | Invalid date format |
LISTING_NOT_FOUND | 404 | Listing không tồn tại |
BOOKING_NOT_FOUND | 404 | Booking không tồn tại |
EXTERNAL_LISTING_NOT_ACCESSIBLE | 404 | Listing không tồn tại hoặc không thuộc teams của token |
EXTERNAL_BOOKING_NOT_ACCESSIBLE | 404 | Booking không tồn tại hoặc không thuộc teams của token |
EXTERNAL_CUSTOMER_NOT_ACCESSIBLE | 403 | Customer không thuộc teams của token |
EXTERNAL_BOOKING_ID_REQUIRED | 400 | external_booking_id required when external_system provided |
RATE_LIMIT_EXCEEDED | 429 | Quá rate limit |
Retry Strategy
import time
def retry_with_backoff(func, max_retries=3):
for i in range(max_retries):
try:
return func()
except Exception as e:
if i == max_retries - 1:
raise
wait_time = 2 ** i # 1, 2, 4 seconds
time.sleep(wait_time)
Rate Limiting
Xem headers để theo dõi rate limit:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1700000000
Best Practice:
- Implement exponential backoff khi nhận 429
- Cache data nếu có thể để giảm số requests
Webhooks
Sử dụng webhooks để nhận notifications thay vì polling:
# Example webhook handler
@app.route('/webhook', methods=['POST'])
def handle_webhook():
payload = request.json
event_type = payload.get('event_type')
if event_type == 'booking.created':
booking_id = payload.get('data', {}).get('id')
# Process booking
Xem thêm: Webhooks