Fincheck

Errors

Read an error response and decide whether to correct, retry, or contact support.

FincheckEngine uses standard HTTP status codes. A 2xx status means the request succeeded, 4xx means something in the request needs to change, and 5xx means something went wrong on Fincheck's side. Every error body carries a stable code and a human-readable message: branch on code, because a message may be reworded.

Status codes

StatusWhat it meansSuggested action
400The JSON, form, or file could not be read.Fix the request format. Do not retry unchanged.
401The API key is missing or rejected.Send Authorization: Bearer fce_… with a key for this environment. See Authentication.
403The key cannot access this resource, for example another affiliate's batch.Use the key that created the resource. Do not retry unchanged.
404The lead, intent, or batch does not exist in this environment, or the lead is not yours.Check the id and the environment.
415POST /lead or POST /offer was not sent as application/json.Send Content-Type: application/json.
422The request was read, but a field or business rule failed.Correct the fields named in the response, then send again.
500An unexpected error occurred.Retry with backoff. Contact support if it keeps happening.
503The API is in maintenance, processing took longer than the request allows, or the intent you named is temporarily unavailable (intent_unavailable).Retry later with backoff. Keep any id you already received.

Error responses

JSON
{
  "code": "lead_already_accepted",
  "message": "This lead has already been accepted."
}

A message is a sentence for people to read or log. It may be reworded, so never match on it. Field messages inside errors (see Field validation) are short phrases that read with the field name, such as is required.

Some errors add a field: missing_fields on intent_schema_validation_failed, row_errors on batch_rows_invalid. A batch row's problems use their own, simpler shape; see Batch Import.

Every error

CodeHTTP statusMessageCauseWhat to do
batch_invalid_request400Invalid JSON body. (example; the text names the problem)The body, form or file could not be read, e.g. leads file is required, leads file must be .xlsx, .xls, or .csv, or map must be a JSON object.Fix the upload. Do not retry it unchanged.
empty_batch400No leads found.The file or leads array had no rows.Check the file has a header row and at least one lead.
invalid_batch_id400Invalid batch id.The batch id is not a number.Use the batch_id from the upload response.
invalid_json400Invalid JSON body.The body could not be read as JSON.Fix the request body. Do not retry it unchanged.
forbidden403Forbidden.The batch belongs to another affiliate.Use the key that uploaded it.
batch_not_found404Batch not found.No batch has that id in this environment.Check the batch_id and the environment.
intent_not_found404Intent not found.No active intent has that id in this environment.Use an id from GET /intent.
lead_not_found404Lead not found.The lead does not exist in this environment, or is not yours.Use the id from your POST /offer response.
lead_not_found404Lead not found.The lead does not exist in this environment, or is not yours.Check the id and the environment.
unsupported_media_type415Content-Type must be application/json.The body was not sent as application/json.Send Content-Type: application/json.
batch_rows_invalid4223 row(s) failed validation. (example; the text names the problem)Rows broke their field rules; row_errors lists each row and field. Nothing was queued.Correct the rows and upload the batch again.
batch_too_large422Batch exceeds the maximum of 10000 rows. (example; the text names the problem)The batch has more rows than allowed.Split it into smaller batches.
intent_inactive422This intent is not accepting leads.The intent exists but is switched off.Choose an active intent from GET /intent.
intent_not_found422Intent not found.No intent has that title or id in this environment.Use a title or id from GET /intent. Intents differ between environments.
intent_required422Either intent_id or intent is required.The batch did not name an intent.Send intent or intent_id for the batch.
intent_schema_validation_failed422Intent schema validation failed.Rare: the intent's required fields changed while the request was processed; missing_fields lists them.Add the fields in missing_fields and send again.
invalid_result_url422The result_url must be an absolute http or https URL.result_url is not an absolute http(s) URL.Send an absolute URL, or leave result_url out.
lead_already_accepted422This lead has already been accepted.The lead was already sent to a partner.Do not accept it again.
lead_not_acceptable422This lead is not in a matched, declined, or failed state.The lead was not matched by POST /offer, or has moved on.Check the lead with GET /lead/{hashid}.
partner_not_assigned422This partner is not assigned to the intent.The partner does not take leads for this intent.Choose a partner from the offer's matches.
partner_not_eligible422This partner is not currently a valid choice for the lead.The partner no longer qualifies for this applicant.Let the applicant choose another match.
partner_unavailable422This partner has no redirect_url configured.The partner cannot receive the applicant yet.Let the applicant choose another match, and tell support.
referee_not_found422The referee_id was not found.No affiliate has that referee_id.Check the referee_id, or leave it out.
validation_failed422Validation failed.One or more fields broke their rules; errors lists each problem per field with its code.Correct the named fields, then send again.
internal_error500Internal error.An unexpected error on Fincheck's side.Retry with backoff. Contact support if it keeps happening.
intent_unavailable503This intent is temporarily unavailable.The intent exists and is active, but its saved validation rules can't be used right now.Retry later with backoff, or use another intent. Contact support if it keeps happening.
processing_timeout503Processing is taking longer than expected. Please retry.The request is still being processed after the time it is allowed.Retry later with backoff. Keep any id you already received.

