--- title: "NIGO Callbacks and Events" slug: "nigo-callbacks-and-events" updated: 2026-11-05T19:41:27Z published: 2026-11-05T19:41:27Z canonical: "docs.onespan.com/nigo-callbacks-and-events" --- > ## Documentation Index > Fetch the complete documentation index at: https://docs.onespan.com/llms.txt > Use this file to discover all available pages before exploring further. # NIGO Callbacks and Events 26.R6 adds a callback event, `ATTACHMENT_VALIDATION_RESULT`, subscribed to like any other event. It fires **once per signer per transaction**, once that signer's upload step is complete and every extraction for their files has reached an outcome. Its `message` is `FINISHED` when every file's extraction completed, or `FAILED` when at least one did not; `sessionUser` identifies the signer and `packageId` the transaction. The event announces that results are ready and carries no per-file detail — on receiving it, read the verifications endpoint. It removes the need to re-read the endpoint on a timer. ## Error and status reference ### extractionStatus | Value | Meaning | | --- | --- | | COMPLETED | Extraction ran and produced results. extractedFields and verificationCheckResults are populated | | NOT_PERFORMED | Extraction has not run, or was never attempted. Check reasonCode for why | | FAILED | Extraction was attempted and errored | ### reasonCode | Value | Cause | What to do | | --- | --- | --- | | null with extractionStatus: NOT_PERFORMED | Extraction was never requested for this file, was skipped because the detected type did not match, has not completed yet, or could not be submitted or read because the validation service was unreachable. | Work through the decision tree below. Only its last branch is worth waiting on | | EXTRACTION_NOT_ENABLED | The requirement asked for extraction, but the account feature Attachment Data Extraction was off when the file was uploaded. Normally prevented when the role is created; it can occur if the feature is turned off afterwards. A requirement that simply does not have extractionEnabled set produces a null reason code, not this one | Configuration, not a failure. Confirm the account feature, then have the signer replace the file | | CLASSIFICATION_UNKNOWN | The document could not be identified as any supported type | The signer likely uploaded the wrong thing, or an unsupported document. Human review | | CLASSIFICATION_UNSUPPORTED_TYPE | The document was identified, but that type does not support field extraction | Every supported document type supports extraction. Reserved for future types | | CLASSIFICATION_QUALITY_WARNING | Two causes, told apart by classificationResult.failed. **true**: the file was rejected before classification — unreadable, wrong format, or out of size bounds — and classificationResult.errorCode names the problem. **false**: classification succeeded but with confidenceLevel MEDIUM or LOW, and the validation service declined to extract; documentType still shows what was detected | Ask the signer for a better copy. If failed is false and documentType is the type you requested, the signer very likely sent the right document; a clearer copy may let it be recognised | | EXTRACTION_ERROR | Extraction was attempted and errored. Always paired with extractionStatus: FAILED | Terminal for this file; re-reading will not change it. See *What can and cannot be retried* below | **Resolving a** `null` **reason code.** Use the fields that are present to rule out the terminal causes before waiting on anything. `classificationResult.failed` never accompanies a `null` reason code — a failed classification always reports `CLASSIFICATION_QUALITY_WARNING` — so the tree starts from a successful classification: 1. `classificationResult` is `null` — the stored classification could not be read, and extraction never ran. Terminal. 2. The requirement did not have `extractionEnabled: true` — extraction was never requested. Terminal, and expected. 3. `classificationResult.documentType` is not the `attachmentType` you requested — the detected type did not match, and extraction was never submitted. Terminal. (A correct type detected at `MEDIUM` or `LOW` confidence does not reach this tree: it reports `CLASSIFICATION_QUALITY_WARNING`.) 4. Otherwise extraction was requested and no result is available yet: it is still running, it was refused at submission (for example the 1,024 px minimum for the six high-detail types), or the validation service could not be reached. These are not distinguished. Re-read this endpoint at intervals with backoff, and after a bounded time of your choosing treat the extraction result as unavailable for this file. **What can and cannot be retried.** OneSpan Sign runs classification and extraction once per file, at upload, and neither retries them nor exposes a way to re-trigger them. Re-reading this endpoint only picks up an extraction that is still in progress — branch 4 above. `EXTRACTION_ERROR`, and a `classificationResult.errorCode` of `upstream_service_error`, are stored outcomes for that file and will not change on re-read; the only recovery is for the signer to replace the file, which runs validation again from the start. If either recurs across many files, the validation service is degraded — contact OneSpan support. **Distinguish configuration from failure.** `EXTRACTION_NOT_ENABLED` means the feature was not turned on — nothing went wrong. Every other reason code describes something that happened to the document. ### Limits you can check before uploading The limits below belong to the validation service, and are separate from OneSpan Sign's own attachment upload limits (about 16 MB, and the file types allowed on the account). Exceeding the upload limits rejects the upload. Exceeding the limits below does **not** — the upload succeeds and classification fails with the error code shown. Checking them on the client avoids those errors entirely. | Limit | Value | Error code if exceeded | | --- | --- | --- | | Accepted formats | PDF (application/pdf), Word (application/msword, application/vnd.openxmlformats-officedocument.wordprocessingml.document), JPEG, PNG, TIFF, BMP, GIF. The type is determined from the file's content and name, not from a declared MIME type | unsupported_content_type | | Minimum file size | 1,024 bytes | file_too_small | | Maximum file size | 10,485,760 bytes (10 MiB) — **lower than the 16 MB upload limit** | file_too_large | | Minimum image dimensions | 200 × 200 px, for an image upload and for each of the first two pages of a PDF or Word file | image_resolution_too_low | | Maximum image dimensions | None. Images over 1,568 px on the longest side are downscaled | — | **Extraction applies a stricter minimum for six document types.** `T4_SLIP_CA`, `AUTO_INSURANCE_CERTIFICATE`, `PROPERTY_INSURANCE`, `LIFE_INSURANCE_POLICY`, `VEHICLE_REGISTRATION` and `EMPLOYMENT_LETTER` require **1,024 × 1,024 px** when extraction runs. A file between 200 and 1,024 px passes classification, then extraction is refused before it starts and nothing is recorded — the file reports `extractionStatus: NOT_PERFORMED` with `reasonCode: null`. If extraction is on for one of these types, enforce 1,024 px on the client. The remaining image checks — `image_too_blurry`, `image_too_dark`, `image_low_contrast`, `image_glare_detected` — measure the pixels and cannot be pre-validated by size or type. Blur and darkness apply to every input; contrast and glare apply only to photo uploads (JPEG, PNG, TIFF, BMP, GIF), never to PDF or Word pages. A born-digital PDF containing no images skips them entirely. For photos, guide the signer to a flat, evenly lit, in-focus capture without flash reflection. ### classificationResult.errorCode Populated only when `classificationResult.failed` is `true`, and only with one of the values below. These are translation keys, all prefixed `esl.error.attachment_verification.` | Key suffix | Cause | | --- | --- | | image_resolution_too_low | Below 200 × 200 px (1,024 px for the six high-detail types at extraction) | | image_too_blurry | The image is out of focus | | image_low_contrast | The image has insufficient contrast | | image_glare_detected | Glare obscures the document | | image_too_dark | The image is underexposed | | document_corrupted | The file could not be decoded as an image or document | | file_too_large | Over 10,485,760 bytes | | file_too_small | Under 1,024 bytes | | unsupported_content_type | Not one of the accepted formats listed above | | upstream_service_error | The validation service reported a problem with no mapping here — an empty file, a missing filename or content type, or an image that could not be processed. Stored for the file and unchanged on re-read — see *What can and cannot be retried* above | **On the upload response.** The signer's client receives the same keys immediately, as `classificationErrorCode` on each file in the response to the attachment upload or replace call, so that it can display an appropriate message. That response can additionally carry one key that never appears on `classificationResult.errorCode`: `type_mismatch` — the detected type does not match the requested type. A file carries at most one key there; a quality problem takes precedence over a mismatch. On the verifications endpoint a mismatch is expressed by `typeMatch` and `documentType` instead. The upload response also carries `verificationResultUuid`, the same value as `classificationResult.documentUuid`.