Retry Strategy
What to Retry
Only retry idempotent operations or those with transient failures:| Scenario | Retry? | Strategy |
|---|---|---|
| Network timeout | Yes | Exponential backoff |
500 INTERNAL_ERROR | Yes | Exponential backoff with jitter |
429 RATE_LIMIT_EXCEEDED | Yes | Wait 60+ seconds |
400 VALIDATION_ERROR | No | Fix the request first |
401 UNAUTHORIZED | No | Fix the API key |
403 FORBIDDEN | No | Request the permission |
404 NOT_FOUND | No | The resource does not exist |
409 DUPLICATE_EXTERNAL_REFERENCE | No | Use a different reference |
422 business errors | No | Read the error code and handle |
Exponential Backoff
Timeouts
Set a reasonable timeout on all HTTP requests. The CleanLife API is not expected to take more than a few seconds, but network conditions vary. Recommended timeout: 30 seconds per requestIdempotency (Booking Creation)
Although theIdempotency-Key header is currently disabled, you can achieve safe retries using externalReference:
- Before calling
POST /partners/bookings, generate a unique reference (e.g., UUID or your internal order ID). - Store this reference in your database with status
PENDING. - Call the API with
externalReferenceset to this value. - If the request fails with a network error or timeout:
- If you receive
409 DUPLICATE_EXTERNAL_REFERENCE, the booking was created successfully — queryGET /partners/bookings?externalReference=...to retrieve it. - If you receive
422 BOOKING_CREATION_FAILED, the booking failed — retry with the sameexternalReference. - If you receive no response, assume the operation may have succeeded and poll before retrying.
- If you receive
Logging
Log the following for every API call to enable debugging and auditing:| Data | Description |
|---|---|
| Request: method + path | e.g., POST /partners/bookings |
| Request: key fields (not the full body — avoid logging customer PII) | e.g., externalReference, serviceId, date |
| Response: HTTP status code | |
Response: error.code (if error) | |
Response: X-Request-Id | Always log this — needed for support escalation |
| Duration (ms) | For latency monitoring |
Error Handling
Build a structured error handler that distinguishes between error categories:Security
- Store API Key as a secret, not in code. Use environment variables or a secrets manager (e.g., AWS Secrets Manager, HashiCorp Vault, Azure Key Vault).
- Store webhook secrets with the same care as API keys. Never log them.
-
Validate webhook signatures on every delivery. Reject requests that fail validation with
401. - Use HTTPS for all your webhook endpoints. Do not accept webhook deliveries over HTTP.
- Restrict your API Key to a specific IP range if possible. Contact CleanLife to configure an IP allowlist.
- Rotate secrets periodically — both the API key and webhook secrets.
Performance
Cache the Service Catalog
Services and pricing tiers change infrequently. Cache these responses:| Endpoint | Recommended TTL |
|---|---|
GET /partners/services | 1 hour |
GET /partners/pricing/tiers | 1 hour |
Do Not Cache Timeslots
Available timeslots change in real time as bookings are created. Always query fresh.Batch Price Calculations
ThePOST /partners/pricing/calculate-price endpoint accepts up to 10 items in a single request. Use this to calculate prices for multiple service combinations in one call rather than multiple individual calls.
Pagination
Uselimit=100 (the maximum) when fetching large lists to minimize the number of API calls.
Webhook Handling
- Respond with 200 immediately — do not do slow processing inline.
- Use a job queue to process webhook events asynchronously.
- Store and deduplicate by
deliveryId— events can be delivered more than once. - Build for out-of-order delivery — a
booking.appointment_status_changedevent may arrive beforebooking.createdin rare retry scenarios. - Monitor for FAILED deliveries — set up alerts to check
GET /partners/webhooks/deliveries?status=FAILEDperiodically.
Testing
- Use a distinct
externalReferenceprefix for test bookings (e.g.,TEST-) to identify them in production logs. - Test cancellation, update, and payment confirmation flows end-to-end before going live.
- Test your webhook signature verification with a known payload before deployment.
- Simulate webhook failures by temporarily stopping your webhook handler to verify the retry behavior.