Skip to content

Errors ​

Every error is an application/problem+json body (RFC 9457) with a stable machine-readable code:

json
{
  "type": "https://partners.finto.lt/docs/errors#validation_failed",
  "title": "Request validation failed",
  "status": 422,
  "code": "validation_failed",
  "detail": "2 fields are invalid.",
  "requestId": "req_8c1f0e6b2a",
  "errors": [
    { "path": "offer.aprc", "message": "Required" },
    { "path": "offer.validUntil", "message": "Must not be in the past" }
  ]
}
  • Branch on code, not on title or detail (those are for people and may be reworded). New codes may be added: treat an unknown one by its HTTP status.
  • errors lists field problems for validation_failed; otherwise it is null. path uses dots and indexes: requirements.0.description.
  • requestId is also in the Finto-Request-Id header of every response, successful or not. Log it, and quote it when you contact Finto.
  • For an application or document that is not yours, the answer is always the same 404, whatever else is wrong with the request.

When to retry ​

StatusRetry?
400, 401, 403, 404, 410, 413, 415, 422No: fix the request, the key, or your state
409Depends on the code: idempotency_key_in_progress yes, after a second; decision_conflict after fetching the application and deciding again; the others no
429Yes, after Retry-After seconds
500, 502, 503, 504, timeoutsYes, with exponential backoff (for example 1, 2, 4, 8 seconds, then every minute). Repeating a POST with the same Idempotency-Key is safe

Codes ​

bad_request ​

400. The body is not valid JSON, or the request is malformed in a way that is not about a specific field.

unauthorized ​

401. The Authorization header is missing, the key is unknown, expired or revoked, or it belongs to the other environment (a fnt_live_ key in the sandbox or the other way round).

ip_not_allowed ​

403. The request did not come from an IP address on your allow-list. detail shows the address Finto saw; send it to Finto if it is yours. In live, every request is checked against the list.

not_found ​

404. No such application, document or endpoint for you. An application that exists but was not sent to you also returns 404, so ids cannot be probed. The sandbox endpoints return 404 in live.

idempotency_key_required ​

400. The POST needs an Idempotency-Key header.

idempotency_key_reused ​

422. You used an Idempotency-Key again for a different request: another body, another application or another endpoint. Use a new key for a different change. (The same key with the same request is not an error: you get the original result back.)

idempotency_key_in_progress ​

409. A request with the same Idempotency-Key is still being processed. Wait a second and retry; you will get its result.

invalid_transition ​

409. The decision status does not follow your current one, for example approved after cancelled, anything but a correction or an outcome after rejected on the same version, terminated before disbursed, or cancelled after the payout with a reason other than withdrawal_right or other. detail says from what to what. See the table in lifecycle.md.

decision_conflict ​

409. You sent previousDecisionId, and it is not your current decision: another decision got in first. Fetch the application, look at decision, and decide again.

application_closed ​

409. The application is closed for you. Only contract_signed, disbursed, cancelled and terminated are accepted now. Usually a race with application.closed: stop working on the application.

application_withdrawn ​

410. The client withdrew consent. The application and its documents are no longer available, and no decisions are accepted. Stop processing.

application_archived ​

410. More than 14 days have passed since your final decision or since the application closed for you; its data is no longer served. The list still shows it without personal data, your decisions stay readable, and reports about the agreement (cancelled with withdrawal_right, terminated) are still accepted.

cursor_expired ​

410. Events after your after cursor were already deleted from the feed (it keeps 30 days). Reconcile with GET /v1/applications?updatedAfter=..., then read the feed without after and store the new lastSequence.

quota_exceeded ​

422. A count limit was reached: 50 decisions or 20 uploads (50 MB) on one application, or 200 sandbox applications per day. See conventions.md.

payload_too_large ​

413. JSON bodies may be up to 64 KB, uploads up to 10 MB.

unsupported_media_type ​

415. The Content-Type is not the expected one (application/json, or multipart/form-data for uploads), or the uploaded file is not a PDF.

validation_failed ​

422. The body or the query parameters do not match the schema, or the values do not fit the application. errors lists every field problem. Common messages:

messageTypical cause
RequiredA required field is missing (offer.aprc)
Required when status is approvedoffer missing with approved; same pattern for other statuses
Not allowed when status is rejectedA field that belongs to another status, such as offer with rejected
Unknown fieldA field name the API does not know, for example offer.apr instead of offer.aprc; check the spelling
Expected numberA value of the wrong type, such as "14500" in quotes
At most 2 decimal placesA money value like 267.891
Must be at least amountoffer.totalAmountPayable below offer.amount
Must not be in the pastoffer.validUntil before today (Vilnius time)
Must be at most 180 days aheadoffer.validUntil too far ahead
Must not be in the futuredecidedAt, contract.signedAt or disbursement.disbursedAt more than 5 minutes ahead of Finto's clock; termination.endedOn after today (Vilnius time)
Must not be before the application was signedOne of those more than a day before the client signed
Must be an https address on your registered domain, without a port, user name or IP addressoffer.continueUrl
Links are not allowed in text shown to the clientA link in offer.conditions or requirements[].description
Contains control or formatting charactersInvisible characters in a text field
Must not be higher than the latest versionapplicationVersion above the application's version
Unknown document: upload it to this application firstAn id in offer.documentIds that is not your own upload on this application
Must not be higher than your latest event sequenceafter in GET /v1/events above your last event, for example a cursor kept from the other environment

Other messages describe the limit that was broken, for example a value out of range or not one of the allowed enum values.

rate_limited ​

429. More than 600 requests per minute with this key, or more than 5 test events (POST /v1/events/test) per minute. Wait Retry-After seconds. A normal integration uses a small fraction of the limit; if you hit it, check for a loop.

internal_error ​

500. Something failed on Finto's side. Retry with backoff; Finto is alerted automatically. If it persists, contact Finto with the requestId.

service_unavailable ​

503. Finto is briefly unavailable, for example during a deployment. Retry with backoff.