Errors without a code

A few errors are sent before your API key is identified, so FincheckEngine does not yet know which contract you are on. Their body has only an error field and no code, so branch on the HTTP status. See Authentication.

HTTP statusResponse bodyCauseWhat to do
401{"error":"api key expired"}The API key has passed its expiry date.Ask Fincheck for a new key.
401{"error":"unauthorized"}The API key is missing or not recognised.Send Authorization: Bearer fce_… with a key for this environment.
503{"error":"system maintenance in progress"}The API is in a maintenance window.Retry later with backoff.

Field validation

JSON
{
  "code": "validation_failed",
  "message": "Validation failed.",
  "errors": {
    "id_number": [{ "code": "invalid_format", "message": "must be a valid RSA ID number" }],
    "payment_frequency": [{ "code": "not_in_enum", "message": "must be one of: weekly, fortnightly, monthly, other" }]
  }
}

Each key in errors is a JSON field you sent, listing the first problem found with it: a stable code to branch on and a message to show or log. Every field with a problem is reported at once. Read the keys as they are: they match your request fields exactly.

Intent problems are separate. A missing intent, or an intent and intent_id that disagree, are field problems on intent. An unknown, inactive or unavailable intent is a request-level error (intent_not_found, intent_inactive, intent_unavailable) listed above, and is returned without field problems. See Intent Fields.

Field codeMeaning
requiredThe field is required and was not sent (null and blank count as not sent).
invalid_typeThe value has the wrong JSON type, e.g. "5000" instead of 5000.
unsupported_fieldThe field is not accepted on v2; the message names the replacement.
not_in_enumThe value is not one of the field's allowed values.
below_minimumThe number is below the field's minimum.
above_maximumThe number is above the field's maximum.
too_shortThe text or list is shorter than allowed.
too_longThe text or list is longer than allowed.
invalid_formatThe value is not in the required format (e.g. SA ID number, SA mobile, email).
invalid_valueThe value is not acceptable for the field, e.g. popi is not true, or intent does not match intent_id.
age_out_of_rangeThe applicant's age, from id_number, is outside the allowed range.
exceeds_fieldThe value is greater than the field it may not exceed (net_income over gross_income).

Each field's type and allowed values are in the field tables, for example Sending a Lead. An intent can require more fields and narrow the limits; see Intent Fields. These rules apply to POST /lead, POST /offer and every POST /lead/batch row.

Retrying safely

  • Correct 400, 401, 403, 404, and 422 responses before sending again. Retrying them unchanged gives the same result.
  • Retry 500 and 503 with exponential backoff, for example after 1, 2, 4, and 8 seconds, and then stop.
  • Resending a POST /lead or POST /offer for the same applicant does not send them to a partner twice. Check result: duplicate returns the lead you already have. See Duplicate Submissions.
  • Never repeat POST /accept after a timeout. Check the lead with GET /lead/{hashid} first.
  • For batches, poll the existing batch_id instead of uploading the file again.

Contacting support

Email support@finch-technologies.com with:

  • the environment and endpoint;
  • the HTTP status and response body;
  • the lead id or batch id; and
  • the time of the request.

Never send your full API key or unredacted applicant data.