Best practices and troubleshooting
Integrate the Merchant API with confidence and resolve issues quickly.Status monitoring
Do
- Consult
GET /merchants/{merchantId}/status every 30 seconds as a heartbeat - Store the last known status and alert on changes
- Log when status changes to
ERROR - Analyze all validations returned in the response
- Use the
reopenable field to determine if the store can be reopened - Implement retry with exponential backoff for
5xx errors
Don't
- Use
polling with intervals less than 30 seconds (may result in rate limiting) - Assume
CLOSED means a problem (it might just be outside operating hours) - Ignore messages in the
message field in validations - Try to reopen stores blocked by penalties (
reopenable: false) - Rely only on the
available field without analyzing validations
Interruption management
Do
- Use Interruptions for pauses lasting minutes/hours
- Always provide a clear description of the reason
- Remove interruptions as soon as the issue is resolved
- Test interruptions in development before using in production
Don't
- Use Interruptions for permanent closures (alter
opening-hours instead) - Create very long interruptions (max 7 days)
- Leave interruptions active unnecessarily
- Create many overlapping interruptions
Operating hours management
Do
- Update operating hours via API when they are permanent
- Include all days of the week when sending with
PUT /merchants/{merchantId}/opening-hours - Test overlap validations before submitting
- Use time format
HH:MM:SS (ex: 09:00:00) - Calculate duration in minutes (ex: 360 minutes = 6 hours)
Don't
- Alter hours for short breaks (use
POST /merchants/{merchantId}/interruptions) - Send only some days (this closes the others)
- Create overlapping shifts on the same day
- Mix time zones (use the store's configured timezone)
- Use
PUT to add hours (it replaces completely)
Error handling
Do
- Catch
400 BadRequest errors and inform the user about validation - Catch
409 InterruptionOverlap errors and suggest schedule adjustments - Catch
401 Unauthorized and 403 Forbidden errors to review credentials/permissions - Implement retry with exponential backoff for
500 InternalServerError - Validate that all required fields are present before calling the API
Don't
- Ignore validation errors and retry with the same request
- Assume that a valid token has access to all stores
- Immediately retry on overlap issues (wait and adjust)
- Expose store IDs or tokens in error messages to end users
- Rely only on the
HTTP code without analyzing the response body
Rate Limiting
Do
- Monitor the rate limit headers in API responses
- Implement exponential backoff when receiving
429 Too Many Requests - Spread requests across multiple merchants over time
- Cache store status when possible
- Use
polling intervals of at least 30 seconds
Don't
- Ignore
429 Too Many Requests errors - Make rapid consecutive requests
- Retry immediately on rate limit errors
- Use
polling faster than 30 seconds per store
Rate limits for Merchant API:- Maximum:
1000 requests per second across all endpoints - Error code:
429
When you receive a 429 error:- Extract the
Retry-After header (if provided) - Wait the specified duration before retrying
- Implement exponential backoff: 1s — 2s — 4s — 8s — 16s
- For persistent issues, reduce
polling frequency or batch requests
See detailed information: Rate Limiting DocumentationTroubleshooting
Persistent ERROR status
Problem: Store returns state: ERROR even with normal validationsPossible causes:- Automatic penalty (ex: excessive cancellations)
- Terms of Service violation (
terms-service-violation) - Outstanding financial issues (
payout-blocked) - Logistical problems (
logistics-blocked) - Active interruption (
unavailabilities)
Solution:- Call
GET /merchants/{merchantId}/status - Analyze the
validations[] array to find which code is in ERROR - Check the
message field for details - Actions by type:
unavailabilities — Remove the interruption with DELETE /interruptions/{id}payout-blocked — Access Partner Portal > Financeterms-service-violation — Contact support via Portallogistics-blocked — External issue, wait for resolution
- Wait up to 60 seconds for the platform to process the change
- If not resolved: open a ticket
Interruption not being removed
Problem: DELETE /interruptions/{id} returns 204 (success) but status remains ERRORPossible causes:- There's still another active interruption not removed
- No permission (
403 Forbidden) — but this would have returned an error - Asynchronous propagation (system is still processing)
Solution:- Wait 5 seconds (asynchronous processing)
- Call
GET /merchants/{merchantId}/interruptions to list all active ones - Remove all interruptions found
- Call
GET /merchants/{merchantId}/status to confirm - If persists after a few minutes: open a ticket
Operating hours won't update
Problem: PUT /opening-hours returns 400 (BadRequest) with overlap errorPossible causes:- Shifts on the same day overlap
- Invalid time format
- Negative or zero duration
Solution:Check that no shift starts before another ends:Calculation: start + (duration / 60) = end
Valid example (FRIDAY):
- Shift 1: 05:00 + (420 min) = 12:00 (valid)
- Shift 2: 13:00 + (300 min) = 18:00 (valid)
- Shift 3: 19:00 + (210 min) = 22:30 (valid)
Invalid example:
- Shift 1: 09:00 + (300 min) = 14:00
- Shift 2: 13:00 + (300 min) = 18:00 (invalid — Overlap!)
- Check the error response for specific fields
- Use correct formats —
dayOfWeek (MONDAY-SUNDAY), start (HH:MM:SS), duration (minutes) - Resubmit with non-overlapping shifts
Store not receiving orders (status OK but no sales)
Problem: available: true and state: OK but orders aren't arrivingPossible causes:- Empty or disabled catalog
- Delivery area configured as empty
- Outside operating hours (check
opening-hours) - No regular
polling (validation is-connected)
Solution:- Check hours with
GET /merchants/{merchantId}/opening-hours - Implement
polling GET /merchants/{merchantId}/status every 30 seconds - Check catalog and delivery areas in Partner Portal
- Simulate an order in test environment (if available)
- Open a ticket if everything is correct
Was this page helpful? Rate your experience in the new Developer portal: