Errors & rate limits
Error codes
The iClinic Integration API always returns an error in the form { requestId, error: { code, message } }. Handle errors by code, not by message. The message text is written for people, is in Vietnamese, and can change.
| HTTP | error.code | When | Retry? |
|---|---|---|---|
| 400 | INVALID_DATE | from or to is missing or has the wrong format. | No: fix the request |
| 400 | INVALID_RANGE | to is before from, or the range is longer than 31 days. | No: fix the request |
| 400 | INVALID_STATUS | status is not valid. | No: fix the request |
| 400 | INVALID_PAGE | page or pageSize is not valid. | No: fix the request |
| 400 | INVALID_UPDATED_SINCE | updatedSince is not an ISO 8601 timestamp with a time zone, or it appears more than once. | No: fix the request |
| 400 | INVALID_CURSOR | cursor is not valid, or it was issued by a different path. | No: use the exact nextCursor |
| 400 | INVALID_LIMIT | limit is not an integer from 1 to 500. | No: fix the request |
| 400 | UNKNOWN_PARAMETER | The request includes a parameter that this path does not support (new paths only; /encounters still ignores unknown parameters). | No: fix the request |
| 401 | UNAUTHORIZED | The key is missing, incorrect or revoked, or the clinic is suspended. | No: check the key |
| 403 | INSUFFICIENT_SCOPE | The key is valid but does not have the scope to read this path. | No: ask the clinic admin for the scope |
| 404 | NOT_FOUND | The key's clinic has no record with this id. | No |
| 405 | METHOD_NOT_ALLOWED | Only GET is supported. | No |
| 429 | RATE_LIMITED | You exceeded the rate limit, or your IP address is temporarily blocked. | Yes: after the delay in Retry-After |
| 5xx | — | Server-side error. | Yes: wait longer after each attempt |
{
"requestId": "req_7c1f3a",
"error": {
"code": "INVALID_RANGE",
"message": "`to` phải sau `from` và khoảng tối đa 31 ngày."
}
}
Rate limits
60requests per minute, counted per key
5wrong-key attempts in 10 minutes, from the same IP address
15′the IP address is blocked temporarily, even if you then send a correct key
Both limits return 429 RATE_LIMITED with a Retry-After header (in seconds). Wait exactly that many seconds, then retry. Do not call repeatedly without waiting.
Do not let your system retry automatically after a wrong key. A loop that keeps sending a wrong key blocks your IP address for 15 minutes. On a
401, stop and tell the person responsible to check the key.
async function callWithRetry(url, options, attempts = 4) {
for (let i = 0; i < attempts; i += 1) {
const res = await fetch(url, options);
if (res.status === 429) {
const seconds = Number(res.headers.get('Retry-After')) || 30;
await new Promise((r) => setTimeout(r, seconds * 1000));
continue;
}
if (res.status >= 500) {
await new Promise((r) => setTimeout(r, 2 ** i * 1000));
continue;
}
return res; // 2xx, 4xx: do not retry
}
throw new Error('Out of attempts');
}
Support
When you contact support, include the requestId of the failed request (it is in the response body and in the X-Request-Id header), the time of the call and the parameters you used. Do not send the API key. If you sent it by mistake, revoke that key immediately.