| 400 | invalid_argument | Malformed or invalid input regardless of state — missing/empty/non-positive field, a date not in yyyy-MM-dd, a value too long. Field errors are listed in message (see above). |
| 400 | failed_precondition | The resource is in the wrong state for the operation — e.g. updating/deleting/adjusting an already-disbursed loan, or repaying a non-active loan. Fix the state first. |
| 400 | out_of_range | A value is outside the valid range. |
| 401 | unauthenticated | Missing, expired, or invalid bearer token. Refresh the token and retry. |
| 403 | permission_denied | Authenticated, but the caller’s role isn’t authorized for this action. Refreshing the token won’t help. |
| 404 | not_found | No resource exists with that id or externalId. |
| 409 | already_exists | A uniqueness constraint was violated — a re-used externalId on a customer, loan, or repayment (idempotencyKey). |
| 409 | aborted | Conflict — a concurrency issue, or an operation blocked by the resource’s current state (e.g. rolling back a loan that already has repayments). |
| 429 | too_many_requests / resource_exhausted | Rate limit or quota exceeded. Back off and retry. |
| 500 | internal | Unexpected server-side or upstream failure. Detail is withheld from the response and logged. |
| 501 | unimplemented | The operation is not supported. |
| 503 | unavailable | A downstream dependency (core banking / credit service) is temporarily unreachable. |
| 504 | deadline_exceeded / canceled | The request timed out (or was canceled) upstream. |