If you are building something that consumes Toolio's import alerts — a webhook endpoint, a monitoring dashboard, an incident workflow — you need to see the failure events, not just the happy path. The success case is easy to produce; the failure cases are the ones your consumer is most likely to get wrong, and the ones you'll rely on when something actually breaks at 3am.
This article shows how to deliberately produce each import status so you can verify your consumer handles all of them. It assumes you have already set up a subscription as described in Data Alerts.
❗ Run these tests in a sandbox or pre-production tenant. Several of them deliberately import bad data, and a `Completed With Errors` test writes its good rows to the tenant for real.
Start With a Test Import Configuration
Point your tests at a dedicated importer rather than one carrying real data. Give it a name you can filter on in the imports grid, and use a small file — a few dozen rows is plenty. Every recipe below works the same way at 20 rows as at 200,000, and small files fail fast, which matters when you are iterating on a consumer.
Once the importer is set up, run one clean file through it first and confirm you receive IMPORT_JOB_STARTED and IMPORT_JOB_COMPLETED. That establishes your baseline before you start breaking things.
What the Send Test Button Does and Doesn't Prove
The Send test action on a webhook subscription is the fastest way to confirm your endpoint is reachable. It sends a POST to your configured URL, with your configured headers, and reports the HTTP status it got back.
What it sends is a fixed connectivity probe:
{
"eventType": "test",
"payload": {
"test": true,
"triggeredAt": "2026-08-17T09:15:00.000Z"
}
}This proves your URL resolves, your firewall allows Toolio through, your auth headers are accepted, and your endpoint returns 2xx. It does not exercise a real event payload — the body has none of the fields a real import event carries. Use it to get connectivity green, then use the recipes below to test your actual parsing and branching logic.
Import Status Values
Your consumer should branch on eventType. If you also read the status field inside the payload, these are the exact values Toolio sends. They are case-sensitive.
Event Type |
|
IMPORT_JOB_STARTED |
|
IMPORT_JOB_COMPLETED |
|
IMPORT_JOB_COMPLETED_WITH_ERRORS |
|
IMPORT_JOB_FAILED |
|
Triggering Completed With Errors
Completed With Errors means some rows failed but the job finished and the good rows were imported. To produce it, take a file you know imports cleanly and corrupt a small number of rows — anything from 1 to 999 failed rows will complete with errors.
Any one of these will do it. Corrupting three or four rows is enough:
Blank a required column. Clear a required field on a few rows. Produces error code
COLUMN_REQUIRED.Put text in a numeric column. Replace a quantity or price value with
abc. ProducesTYPE_ERROR.Break a date. Replace a date value with
not-a-dateor2026-13-45. ProducesINVALID_TIME_FIELD.Reference something that doesn't exist. Change an attribute value, option, or size to a string that isn't configured in your tenant. Produces
UNKNOWN_ATTRIBUTE_VALUE,UNKNOWN_OPTION, orUNKNOWN_SIZE_OPTION.
Blanking a required column is the most reliable of these, because it doesn't depend on how your tenant is configured.
The resulting event carries errorCount set to the number of bad rows, and an errorReportUrl pointing at a CSV listing each failed row with its reason. Testing that your consumer downloads and parses that report is worth doing here — it is the same mechanism you will depend on in production.
Triggering Failed
Failed means the job stopped before finishing and nothing was imported. This is a file-level problem rather than a row-level one. Pick whichever of these is easiest to automate in your test harness.
Remove a Required Header
Delete one required column from the header row, leaving the data rows as they are.
This is the cleanest way to force a failure. It is deterministic, it doesn't depend on tenant configuration, and it writes nothing to your tenant. The event's message reads Missing headers: <column>.
If you want a single repeatable recipe for your regression suite, use this one.
Break the CSV Syntax
Introduce an unterminated quote, or give one row a different number of columns than the header.
The event's message reads Your CSV is invalid. This one is useful if you want to verify your consumer handles a failure where lineCount may be absent or zero.
Use a Filename the Importer Doesn't Recognize
Rename the file so it no longer matches the naming pattern your importer expects.
The event's message reads Invalid Filename. Note that if the filename matches no importer at all, Toolio may not be able to attribute the job to your test importer — so prefer the header or CSV recipes when you are targeting a specific importer by name.
Exceed the Invalid Row Threshold
If a single import accumulates 1,000 or more failed rows, Toolio stops treating it as a partial success and fails the whole job with Too Many Invalid Rows.
This is the recipe to use if you specifically want to test the boundary between the two failure modes. Generate a file with 999 bad rows to get IMPORT_JOB_COMPLETED_WITH_ERRORS, then the same file with 1,000 bad rows to get IMPORT_JOB_FAILED. Nothing else about the file needs to change.
What Won't Trigger a Failure Alert
Two behaviors surprise people building consumers, and both are deliberate.
Transient infrastructure errors don't alert immediately. If a job hits a temporary processing error, Toolio retries it. Alerting on every attempt would page you for problems that resolve themselves on the next try, so the IMPORT_JOB_FAILED alert fires when the failure is terminal — not on each intermediate attempt. Every recipe in this article produces a terminal failure, so all of them alert.
Skipped rows are not errors. Rows excluded by an import filter, and inventory rows with 0 units, are counted in skippedLineCount rather than errorCount. A file where every row is filtered out still completes successfully. If you are trying to force an error and getting Completed with a high skipped count, a filter is eating your test rows before validation sees them.
Verifying Your Consumer
A reasonable checklist before you call the integration done:
Connectivity is green via
Send test.A clean file produces
IMPORT_JOB_STARTEDthenIMPORT_JOB_COMPLETED.A file with a few bad rows produces
IMPORT_JOB_COMPLETED_WITH_ERRORSwith a non-zeroerrorCount.Your consumer downloads and parses the
errorReportUrlCSV.A file with a missing header produces
IMPORT_JOB_FAILED.Your consumer distinguishes
CompletedWithErrorsfromFailedand treats only the latter as "no data landed."Your endpoint returns 2xx promptly. Toolio treats a non-2xx response as a delivery failure.
For the full field-by-field payload contract for each event, see Data Alerts. For what each status and error code means once you are live, see Import Status and Error Diagnostics.
FAQs
Can Toolio send me a sample failure payload without running an import?
Not currently. The Send test action sends a fixed connectivity probe rather than a sample of a real event. To see a real payload you need to run an import that produces the status you want, using one of the recipes above.
Which failure recipe should I automate in a regression suite?
Removing a required header. It is deterministic, independent of tenant configuration, imports no data, and produces a clear Missing headers: message you can assert on.
Does a Failed import leave partial data behind?
No. A Failed job imports nothing, so there is no cleanup. A Completed With Errors job has already written its good rows — re-importing a corrected file updates those rows rather than duplicating them.
My test file only produced skipped rows, not errors. Why?
An import filter is excluding your rows before they reach validation. Add the Filter Name attribute to your imports view to see which filter was applied, and either adjust it or use a test importer with no filter attached.