LendEasy/DocsLMS + Servicing·v1
Start integrating
Guides›Overview›Errors & status codes

Errors & status codes

The status code tells a client whether to retry; the body tells it what to fix — and a client that reads only one of them gets stuck.

An error answers two different questions at once, and a client that reads only one of them gets stuck. The status code says whether to retry, and when. The body says what to fix, in codes stable enough to branch on.

Every Lending Core error is application/json in one envelope.

One envelope, one entry per bad field

{
  "developerMessage": "Request was understood but rejected; inspect errors for field-level causes.",
  "httpStatusCode": "400",
  "defaultUserMessage": "The request could not be applied.",
  "userMessageGlobalisationCode": "validation.msg.validation.errors.exist",
  "errors": [
    {
      "developerMessage": "stateCode must be a full ISO 3166-2 code matching country.",
      "defaultUserMessage": "stateCode is invalid.",
      "userMessageGlobalisationCode": "validation.msg.address.stateCode.invalid",
      "parameterName": "stateCode",
      "value": "CA"
    }
  ]
}

A form can highlight every violating field at once instead of walking a borrower through them one round trip at a time. Unknown body fields and unknown query parameters are rejected with 400 rather than silently discarded — a mistyped field name that was accepted and ignored is a value you believe you sent and the loan never saw.

The status says whether to retry

Ten rows, and the last column is the one your retry logic reads:

Status Meaning Retry?
200 Successful read, or a mutation’s command receipt {resourceId, changes}. No.
201 Payment or funding created; Location names the new resource. No — a replayed create returns the original result with x-served-from-cache: true.
400 Malformed request: unknown field or query parameter, invalid value, or a missing or invalid tenant header. Fix request.
401 Token missing, invalid, expired, or wrong environment. Refresh once; then stop.
403 Authenticated but missing the named permission, required case context, or valid actor-to-case relationship. Change authority, not timing.
404 Resource absent or outside tenant visibility. Verify ID and environment.
409 Lifecycle-state conflict, an in-flight idempotent duplicate (includes Retry-After), or a second entry for a SINGLE-mode form. Read current state, or wait Retry-After.
422 Well-formed request violates a business rule, including an idempotency payload fingerprint mismatch. Correct inputs, or follow the review path.
429 Current rate budget exceeded. Honor Retry-After; same key.
5xx Server or dependency failure; outcome may be unknown. Back off; same key.

Not every 409 is a duplicate create

Three conditions arrive under the same status:

  • in-flight idempotency: the same key’s original attempt is still executing, and the response carries Retry-After;
  • state conflict: the operation is not valid from the resource’s current lifecycle state;
  • single-entry conflict: a second entry for a SINGLE-mode form on the same target.

A reused key with a different payload on a money create is not a 409 — it is a 422 fingerprint mismatch. Blind retries cannot resolve a semantic conflict.

A 200 can carry bad news

A loan summary read can succeed while reporting that no payoff can be quoted:

{
  "loanRef": "7204",
  "payoff": { "available": false },
  "asOf": "2026-09-20T10:00:00Z"
}

That is 200: the read model worked and the business answer is “not available right now.” A 503 means no reliable answer was produced, and the caller follows fail-closed degraded behavior. Collapsing the two — rendering a 503 as “no payoff available” — turns an outage into a statement, and the borrower is told something nobody computed.

Servicing shares the envelope, plus one smaller form

Implemented operations under /v1/servicing use the same response shape, with the same globalisation codes and parameter names. A request rejected at the shared tenant boundary returns the smaller safe form:

{
  "code": "tenant.header.invalid"
}

Every servicing operation returns the same application/problem+json contract, so one parser handles the whole surface.

Keep the correlation IDs, drop everything else

Retain the request correlation identifiers your client and the response headers carry: they are how somebody finds your exact call among a day of traffic. Keep bearer tokens, raw personal data, provider credentials, full document payloads, and sensitive error inputs out of those same logs — a support report travels further than the request that produced it, and to more people.

The whole policy in seven lines

A network timeout does not prove failure. Treat the outcome as unknown and recover with the same idempotency key or status read; never create a second money movement to “make sure.”
Unified search across guides, recipes & the API referenceEsc