> For the complete documentation index, see [llms.txt](https://developer.emporix.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.emporix.io/api-references/readme/api-reference-33/runs.md).

# Runs

Trigger, monitor, and cancel import runs.

## Retrieving run history

> Retrieves the run history for a configuration, most recent first.

```json
{"openapi":"3.0.0","info":{"title":"Import Service","version":"0.0.1"},"tags":[{"name":"Runs","description":"Trigger, monitor, and cancel import runs."}],"servers":[{"url":"https://api.emporix.io"}],"security":[{"OAuth2":["importtool.import_trigger"]}],"components":{"securitySchemes":{"OAuth2":{"type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"https://api.emporix.io/oauth/token","scopes":{"importtool.import_trigger":"Needed to trigger, schedule, monitor, and cancel import runs and to read configurations, streams, schedules, runs, and imported data."}}}}},"parameters":{"trait_page":{"name":"page","in":"query","required":false,"description":"The zero-based page number.","schema":{"type":"integer","default":0}},"trait_size":{"name":"size","in":"query","required":false,"description":"The page size.","schema":{"type":"integer"}}},"schemas":{"ImportRunPage":{"title":"Run page","allOf":[{"$ref":"#/components/schemas/Page"},{"type":"object","properties":{"content":{"type":"array","description":"The runs on this page.","items":{"$ref":"#/components/schemas/ImportRun"}}}}]},"Page":{"title":"Page","type":"object","description":"Pagination metadata for a page of results.","properties":{"totalElements":{"type":"integer","description":"The total number of elements across all pages."},"totalPages":{"type":"integer","description":"The total number of pages."},"number":{"type":"integer","description":"The current zero-based page number."},"size":{"type":"integer","description":"The page size."}}},"ImportRun":{"title":"Run","type":"object","description":"An import run and its reconciled counters.","properties":{"id":{"type":"string","format":"uuid","description":"The run identifier."},"configId":{"type":"string","format":"uuid","description":"The configuration the run belongs to."},"tenant":{"type":"string","description":"The owning tenant."},"trigger":{"type":"string","enum":["MANUAL","SCHEDULED"],"description":"What triggered the run."},"dryRunSample":{"type":"array","description":"Dry-run only. A sample of the mapped records that would be written, so the mapping can be previewed without a real import. Absent on normal runs. Each stream is sampled separately, up to the `sampleSize` set in the run request. A parent stream's records include the records of its composite child streams that have `childStrategy` set to `EMBED` or `PATCH`. Those child records appear in the parent attribute named by the child stream's `embedAttribute`, as a real import writes them. Only child records inside the child stream's own sample are included, so a sampled parent record can show fewer child records than the source contains for that parent, or none. Child records are also sampled under their own stream.","items":{"type":"object","properties":{"stream":{"type":"string","description":"The stream that produced the sample record."},"targetType":{"type":"string","description":"The resolved target type the record would be written to."},"key":{"type":"string","description":"The record's natural/deterministic key."},"fields":{"type":"object","additionalProperties":true,"description":"The mapped target fields that would be written."}}}},"origin":{"type":"string","description":"What requested the run. The `origin` value from the trigger request, or the `trigger` value when `origin` was omitted. Use this field to distinguish a dashboard run from a run started by an integration scenario. The field is absent on runs recorded before it existed."},"status":{"type":"string","enum":["QUEUED","RUNNING","RESUMABLE","SUCCEEDED","PARTIAL","FAILED","CANCELLED","ABORTED"],"description":"The run status. Possible values:\n\n* `QUEUED` – the run waits to start. Nothing has been read yet, and the run has no per-stream\n  progress. `queueWaitingFor` says what the run waits for.\n* `RUNNING` – the run is executing.\n* `RESUMABLE` – the run was interrupted, for example by a service restart, and resumes automatically\n  from its last checkpoint. It is not a final status.\n* `SUCCEEDED` – the run finished, and every record was processed.\n* `PARTIAL` – the run finished, but not completely: some records failed, a limit skipped records,\n  or a stream was not run. The `message` field and the per-stream progress give the details.\n* `FAILED` – the run stopped because of an error.\n* `CANCELLED` – the run was cancelled.\n* `ABORTED` – the service refused to start the run because of the import configuration, for example\n  mappings that have never been published or a changed target schema. Nothing was read or written."},"mode":{"type":"string","enum":["FULL","DELTA"],"description":"The run mode."},"startedAt":{"type":"string","format":"date-time","description":"When the run was requested. If the run was queued first, it began executing later, at `executionStartedAt`."},"executionStartedAt":{"type":"string","format":"date-time","nullable":true,"description":"When the run began executing. Equal to `startedAt`, or later by the time the run spent in the queue. `null` while the run is `QUEUED`, and on runs recorded before the field existed."},"finishedAt":{"type":"string","format":"date-time","description":"When the run finished."},"queuePosition":{"type":"integer","minimum":1,"description":"`QUEUED` runs only. The run's position among the queued runs that can start, where `1` starts next. Runs of all tenants share the queue, and a tenant with fewer runs executing goes first. The value is approximate, because the queue changes while you read it. The field is absent when the run is not queued, when it waits for something other than a worker, or when the service has not yet calculated it."},"queueWaitingFor":{"type":"string","enum":["WORKER","PREVIOUS_RUN","TENANT_LIMIT"],"description":"`QUEUED` runs only. What the run waits for. Possible values:\n\n* `WORKER` – the run waits for a free worker. `queuePosition` gives its place in the queue.\n* `PREVIOUS_RUN` – the run waits for the configuration's current run to finish.\n* `TENANT_LIMIT` – the run waits for one of the tenant's runs to finish, because\n  `maxConcurrentImports` runs are already executing.\n\nThe field is absent when the run is not queued, or when the service has not yet calculated it."},"supersededRequests":{"type":"integer","description":"The number of later scheduled run requests that were added to this run while it was queued. A configuration has at most one queued run, so a scheduled request that arrives while a real run of the whole configuration is queued does not queue a second run."},"lastRequestedAt":{"type":"string","format":"date-time","description":"When the latest scheduled run request counted in `supersededRequests` was made. Absent when `supersededRequests` is `0`."},"recordsRead":{"type":"integer","description":"Records read (created + updated + skipped + deleted + failed)."},"created":{"type":"integer","description":"Records created."},"updated":{"type":"integer","description":"Records updated."},"skipped":{"type":"integer","description":"Records skipped because they were unchanged."},"failed":{"type":"integer","description":"Records that failed."},"deleted":{"type":"integer","description":"Records deleted."},"duplicateKeys":{"type":"integer","description":"Source rows that repeat a key already imported in this run. The import keeps the last row of each repeated key and discards earlier rows. Duplicate keys do not fail the run; they mean the source feed is not unique on the key the stream imports by."},"unresolvedParents":{"type":"integer","description":"Child records that were not imported because their parent could not be found. Counted separately from `skipped`, which counts records that were already up to date."},"message":{"type":"string","description":"A terminal status message, typically set on failure."},"retryOfRunId":{"type":"string","format":"uuid","description":"When the run retries another run's failed records, the identifier of that original run."},"force":{"type":"boolean","description":"Whether the run rewrote every record, bypassing the skip-if-unchanged check."},"dryRun":{"type":"boolean","description":"Whether the run only extracted, mapped, and validated, writing nothing to the target. A dry run legitimately reports zero for every counter, so this distinguishes it from a run that wrote nothing because it failed."},"cancelRequested":{"type":"boolean","description":"Whether cancellation has been requested for a run that is still finishing."},"dryRunSampleSize":{"type":"integer","description":"For a dry run, how many mapped records were kept as a sample."},"dryRunPublished":{"type":"boolean","description":"Dry-run only. Whether the dry run used the published mappings (`true`) or the draft mappings (`false`)."},"mappingVersions":{"type":"array","description":"The published mapping version each stream uses in this run, fixed when the run starts executing. Version `0` means that the stream has no published mappings. The field is absent while the run is `QUEUED`, on a dry run of the draft mappings, and on runs recorded before it existed.","items":{"type":"object","properties":{"streamId":{"type":"string","format":"uuid","description":"The stream identifier."},"version":{"type":"integer","description":"The published mapping version the stream uses."}}}}}},"errorMessage":{"title":"Error","description":"Schema for specific API errors.","type":"object","properties":{"code":{"type":"integer","description":"HTTP status code.","minimum":100,"maximum":599},"status":{"description":"HTTP status.","type":"string"},"message":{"description":"Descriptive error message for debugging.","type":"string"},"details":{"description":"List of problems causing this error.","type":"array","items":{"title":"Error Detail","description":"Error details.","type":"string"}}},"required":["status","code","message"]}},"responses":{"Unauthorized_401":{"description":"Given request is unauthorized - the authorization token is invalid or has expired. Details will be provided in the response payload.","content":{"application/json":{"schema":{"type":"object","properties":{"fault":{"type":"object","properties":{"faultstring":{"type":"string"},"detail":{"type":"object","properties":{"errorcode":{"type":"string"}}}}}}}}}},"Forbidden_403":{"description":"Given authorization scopes are not sufficient and do not match scopes required by the endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorMessage"}}}},"InternalServiceError_500":{"description":"Internal Service Error occurred.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorMessage"}}}}}},"paths":{"/importtool/{tenant}/configs/{configId}/runs":{"get":{"summary":"Retrieving run history","description":"Retrieves the run history for a configuration, most recent first.","operationId":"GET-importtool-list-runs","tags":["Runs"],"parameters":[{"$ref":"#/components/parameters/trait_page"},{"$ref":"#/components/parameters/trait_size"}],"responses":{"200":{"description":"The request was successful. The run history is returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportRunPage"}}}},"401":{"$ref":"#/components/responses/Unauthorized_401"},"403":{"$ref":"#/components/responses/Forbidden_403"},"500":{"$ref":"#/components/responses/InternalServiceError_500"}}}}}}
```

## Triggering an import run

> Requests an import run for the configuration and returns immediately with the run in the \`QUEUED\`\
> status. The run starts when a worker of the Import Service is free, usually within moments, and then\
> has the \`RUNNING\` status. If \`maxConcurrentImports\` runs are already executing for the tenant, the run\
> waits until one of them finishes. \`queueWaitingFor\` says what a queued run waits for. To follow the\
> run's progress, retrieve the run or stream its progress events.\
> \
> A configuration has at most one run executing and at most one run queued. The service rejects a\
> request with a \`409 Conflict\` response while the configuration has a run in the \`QUEUED\`, \`RUNNING\`, or\
> \`RESUMABLE\` status.\
> \
> A scheduled run is not rejected. It is queued behind the configuration's current run and starts when\
> that run finishes. If the schedule requests another run while the configuration's run is still\
> queued, the service adds the request to the queued run instead of queuing a second run, and counts it\
> in \`supersededRequests\`. The service does this only when the queued run is a real run of the whole\
> configuration. If the queued run is a dry run, a run of selected streams, or a retry, the scheduled run\
> waits until that run starts and is then queued behind it.\
> \
> A run executes each stream's published mappings. Saved mapping changes that are not published yet are\
> the draft mappings, and they take effect only after they are published. Publishing mappings is an\
> administrative operation that requires the \`importtool.import\_manage\` scope and is not covered in this\
> reference. A real run, or a dry run that uses the published mappings, fixes the published mapping version of\
> each stream when it starts, so a version published during the run applies from the next run. The run\
> reports these versions in \`mappingVersions\`. A dry run of the draft mappings does not use published\
> versions and does not report \`mappingVersions\`.\
> \
> A stream whose mappings have never been published is not run. Its entry in the run details (\`streams\` in\
> the response of retrieving a run) has the \`ABORTED\` status and a \`message\` that gives the reason, and the\
> run finishes with the \`PARTIAL\` status. The service refuses the whole run when \`streamIds\` names a stream\
> whose mappings have never been published, or when every enabled stream is in that state.\
> \
> The refusal does not change the response to this request: the service still returns \`200\` with the run,\
> and the run then finishes with the \`ABORTED\` status and a \`message\` that names the streams. Retrieve the\
> run to check its final status.

```json
{"openapi":"3.0.0","info":{"title":"Import Service","version":"0.0.1"},"tags":[{"name":"Runs","description":"Trigger, monitor, and cancel import runs."}],"servers":[{"url":"https://api.emporix.io"}],"security":[{"OAuth2":["importtool.import_trigger"]}],"components":{"securitySchemes":{"OAuth2":{"type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"https://api.emporix.io/oauth/token","scopes":{"importtool.import_trigger":"Needed to trigger, schedule, monitor, and cancel import runs and to read configurations, streams, schedules, runs, and imported data."}}}}},"schemas":{"ImportRun":{"title":"Run","type":"object","description":"An import run and its reconciled counters.","properties":{"id":{"type":"string","format":"uuid","description":"The run identifier."},"configId":{"type":"string","format":"uuid","description":"The configuration the run belongs to."},"tenant":{"type":"string","description":"The owning tenant."},"trigger":{"type":"string","enum":["MANUAL","SCHEDULED"],"description":"What triggered the run."},"dryRunSample":{"type":"array","description":"Dry-run only. A sample of the mapped records that would be written, so the mapping can be previewed without a real import. Absent on normal runs. Each stream is sampled separately, up to the `sampleSize` set in the run request. A parent stream's records include the records of its composite child streams that have `childStrategy` set to `EMBED` or `PATCH`. Those child records appear in the parent attribute named by the child stream's `embedAttribute`, as a real import writes them. Only child records inside the child stream's own sample are included, so a sampled parent record can show fewer child records than the source contains for that parent, or none. Child records are also sampled under their own stream.","items":{"type":"object","properties":{"stream":{"type":"string","description":"The stream that produced the sample record."},"targetType":{"type":"string","description":"The resolved target type the record would be written to."},"key":{"type":"string","description":"The record's natural/deterministic key."},"fields":{"type":"object","additionalProperties":true,"description":"The mapped target fields that would be written."}}}},"origin":{"type":"string","description":"What requested the run. The `origin` value from the trigger request, or the `trigger` value when `origin` was omitted. Use this field to distinguish a dashboard run from a run started by an integration scenario. The field is absent on runs recorded before it existed."},"status":{"type":"string","enum":["QUEUED","RUNNING","RESUMABLE","SUCCEEDED","PARTIAL","FAILED","CANCELLED","ABORTED"],"description":"The run status. Possible values:\n\n* `QUEUED` – the run waits to start. Nothing has been read yet, and the run has no per-stream\n  progress. `queueWaitingFor` says what the run waits for.\n* `RUNNING` – the run is executing.\n* `RESUMABLE` – the run was interrupted, for example by a service restart, and resumes automatically\n  from its last checkpoint. It is not a final status.\n* `SUCCEEDED` – the run finished, and every record was processed.\n* `PARTIAL` – the run finished, but not completely: some records failed, a limit skipped records,\n  or a stream was not run. The `message` field and the per-stream progress give the details.\n* `FAILED` – the run stopped because of an error.\n* `CANCELLED` – the run was cancelled.\n* `ABORTED` – the service refused to start the run because of the import configuration, for example\n  mappings that have never been published or a changed target schema. Nothing was read or written."},"mode":{"type":"string","enum":["FULL","DELTA"],"description":"The run mode."},"startedAt":{"type":"string","format":"date-time","description":"When the run was requested. If the run was queued first, it began executing later, at `executionStartedAt`."},"executionStartedAt":{"type":"string","format":"date-time","nullable":true,"description":"When the run began executing. Equal to `startedAt`, or later by the time the run spent in the queue. `null` while the run is `QUEUED`, and on runs recorded before the field existed."},"finishedAt":{"type":"string","format":"date-time","description":"When the run finished."},"queuePosition":{"type":"integer","minimum":1,"description":"`QUEUED` runs only. The run's position among the queued runs that can start, where `1` starts next. Runs of all tenants share the queue, and a tenant with fewer runs executing goes first. The value is approximate, because the queue changes while you read it. The field is absent when the run is not queued, when it waits for something other than a worker, or when the service has not yet calculated it."},"queueWaitingFor":{"type":"string","enum":["WORKER","PREVIOUS_RUN","TENANT_LIMIT"],"description":"`QUEUED` runs only. What the run waits for. Possible values:\n\n* `WORKER` – the run waits for a free worker. `queuePosition` gives its place in the queue.\n* `PREVIOUS_RUN` – the run waits for the configuration's current run to finish.\n* `TENANT_LIMIT` – the run waits for one of the tenant's runs to finish, because\n  `maxConcurrentImports` runs are already executing.\n\nThe field is absent when the run is not queued, or when the service has not yet calculated it."},"supersededRequests":{"type":"integer","description":"The number of later scheduled run requests that were added to this run while it was queued. A configuration has at most one queued run, so a scheduled request that arrives while a real run of the whole configuration is queued does not queue a second run."},"lastRequestedAt":{"type":"string","format":"date-time","description":"When the latest scheduled run request counted in `supersededRequests` was made. Absent when `supersededRequests` is `0`."},"recordsRead":{"type":"integer","description":"Records read (created + updated + skipped + deleted + failed)."},"created":{"type":"integer","description":"Records created."},"updated":{"type":"integer","description":"Records updated."},"skipped":{"type":"integer","description":"Records skipped because they were unchanged."},"failed":{"type":"integer","description":"Records that failed."},"deleted":{"type":"integer","description":"Records deleted."},"duplicateKeys":{"type":"integer","description":"Source rows that repeat a key already imported in this run. The import keeps the last row of each repeated key and discards earlier rows. Duplicate keys do not fail the run; they mean the source feed is not unique on the key the stream imports by."},"unresolvedParents":{"type":"integer","description":"Child records that were not imported because their parent could not be found. Counted separately from `skipped`, which counts records that were already up to date."},"message":{"type":"string","description":"A terminal status message, typically set on failure."},"retryOfRunId":{"type":"string","format":"uuid","description":"When the run retries another run's failed records, the identifier of that original run."},"force":{"type":"boolean","description":"Whether the run rewrote every record, bypassing the skip-if-unchanged check."},"dryRun":{"type":"boolean","description":"Whether the run only extracted, mapped, and validated, writing nothing to the target. A dry run legitimately reports zero for every counter, so this distinguishes it from a run that wrote nothing because it failed."},"cancelRequested":{"type":"boolean","description":"Whether cancellation has been requested for a run that is still finishing."},"dryRunSampleSize":{"type":"integer","description":"For a dry run, how many mapped records were kept as a sample."},"dryRunPublished":{"type":"boolean","description":"Dry-run only. Whether the dry run used the published mappings (`true`) or the draft mappings (`false`)."},"mappingVersions":{"type":"array","description":"The published mapping version each stream uses in this run, fixed when the run starts executing. Version `0` means that the stream has no published mappings. The field is absent while the run is `QUEUED`, on a dry run of the draft mappings, and on runs recorded before it existed.","items":{"type":"object","properties":{"streamId":{"type":"string","format":"uuid","description":"The stream identifier."},"version":{"type":"integer","description":"The published mapping version the stream uses."}}}}}},"errorMessage":{"title":"Error","description":"Schema for specific API errors.","type":"object","properties":{"code":{"type":"integer","description":"HTTP status code.","minimum":100,"maximum":599},"status":{"description":"HTTP status.","type":"string"},"message":{"description":"Descriptive error message for debugging.","type":"string"},"details":{"description":"List of problems causing this error.","type":"array","items":{"title":"Error Detail","description":"Error details.","type":"string"}}},"required":["status","code","message"]}},"responses":{"Unauthorized_401":{"description":"Given request is unauthorized - the authorization token is invalid or has expired. Details will be provided in the response payload.","content":{"application/json":{"schema":{"type":"object","properties":{"fault":{"type":"object","properties":{"faultstring":{"type":"string"},"detail":{"type":"object","properties":{"errorcode":{"type":"string"}}}}}}}}}},"Forbidden_403":{"description":"Given authorization scopes are not sufficient and do not match scopes required by the endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorMessage"}}}},"Conflict_409":{"description":"The request conflicts with the current state of the resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorMessage"}}}},"InternalServiceError_500":{"description":"Internal Service Error occurred.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorMessage"}}}}}},"paths":{"/importtool/{tenant}/configs/{configId}/runs":{"post":{"summary":"Triggering an import run","description":"Requests an import run for the configuration and returns immediately with the run in the `QUEUED`\nstatus. The run starts when a worker of the Import Service is free, usually within moments, and then\nhas the `RUNNING` status. If `maxConcurrentImports` runs are already executing for the tenant, the run\nwaits until one of them finishes. `queueWaitingFor` says what a queued run waits for. To follow the\nrun's progress, retrieve the run or stream its progress events.\n\nA configuration has at most one run executing and at most one run queued. The service rejects a\nrequest with a `409 Conflict` response while the configuration has a run in the `QUEUED`, `RUNNING`, or\n`RESUMABLE` status.\n\nA scheduled run is not rejected. It is queued behind the configuration's current run and starts when\nthat run finishes. If the schedule requests another run while the configuration's run is still\nqueued, the service adds the request to the queued run instead of queuing a second run, and counts it\nin `supersededRequests`. The service does this only when the queued run is a real run of the whole\nconfiguration. If the queued run is a dry run, a run of selected streams, or a retry, the scheduled run\nwaits until that run starts and is then queued behind it.\n\nA run executes each stream's published mappings. Saved mapping changes that are not published yet are\nthe draft mappings, and they take effect only after they are published. Publishing mappings is an\nadministrative operation that requires the `importtool.import_manage` scope and is not covered in this\nreference. A real run, or a dry run that uses the published mappings, fixes the published mapping version of\neach stream when it starts, so a version published during the run applies from the next run. The run\nreports these versions in `mappingVersions`. A dry run of the draft mappings does not use published\nversions and does not report `mappingVersions`.\n\nA stream whose mappings have never been published is not run. Its entry in the run details (`streams` in\nthe response of retrieving a run) has the `ABORTED` status and a `message` that gives the reason, and the\nrun finishes with the `PARTIAL` status. The service refuses the whole run when `streamIds` names a stream\nwhose mappings have never been published, or when every enabled stream is in that state.\n\nThe refusal does not change the response to this request: the service still returns `200` with the run,\nand the run then finishes with the `ABORTED` status and a `message` that names the streams. Retrieve the\nrun to check its final status.","operationId":"POST-importtool-trigger-run","tags":["Runs"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"mode":{"type":"string","enum":["FULL","DELTA"],"description":"The run mode. When omitted, defaults to `DELTA`."},"dryRun":{"type":"boolean","description":"When `true`, the run maps and validates but performs no remote writes."},"mappings":{"type":"string","enum":["published","draft"],"default":"published","description":"Dry-run only. Which mappings the dry run uses. `published` uses each stream's published mappings, which is what a real run executes. `draft` uses the draft mappings, so you can check them before publishing. When omitted, defaults to `published`. A dry run with `published` handles streams whose mappings have never been published in the same way as a real run. The field has no effect when `dryRun` is `false`, because a real run always uses the published mappings."},"force":{"type":"boolean","description":"When `true`, every extracted record is rewritten, even if unchanged. It bypasses the idempotency `skip-if-unchanged` check. Use it to force target IDs and values to be rewritten."},"sampleSize":{"type":"integer","minimum":1,"maximum":100,"description":"Dry-run only. How many mapped records to sample per stream for the preview returned as `dryRunSample`. Clamped to 1-100; defaults to 25."},"origin":{"type":"string","maxLength":40,"description":"What requested this run. Examples: `Dashboard`, an integration scenario name, or a scheduler name. The `trigger` field records only `MANUAL` or `SCHEDULED`. Use `origin` when more than one system calls this endpoint. If you omit `origin` or send a blank value, the service stores the `trigger` value. The service rejects values longer than 40 characters and values that contain control characters. It does not shorten them."},"streamIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"The stream identifiers to run. Omit the field to run every stream in the configuration. Send a list of stream IDs to run only those streams. Do not send stream names; use the `id` values from the stream resource.\nThe service rejects an empty list. It also rejects a list that includes no stream from this configuration. Listed streams still run in the computed stream order, not in list order.\nThe service also rejects a stream that cannot produce data on its own. A `COMPOSITE_CHILD` stream with `childStrategy` set to `EMBED` is written by its parent. A child that reads values captured during the parent run also cannot run alone. Either stream without its parent would complete successfully without importing records."}}}}}},"responses":{"200":{"description":"The request was successful. The run has been queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportRun"}}}},"400":{"description":"The request is invalid. For example, `dryRun` is `true` and `mappings` has a value other than `published` or `draft`.","content":{"application/json":{"schema":{"type":"object","properties":{"timestamp":{"type":"string","format":"date-time","description":"When the error occurred."},"status":{"type":"integer","description":"HTTP status code."},"error":{"type":"string","description":"HTTP status reason phrase."},"path":{"type":"string","description":"The request path."}}}}}},"401":{"$ref":"#/components/responses/Unauthorized_401"},"403":{"$ref":"#/components/responses/Forbidden_403"},"409":{"$ref":"#/components/responses/Conflict_409"},"500":{"$ref":"#/components/responses/InternalServiceError_500"}}}}}}
```

## Retrieving a run

> Retrieves a run's status together with its per-stream progress.

```json
{"openapi":"3.0.0","info":{"title":"Import Service","version":"0.0.1"},"tags":[{"name":"Runs","description":"Trigger, monitor, and cancel import runs."}],"servers":[{"url":"https://api.emporix.io"}],"security":[{"OAuth2":["importtool.import_trigger"]}],"components":{"securitySchemes":{"OAuth2":{"type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"https://api.emporix.io/oauth/token","scopes":{"importtool.import_trigger":"Needed to trigger, schedule, monitor, and cancel import runs and to read configurations, streams, schedules, runs, and imported data."}}}}},"schemas":{"RunDetail":{"title":"Run detail","type":"object","description":"A run together with its per-stream progress.","properties":{"run":{"$ref":"#/components/schemas/ImportRun"},"streams":{"type":"array","description":"The per-stream progress.","items":{"$ref":"#/components/schemas/ImportRunStream"}}}},"ImportRun":{"title":"Run","type":"object","description":"An import run and its reconciled counters.","properties":{"id":{"type":"string","format":"uuid","description":"The run identifier."},"configId":{"type":"string","format":"uuid","description":"The configuration the run belongs to."},"tenant":{"type":"string","description":"The owning tenant."},"trigger":{"type":"string","enum":["MANUAL","SCHEDULED"],"description":"What triggered the run."},"dryRunSample":{"type":"array","description":"Dry-run only. A sample of the mapped records that would be written, so the mapping can be previewed without a real import. Absent on normal runs. Each stream is sampled separately, up to the `sampleSize` set in the run request. A parent stream's records include the records of its composite child streams that have `childStrategy` set to `EMBED` or `PATCH`. Those child records appear in the parent attribute named by the child stream's `embedAttribute`, as a real import writes them. Only child records inside the child stream's own sample are included, so a sampled parent record can show fewer child records than the source contains for that parent, or none. Child records are also sampled under their own stream.","items":{"type":"object","properties":{"stream":{"type":"string","description":"The stream that produced the sample record."},"targetType":{"type":"string","description":"The resolved target type the record would be written to."},"key":{"type":"string","description":"The record's natural/deterministic key."},"fields":{"type":"object","additionalProperties":true,"description":"The mapped target fields that would be written."}}}},"origin":{"type":"string","description":"What requested the run. The `origin` value from the trigger request, or the `trigger` value when `origin` was omitted. Use this field to distinguish a dashboard run from a run started by an integration scenario. The field is absent on runs recorded before it existed."},"status":{"type":"string","enum":["QUEUED","RUNNING","RESUMABLE","SUCCEEDED","PARTIAL","FAILED","CANCELLED","ABORTED"],"description":"The run status. Possible values:\n\n* `QUEUED` – the run waits to start. Nothing has been read yet, and the run has no per-stream\n  progress. `queueWaitingFor` says what the run waits for.\n* `RUNNING` – the run is executing.\n* `RESUMABLE` – the run was interrupted, for example by a service restart, and resumes automatically\n  from its last checkpoint. It is not a final status.\n* `SUCCEEDED` – the run finished, and every record was processed.\n* `PARTIAL` – the run finished, but not completely: some records failed, a limit skipped records,\n  or a stream was not run. The `message` field and the per-stream progress give the details.\n* `FAILED` – the run stopped because of an error.\n* `CANCELLED` – the run was cancelled.\n* `ABORTED` – the service refused to start the run because of the import configuration, for example\n  mappings that have never been published or a changed target schema. Nothing was read or written."},"mode":{"type":"string","enum":["FULL","DELTA"],"description":"The run mode."},"startedAt":{"type":"string","format":"date-time","description":"When the run was requested. If the run was queued first, it began executing later, at `executionStartedAt`."},"executionStartedAt":{"type":"string","format":"date-time","nullable":true,"description":"When the run began executing. Equal to `startedAt`, or later by the time the run spent in the queue. `null` while the run is `QUEUED`, and on runs recorded before the field existed."},"finishedAt":{"type":"string","format":"date-time","description":"When the run finished."},"queuePosition":{"type":"integer","minimum":1,"description":"`QUEUED` runs only. The run's position among the queued runs that can start, where `1` starts next. Runs of all tenants share the queue, and a tenant with fewer runs executing goes first. The value is approximate, because the queue changes while you read it. The field is absent when the run is not queued, when it waits for something other than a worker, or when the service has not yet calculated it."},"queueWaitingFor":{"type":"string","enum":["WORKER","PREVIOUS_RUN","TENANT_LIMIT"],"description":"`QUEUED` runs only. What the run waits for. Possible values:\n\n* `WORKER` – the run waits for a free worker. `queuePosition` gives its place in the queue.\n* `PREVIOUS_RUN` – the run waits for the configuration's current run to finish.\n* `TENANT_LIMIT` – the run waits for one of the tenant's runs to finish, because\n  `maxConcurrentImports` runs are already executing.\n\nThe field is absent when the run is not queued, or when the service has not yet calculated it."},"supersededRequests":{"type":"integer","description":"The number of later scheduled run requests that were added to this run while it was queued. A configuration has at most one queued run, so a scheduled request that arrives while a real run of the whole configuration is queued does not queue a second run."},"lastRequestedAt":{"type":"string","format":"date-time","description":"When the latest scheduled run request counted in `supersededRequests` was made. Absent when `supersededRequests` is `0`."},"recordsRead":{"type":"integer","description":"Records read (created + updated + skipped + deleted + failed)."},"created":{"type":"integer","description":"Records created."},"updated":{"type":"integer","description":"Records updated."},"skipped":{"type":"integer","description":"Records skipped because they were unchanged."},"failed":{"type":"integer","description":"Records that failed."},"deleted":{"type":"integer","description":"Records deleted."},"duplicateKeys":{"type":"integer","description":"Source rows that repeat a key already imported in this run. The import keeps the last row of each repeated key and discards earlier rows. Duplicate keys do not fail the run; they mean the source feed is not unique on the key the stream imports by."},"unresolvedParents":{"type":"integer","description":"Child records that were not imported because their parent could not be found. Counted separately from `skipped`, which counts records that were already up to date."},"message":{"type":"string","description":"A terminal status message, typically set on failure."},"retryOfRunId":{"type":"string","format":"uuid","description":"When the run retries another run's failed records, the identifier of that original run."},"force":{"type":"boolean","description":"Whether the run rewrote every record, bypassing the skip-if-unchanged check."},"dryRun":{"type":"boolean","description":"Whether the run only extracted, mapped, and validated, writing nothing to the target. A dry run legitimately reports zero for every counter, so this distinguishes it from a run that wrote nothing because it failed."},"cancelRequested":{"type":"boolean","description":"Whether cancellation has been requested for a run that is still finishing."},"dryRunSampleSize":{"type":"integer","description":"For a dry run, how many mapped records were kept as a sample."},"dryRunPublished":{"type":"boolean","description":"Dry-run only. Whether the dry run used the published mappings (`true`) or the draft mappings (`false`)."},"mappingVersions":{"type":"array","description":"The published mapping version each stream uses in this run, fixed when the run starts executing. Version `0` means that the stream has no published mappings. The field is absent while the run is `QUEUED`, on a dry run of the draft mappings, and on runs recorded before it existed.","items":{"type":"object","properties":{"streamId":{"type":"string","format":"uuid","description":"The stream identifier."},"version":{"type":"integer","description":"The published mapping version the stream uses."}}}}}},"ImportRunStream":{"title":"Run stream progress","type":"object","description":"The per-stream progress within a run.","properties":{"id":{"type":"string","format":"uuid","description":"The run-stream identifier."},"runId":{"type":"string","format":"uuid","description":"The run this progress belongs to."},"streamId":{"type":"string","format":"uuid","description":"The stream this progress belongs to."},"streamName":{"type":"string","description":"The stream name."},"status":{"type":"string","enum":["QUEUED","RUNNING","SUCCEEDED","PARTIAL","FAILED","SKIPPED","ABORTED"],"description":"The stream's status within the run. `ABORTED` means the service refused to run the stream because of its configuration, for example because its mappings have never been published. It indicates a configuration problem to fix. The `message` field gives the reason."},"recordsRead":{"type":"integer","description":"Records read for this stream."},"created":{"type":"integer","description":"Records created."},"updated":{"type":"integer","description":"Records updated."},"skipped":{"type":"integer","description":"Records skipped."},"failed":{"type":"integer","description":"Records that failed."},"deleted":{"type":"integer","description":"Records deleted."},"duplicateKeys":{"type":"integer","description":"Source rows that repeat a key already imported in this run. The import keeps the last row of each repeated key and discards earlier rows. Duplicate keys do not fail the run; they mean the source feed is not unique on the key the stream imports by."},"unresolvedParents":{"type":"integer","description":"Child records that were not imported because their parent could not be found. Counted separately from `skipped`, which counts records that were already up to date."},"message":{"type":"string","description":"A per-stream status message."}}},"errorMessage":{"title":"Error","description":"Schema for specific API errors.","type":"object","properties":{"code":{"type":"integer","description":"HTTP status code.","minimum":100,"maximum":599},"status":{"description":"HTTP status.","type":"string"},"message":{"description":"Descriptive error message for debugging.","type":"string"},"details":{"description":"List of problems causing this error.","type":"array","items":{"title":"Error Detail","description":"Error details.","type":"string"}}},"required":["status","code","message"]}},"responses":{"Unauthorized_401":{"description":"Given request is unauthorized - the authorization token is invalid or has expired. Details will be provided in the response payload.","content":{"application/json":{"schema":{"type":"object","properties":{"fault":{"type":"object","properties":{"faultstring":{"type":"string"},"detail":{"type":"object","properties":{"errorcode":{"type":"string"}}}}}}}}}},"Forbidden_403":{"description":"Given authorization scopes are not sufficient and do not match scopes required by the endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorMessage"}}}},"NotFound_404":{"description":"The requested resource does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorMessage"}}}},"InternalServiceError_500":{"description":"Internal Service Error occurred.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorMessage"}}}}}},"paths":{"/importtool/{tenant}/runs/{runId}":{"get":{"summary":"Retrieving a run","description":"Retrieves a run's status together with its per-stream progress.","operationId":"GET-importtool-get-run","tags":["Runs"],"responses":{"200":{"description":"The request was successful. The run and its streams are returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunDetail"}}}},"401":{"$ref":"#/components/responses/Unauthorized_401"},"403":{"$ref":"#/components/responses/Forbidden_403"},"404":{"$ref":"#/components/responses/NotFound_404"},"500":{"$ref":"#/components/responses/InternalServiceError_500"}}}}}}
```

## Streaming run progress

> Streams a run's progress as Server-Sent Events: an initial \`snapshot\` (run and streams), then a\
> \`stream\` event per processed batch, and a final \`run\` event when the run finishes.

```json
{"openapi":"3.0.0","info":{"title":"Import Service","version":"0.0.1"},"tags":[{"name":"Runs","description":"Trigger, monitor, and cancel import runs."}],"servers":[{"url":"https://api.emporix.io"}],"security":[{"OAuth2":["importtool.import_trigger"]}],"components":{"securitySchemes":{"OAuth2":{"type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"https://api.emporix.io/oauth/token","scopes":{"importtool.import_trigger":"Needed to trigger, schedule, monitor, and cancel import runs and to read configurations, streams, schedules, runs, and imported data."}}}}},"responses":{"Unauthorized_401":{"description":"Given request is unauthorized - the authorization token is invalid or has expired. Details will be provided in the response payload.","content":{"application/json":{"schema":{"type":"object","properties":{"fault":{"type":"object","properties":{"faultstring":{"type":"string"},"detail":{"type":"object","properties":{"errorcode":{"type":"string"}}}}}}}}}},"Forbidden_403":{"description":"Given authorization scopes are not sufficient and do not match scopes required by the endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorMessage"}}}},"InternalServiceError_500":{"description":"Internal Service Error occurred.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorMessage"}}}}},"schemas":{"errorMessage":{"title":"Error","description":"Schema for specific API errors.","type":"object","properties":{"code":{"type":"integer","description":"HTTP status code.","minimum":100,"maximum":599},"status":{"description":"HTTP status.","type":"string"},"message":{"description":"Descriptive error message for debugging.","type":"string"},"details":{"description":"List of problems causing this error.","type":"array","items":{"title":"Error Detail","description":"Error details.","type":"string"}}},"required":["status","code","message"]}}},"paths":{"/importtool/{tenant}/runs/{runId}/events":{"get":{"summary":"Streaming run progress","description":"Streams a run's progress as Server-Sent Events: an initial `snapshot` (run and streams), then a\n`stream` event per processed batch, and a final `run` event when the run finishes.","operationId":"GET-importtool-stream-run-events","tags":["Runs"],"responses":{"200":{"description":"The event stream was opened.","content":{"text/event-stream":{"schema":{"type":"string"}}}},"401":{"$ref":"#/components/responses/Unauthorized_401"},"403":{"$ref":"#/components/responses/Forbidden_403"},"500":{"$ref":"#/components/responses/InternalServiceError_500"}}}}}}
```

## Cancelling a run

> Requests cancellation of an active run. By default the cancellation is cooperative; with\
> \`force=true\` the run is stopped immediately and its configuration is unblocked.\
> \
> A run in the \`QUEUED\` status has not started, so it is cancelled immediately and gets the \`CANCELLED\`\
> status, with or without \`force\`. A run in the \`RESUMABLE\` status can be stopped only with\
> \`force=true\`. Without \`force\`, the request returns a \`409 Conflict\` response.

```json
{"openapi":"3.0.0","info":{"title":"Import Service","version":"0.0.1"},"tags":[{"name":"Runs","description":"Trigger, monitor, and cancel import runs."}],"servers":[{"url":"https://api.emporix.io"}],"security":[{"OAuth2":["importtool.import_trigger"]}],"components":{"securitySchemes":{"OAuth2":{"type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"https://api.emporix.io/oauth/token","scopes":{"importtool.import_trigger":"Needed to trigger, schedule, monitor, and cancel import runs and to read configurations, streams, schedules, runs, and imported data."}}}}},"schemas":{"CancelResult":{"title":"Cancellation result","type":"object","description":"The outcome of a cancellation request.","properties":{"runId":{"type":"string","format":"uuid","description":"The run the cancellation targeted."},"force":{"type":"boolean","description":"Whether a hard stop was requested."},"accepted":{"type":"boolean","description":"Whether the cancellation was accepted. `false` when the run is unknown or already finished."}}},"errorMessage":{"title":"Error","description":"Schema for specific API errors.","type":"object","properties":{"code":{"type":"integer","description":"HTTP status code.","minimum":100,"maximum":599},"status":{"description":"HTTP status.","type":"string"},"message":{"description":"Descriptive error message for debugging.","type":"string"},"details":{"description":"List of problems causing this error.","type":"array","items":{"title":"Error Detail","description":"Error details.","type":"string"}}},"required":["status","code","message"]}},"responses":{"Unauthorized_401":{"description":"Given request is unauthorized - the authorization token is invalid or has expired. Details will be provided in the response payload.","content":{"application/json":{"schema":{"type":"object","properties":{"fault":{"type":"object","properties":{"faultstring":{"type":"string"},"detail":{"type":"object","properties":{"errorcode":{"type":"string"}}}}}}}}}},"Forbidden_403":{"description":"Given authorization scopes are not sufficient and do not match scopes required by the endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorMessage"}}}},"Conflict_409":{"description":"The request conflicts with the current state of the resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorMessage"}}}},"InternalServiceError_500":{"description":"Internal Service Error occurred.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorMessage"}}}}}},"paths":{"/importtool/{tenant}/runs/{runId}/cancel":{"post":{"summary":"Cancelling a run","description":"Requests cancellation of an active run. By default the cancellation is cooperative; with\n`force=true` the run is stopped immediately and its configuration is unblocked.\n\nA run in the `QUEUED` status has not started, so it is cancelled immediately and gets the `CANCELLED`\nstatus, with or without `force`. A run in the `RESUMABLE` status can be stopped only with\n`force=true`. Without `force`, the request returns a `409 Conflict` response.","operationId":"POST-importtool-cancel-run","tags":["Runs"],"parameters":[{"name":"force","in":"query","required":false,"description":"When `true`, hard-stops the run immediately.","schema":{"type":"boolean","default":false}}],"responses":{"202":{"description":"The cancellation was accepted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelResult"}}}},"401":{"$ref":"#/components/responses/Unauthorized_401"},"403":{"$ref":"#/components/responses/Forbidden_403"},"409":{"$ref":"#/components/responses/Conflict_409"},"500":{"$ref":"#/components/responses/InternalServiceError_500"}}}}}}
```

## Retrieving run errors

> Retrieves the errors recorded during a run, paginated.

```json
{"openapi":"3.0.0","info":{"title":"Import Service","version":"0.0.1"},"tags":[{"name":"Runs","description":"Trigger, monitor, and cancel import runs."}],"servers":[{"url":"https://api.emporix.io"}],"security":[{"OAuth2":["importtool.import_trigger"]}],"components":{"securitySchemes":{"OAuth2":{"type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"https://api.emporix.io/oauth/token","scopes":{"importtool.import_trigger":"Needed to trigger, schedule, monitor, and cancel import runs and to read configurations, streams, schedules, runs, and imported data."}}}}},"parameters":{"trait_page":{"name":"page","in":"query","required":false,"description":"The zero-based page number.","schema":{"type":"integer","default":0}},"trait_size":{"name":"size","in":"query","required":false,"description":"The page size.","schema":{"type":"integer"}}},"schemas":{"ErrorRecordPage":{"title":"Error record page","allOf":[{"$ref":"#/components/schemas/Page"},{"type":"object","properties":{"content":{"type":"array","description":"The error records on this page.","items":{"$ref":"#/components/schemas/ErrorRecord"}}}}]},"Page":{"title":"Page","type":"object","description":"Pagination metadata for a page of results.","properties":{"totalElements":{"type":"integer","description":"The total number of elements across all pages."},"totalPages":{"type":"integer","description":"The total number of pages."},"number":{"type":"integer","description":"The current zero-based page number."},"size":{"type":"integer","description":"The page size."}}},"ErrorRecord":{"title":"Error record","type":"object","description":"A single error recorded during a run.","properties":{"id":{"type":"string","format":"uuid","description":"The error identifier."},"runId":{"type":"string","format":"uuid","description":"The run the error occurred in."},"streamId":{"type":"string","format":"uuid","description":"The stream the error occurred in."},"naturalKey":{"type":"string","description":"The source natural key of the offending record."},"targetEntity":{"type":"string","description":"The target writer the record was bound for."},"stage":{"type":"string","description":"The pipeline stage the error occurred in."},"errorCode":{"type":"string","description":"A machine-readable error code."},"message":{"type":"string","description":"A human-readable error message."},"createdAt":{"type":"string","format":"date-time","description":"When the error was recorded."}}},"errorMessage":{"title":"Error","description":"Schema for specific API errors.","type":"object","properties":{"code":{"type":"integer","description":"HTTP status code.","minimum":100,"maximum":599},"status":{"description":"HTTP status.","type":"string"},"message":{"description":"Descriptive error message for debugging.","type":"string"},"details":{"description":"List of problems causing this error.","type":"array","items":{"title":"Error Detail","description":"Error details.","type":"string"}}},"required":["status","code","message"]}},"responses":{"Unauthorized_401":{"description":"Given request is unauthorized - the authorization token is invalid or has expired. Details will be provided in the response payload.","content":{"application/json":{"schema":{"type":"object","properties":{"fault":{"type":"object","properties":{"faultstring":{"type":"string"},"detail":{"type":"object","properties":{"errorcode":{"type":"string"}}}}}}}}}},"Forbidden_403":{"description":"Given authorization scopes are not sufficient and do not match scopes required by the endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorMessage"}}}},"InternalServiceError_500":{"description":"Internal Service Error occurred.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorMessage"}}}}}},"paths":{"/importtool/{tenant}/runs/{runId}/errors":{"get":{"summary":"Retrieving run errors","description":"Retrieves the errors recorded during a run, paginated.","operationId":"GET-importtool-list-run-errors","tags":["Runs"],"parameters":[{"$ref":"#/components/parameters/trait_page"},{"$ref":"#/components/parameters/trait_size"}],"responses":{"200":{"description":"The request was successful. The errors are returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRecordPage"}}}},"401":{"$ref":"#/components/responses/Unauthorized_401"},"403":{"$ref":"#/components/responses/Forbidden_403"},"500":{"$ref":"#/components/responses/InternalServiceError_500"}}}}}}
```

## Retrieving run diagnostics

> Retrieves the source rows represented by a run's feed-quality counters.\
> \
> A run reports how many source rows repeated a natural key (\`duplicateKeys\`) and how many child\
> lines had no parent to attach to (\`unresolvedParents\`). This endpoint identifies the affected rows\
> and returns each record's key, its parent-linking field and value, and the number of lines waiting\
> for each missing parent.\
> \
> Neither counter is a failure, so these rows are kept separately from run errors.\
> \
> The rows are a capped SAMPLE, not necessarily the whole set — \`recorded\` gives how many were\
> stored and \`sampleTruncated\` says whether a stream hit the cap. The run's own counters show the\
> total number of affected rows; do not use the returned row count to measure the size of the problem.

```json
{"openapi":"3.0.0","info":{"title":"Import Service","version":"0.0.1"},"tags":[{"name":"Runs","description":"Trigger, monitor, and cancel import runs."}],"servers":[{"url":"https://api.emporix.io"}],"security":[{"OAuth2":["importtool.import_trigger"]}],"components":{"securitySchemes":{"OAuth2":{"type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"https://api.emporix.io/oauth/token","scopes":{"importtool.import_trigger":"Needed to trigger, schedule, monitor, and cancel import runs and to read configurations, streams, schedules, runs, and imported data."}}}}},"parameters":{"trait_diagnosticsStreamId":{"name":"streamId","in":"query","required":false,"description":"Restrict the rows to those recorded for this stream.","schema":{"type":"string","format":"uuid"}},"trait_diagnosticsKind":{"name":"kind","in":"query","required":false,"description":"Restrict the rows to this kind.","schema":{"type":"string","enum":["UNRESOLVED_PARENT","REPEATED_KEY"]}}},"schemas":{"DiagnosticPage":{"type":"object","description":"A page of diagnostic rows with metadata that indicates whether the response contains all recorded rows or only part of a capped sample. Use `recorded`, `cap`, and `sampleTruncated` to interpret the page. The run's counters show the total number of affected rows.","properties":{"rows":{"type":"array","items":{"$ref":"#/components/schemas/DiagnosticRecord"}},"returned":{"type":"integer","description":"How many rows this response contains."},"recorded":{"type":"integer","description":"How many rows were recorded in total for this scope."},"cap":{"type":"integer","description":"The per-stream, per-kind recording cap."},"sampleTruncated":{"type":"boolean","description":"Whether at least one stream reached the cap. When true, these rows are a sample, and the run's\nown counters show the total number of affected rows."},"note":{"type":"string","description":"A human-readable statement of what this response is."}}},"DiagnosticRecord":{"type":"object","description":"One row behind a feed-quality counter.","properties":{"id":{"type":"string","format":"uuid"},"runId":{"type":"string","format":"uuid"},"streamId":{"type":"string","format":"uuid"},"streamName":{"type":"string","description":"The stream that recorded the row."},"kind":{"type":"string","enum":["UNRESOLVED_PARENT","REPEATED_KEY"],"description":"`UNRESOLVED_PARENT`: a child line whose parent instance did not exist when it was written.\n`REPEATED_KEY`: a source row whose natural key this run had already imported."},"naturalKey":{"type":"string","description":"The record's own natural key in the source."},"linkingField":{"type":"string","description":"`UNRESOLVED_PARENT` only. The field that points at the parent."},"linkingValue":{"type":"string","description":"`UNRESOLVED_PARENT` only. The parent key the line pointed at — the value to look up in the\nsource system."},"targetType":{"type":"string","description":"The target type the row was headed for."},"waitingLines":{"type":"integer","description":"`UNRESOLVED_PARENT` only. The number of child lines waiting for this parent."},"occurrence":{"type":"integer","description":"`REPEATED_KEY` only. How many times this key had already been seen in this run."},"createdAt":{"type":"string","format":"date-time"}}},"errorMessage":{"title":"Error","description":"Schema for specific API errors.","type":"object","properties":{"code":{"type":"integer","description":"HTTP status code.","minimum":100,"maximum":599},"status":{"description":"HTTP status.","type":"string"},"message":{"description":"Descriptive error message for debugging.","type":"string"},"details":{"description":"List of problems causing this error.","type":"array","items":{"title":"Error Detail","description":"Error details.","type":"string"}}},"required":["status","code","message"]}},"responses":{"Unauthorized_401":{"description":"Given request is unauthorized - the authorization token is invalid or has expired. Details will be provided in the response payload.","content":{"application/json":{"schema":{"type":"object","properties":{"fault":{"type":"object","properties":{"faultstring":{"type":"string"},"detail":{"type":"object","properties":{"errorcode":{"type":"string"}}}}}}}}}},"Forbidden_403":{"description":"Given authorization scopes are not sufficient and do not match scopes required by the endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorMessage"}}}},"InternalServiceError_500":{"description":"Internal Service Error occurred.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorMessage"}}}}}},"paths":{"/importtool/{tenant}/runs/{runId}/diagnostics":{"get":{"summary":"Retrieving run diagnostics","description":"Retrieves the source rows represented by a run's feed-quality counters.\n\nA run reports how many source rows repeated a natural key (`duplicateKeys`) and how many child\nlines had no parent to attach to (`unresolvedParents`). This endpoint identifies the affected rows\nand returns each record's key, its parent-linking field and value, and the number of lines waiting\nfor each missing parent.\n\nNeither counter is a failure, so these rows are kept separately from run errors.\n\nThe rows are a capped SAMPLE, not necessarily the whole set — `recorded` gives how many were\nstored and `sampleTruncated` says whether a stream hit the cap. The run's own counters show the\ntotal number of affected rows; do not use the returned row count to measure the size of the problem.","operationId":"GET-importtool-list-run-diagnostics","tags":["Runs"],"parameters":[{"$ref":"#/components/parameters/trait_diagnosticsStreamId"},{"$ref":"#/components/parameters/trait_diagnosticsKind"},{"name":"limit","in":"query","required":false,"description":"Maximum number of rows to return. Defaults differ between the JSON and CSV operations.","schema":{"type":"integer","default":500,"minimum":1,"maximum":50000}}],"responses":{"200":{"description":"The request was successful. The diagnostic rows are returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiagnosticPage"}}}},"401":{"$ref":"#/components/responses/Unauthorized_401"},"403":{"$ref":"#/components/responses/Forbidden_403"},"500":{"$ref":"#/components/responses/InternalServiceError_500"}}}}}}
```

## Downloading run diagnostics as CSV

> Returns the same rows as a CSV attachment, for opening in a spreadsheet or attaching to a ticket.\
> \
> Comment lines above the header indicate whether the \`limit\` parameter restricted the response or\
> a stream reached the recording cap. These comments preserve that context when the file is shared\
> independently of the request.\
> \
> Values are quoted. Any value beginning with \`=\`, \`+\`, \`-\`, or \`@\` is prefixed with an apostrophe\
> so that spreadsheet software does not interpret source-provided data as a formula.

```json
{"openapi":"3.0.0","info":{"title":"Import Service","version":"0.0.1"},"tags":[{"name":"Runs","description":"Trigger, monitor, and cancel import runs."}],"servers":[{"url":"https://api.emporix.io"}],"security":[{"OAuth2":["importtool.import_trigger"]}],"components":{"securitySchemes":{"OAuth2":{"type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"https://api.emporix.io/oauth/token","scopes":{"importtool.import_trigger":"Needed to trigger, schedule, monitor, and cancel import runs and to read configurations, streams, schedules, runs, and imported data."}}}}},"parameters":{"trait_diagnosticsStreamId":{"name":"streamId","in":"query","required":false,"description":"Restrict the rows to those recorded for this stream.","schema":{"type":"string","format":"uuid"}},"trait_diagnosticsKind":{"name":"kind","in":"query","required":false,"description":"Restrict the rows to this kind.","schema":{"type":"string","enum":["UNRESOLVED_PARENT","REPEATED_KEY"]}}},"responses":{"Unauthorized_401":{"description":"Given request is unauthorized - the authorization token is invalid or has expired. Details will be provided in the response payload.","content":{"application/json":{"schema":{"type":"object","properties":{"fault":{"type":"object","properties":{"faultstring":{"type":"string"},"detail":{"type":"object","properties":{"errorcode":{"type":"string"}}}}}}}}}},"Forbidden_403":{"description":"Given authorization scopes are not sufficient and do not match scopes required by the endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorMessage"}}}},"InternalServiceError_500":{"description":"Internal Service Error occurred.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorMessage"}}}}},"schemas":{"errorMessage":{"title":"Error","description":"Schema for specific API errors.","type":"object","properties":{"code":{"type":"integer","description":"HTTP status code.","minimum":100,"maximum":599},"status":{"description":"HTTP status.","type":"string"},"message":{"description":"Descriptive error message for debugging.","type":"string"},"details":{"description":"List of problems causing this error.","type":"array","items":{"title":"Error Detail","description":"Error details.","type":"string"}}},"required":["status","code","message"]}}},"paths":{"/importtool/{tenant}/runs/{runId}/diagnostics/csv":{"get":{"summary":"Downloading run diagnostics as CSV","description":"Returns the same rows as a CSV attachment, for opening in a spreadsheet or attaching to a ticket.\n\nComment lines above the header indicate whether the `limit` parameter restricted the response or\na stream reached the recording cap. These comments preserve that context when the file is shared\nindependently of the request.\n\nValues are quoted. Any value beginning with `=`, `+`, `-`, or `@` is prefixed with an apostrophe\nso that spreadsheet software does not interpret source-provided data as a formula.","operationId":"GET-importtool-download-run-diagnostics-csv","tags":["Runs"],"parameters":[{"$ref":"#/components/parameters/trait_diagnosticsStreamId"},{"$ref":"#/components/parameters/trait_diagnosticsKind"},{"name":"limit","in":"query","required":false,"description":"Maximum number of rows to include. Defaults differ between the JSON and CSV operations.","schema":{"type":"integer","default":50000,"minimum":1,"maximum":50000}}],"responses":{"200":{"description":"The request was successful. The CSV file is returned.","headers":{"Content-Disposition":{"description":"Attachment disposition and the suggested file name.","schema":{"type":"string"}}},"content":{"text/csv":{"schema":{"type":"string"}}}},"401":{"$ref":"#/components/responses/Unauthorized_401"},"403":{"$ref":"#/components/responses/Forbidden_403"},"500":{"$ref":"#/components/responses/InternalServiceError_500"}}}}}}
```

## Retrying the failed records of a run

> Starts a new run that reprocesses only the records that failed in the given run, instead of the\
> whole source. The new run is returned immediately in the \`QUEUED\` status and starts when a worker is\
> free. It reports its own progress. The original run is left untouched and keeps its counters.\
> \
> As with a run that you trigger, the service rejects the retry with a \`409 Conflict\` response while the\
> configuration has a run in the \`QUEUED\`, \`RUNNING\`, or \`RESUMABLE\` status.

```json
{"openapi":"3.0.0","info":{"title":"Import Service","version":"0.0.1"},"tags":[{"name":"Runs","description":"Trigger, monitor, and cancel import runs."}],"servers":[{"url":"https://api.emporix.io"}],"security":[{"OAuth2":["importtool.import_trigger"]}],"components":{"securitySchemes":{"OAuth2":{"type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"https://api.emporix.io/oauth/token","scopes":{"importtool.import_trigger":"Needed to trigger, schedule, monitor, and cancel import runs and to read configurations, streams, schedules, runs, and imported data."}}}}},"schemas":{"ImportRun":{"title":"Run","type":"object","description":"An import run and its reconciled counters.","properties":{"id":{"type":"string","format":"uuid","description":"The run identifier."},"configId":{"type":"string","format":"uuid","description":"The configuration the run belongs to."},"tenant":{"type":"string","description":"The owning tenant."},"trigger":{"type":"string","enum":["MANUAL","SCHEDULED"],"description":"What triggered the run."},"dryRunSample":{"type":"array","description":"Dry-run only. A sample of the mapped records that would be written, so the mapping can be previewed without a real import. Absent on normal runs. Each stream is sampled separately, up to the `sampleSize` set in the run request. A parent stream's records include the records of its composite child streams that have `childStrategy` set to `EMBED` or `PATCH`. Those child records appear in the parent attribute named by the child stream's `embedAttribute`, as a real import writes them. Only child records inside the child stream's own sample are included, so a sampled parent record can show fewer child records than the source contains for that parent, or none. Child records are also sampled under their own stream.","items":{"type":"object","properties":{"stream":{"type":"string","description":"The stream that produced the sample record."},"targetType":{"type":"string","description":"The resolved target type the record would be written to."},"key":{"type":"string","description":"The record's natural/deterministic key."},"fields":{"type":"object","additionalProperties":true,"description":"The mapped target fields that would be written."}}}},"origin":{"type":"string","description":"What requested the run. The `origin` value from the trigger request, or the `trigger` value when `origin` was omitted. Use this field to distinguish a dashboard run from a run started by an integration scenario. The field is absent on runs recorded before it existed."},"status":{"type":"string","enum":["QUEUED","RUNNING","RESUMABLE","SUCCEEDED","PARTIAL","FAILED","CANCELLED","ABORTED"],"description":"The run status. Possible values:\n\n* `QUEUED` – the run waits to start. Nothing has been read yet, and the run has no per-stream\n  progress. `queueWaitingFor` says what the run waits for.\n* `RUNNING` – the run is executing.\n* `RESUMABLE` – the run was interrupted, for example by a service restart, and resumes automatically\n  from its last checkpoint. It is not a final status.\n* `SUCCEEDED` – the run finished, and every record was processed.\n* `PARTIAL` – the run finished, but not completely: some records failed, a limit skipped records,\n  or a stream was not run. The `message` field and the per-stream progress give the details.\n* `FAILED` – the run stopped because of an error.\n* `CANCELLED` – the run was cancelled.\n* `ABORTED` – the service refused to start the run because of the import configuration, for example\n  mappings that have never been published or a changed target schema. Nothing was read or written."},"mode":{"type":"string","enum":["FULL","DELTA"],"description":"The run mode."},"startedAt":{"type":"string","format":"date-time","description":"When the run was requested. If the run was queued first, it began executing later, at `executionStartedAt`."},"executionStartedAt":{"type":"string","format":"date-time","nullable":true,"description":"When the run began executing. Equal to `startedAt`, or later by the time the run spent in the queue. `null` while the run is `QUEUED`, and on runs recorded before the field existed."},"finishedAt":{"type":"string","format":"date-time","description":"When the run finished."},"queuePosition":{"type":"integer","minimum":1,"description":"`QUEUED` runs only. The run's position among the queued runs that can start, where `1` starts next. Runs of all tenants share the queue, and a tenant with fewer runs executing goes first. The value is approximate, because the queue changes while you read it. The field is absent when the run is not queued, when it waits for something other than a worker, or when the service has not yet calculated it."},"queueWaitingFor":{"type":"string","enum":["WORKER","PREVIOUS_RUN","TENANT_LIMIT"],"description":"`QUEUED` runs only. What the run waits for. Possible values:\n\n* `WORKER` – the run waits for a free worker. `queuePosition` gives its place in the queue.\n* `PREVIOUS_RUN` – the run waits for the configuration's current run to finish.\n* `TENANT_LIMIT` – the run waits for one of the tenant's runs to finish, because\n  `maxConcurrentImports` runs are already executing.\n\nThe field is absent when the run is not queued, or when the service has not yet calculated it."},"supersededRequests":{"type":"integer","description":"The number of later scheduled run requests that were added to this run while it was queued. A configuration has at most one queued run, so a scheduled request that arrives while a real run of the whole configuration is queued does not queue a second run."},"lastRequestedAt":{"type":"string","format":"date-time","description":"When the latest scheduled run request counted in `supersededRequests` was made. Absent when `supersededRequests` is `0`."},"recordsRead":{"type":"integer","description":"Records read (created + updated + skipped + deleted + failed)."},"created":{"type":"integer","description":"Records created."},"updated":{"type":"integer","description":"Records updated."},"skipped":{"type":"integer","description":"Records skipped because they were unchanged."},"failed":{"type":"integer","description":"Records that failed."},"deleted":{"type":"integer","description":"Records deleted."},"duplicateKeys":{"type":"integer","description":"Source rows that repeat a key already imported in this run. The import keeps the last row of each repeated key and discards earlier rows. Duplicate keys do not fail the run; they mean the source feed is not unique on the key the stream imports by."},"unresolvedParents":{"type":"integer","description":"Child records that were not imported because their parent could not be found. Counted separately from `skipped`, which counts records that were already up to date."},"message":{"type":"string","description":"A terminal status message, typically set on failure."},"retryOfRunId":{"type":"string","format":"uuid","description":"When the run retries another run's failed records, the identifier of that original run."},"force":{"type":"boolean","description":"Whether the run rewrote every record, bypassing the skip-if-unchanged check."},"dryRun":{"type":"boolean","description":"Whether the run only extracted, mapped, and validated, writing nothing to the target. A dry run legitimately reports zero for every counter, so this distinguishes it from a run that wrote nothing because it failed."},"cancelRequested":{"type":"boolean","description":"Whether cancellation has been requested for a run that is still finishing."},"dryRunSampleSize":{"type":"integer","description":"For a dry run, how many mapped records were kept as a sample."},"dryRunPublished":{"type":"boolean","description":"Dry-run only. Whether the dry run used the published mappings (`true`) or the draft mappings (`false`)."},"mappingVersions":{"type":"array","description":"The published mapping version each stream uses in this run, fixed when the run starts executing. Version `0` means that the stream has no published mappings. The field is absent while the run is `QUEUED`, on a dry run of the draft mappings, and on runs recorded before it existed.","items":{"type":"object","properties":{"streamId":{"type":"string","format":"uuid","description":"The stream identifier."},"version":{"type":"integer","description":"The published mapping version the stream uses."}}}}}},"errorMessage":{"title":"Error","description":"Schema for specific API errors.","type":"object","properties":{"code":{"type":"integer","description":"HTTP status code.","minimum":100,"maximum":599},"status":{"description":"HTTP status.","type":"string"},"message":{"description":"Descriptive error message for debugging.","type":"string"},"details":{"description":"List of problems causing this error.","type":"array","items":{"title":"Error Detail","description":"Error details.","type":"string"}}},"required":["status","code","message"]}},"responses":{"Unauthorized_401":{"description":"Given request is unauthorized - the authorization token is invalid or has expired. Details will be provided in the response payload.","content":{"application/json":{"schema":{"type":"object","properties":{"fault":{"type":"object","properties":{"faultstring":{"type":"string"},"detail":{"type":"object","properties":{"errorcode":{"type":"string"}}}}}}}}}},"Forbidden_403":{"description":"Given authorization scopes are not sufficient and do not match scopes required by the endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorMessage"}}}},"NotFound_404":{"description":"The requested resource does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorMessage"}}}},"Conflict_409":{"description":"The request conflicts with the current state of the resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorMessage"}}}},"InternalServiceError_500":{"description":"Internal Service Error occurred.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorMessage"}}}}}},"paths":{"/importtool/{tenant}/runs/{runId}/retry":{"post":{"summary":"Retrying the failed records of a run","description":"Starts a new run that reprocesses only the records that failed in the given run, instead of the\nwhole source. The new run is returned immediately in the `QUEUED` status and starts when a worker is\nfree. It reports its own progress. The original run is left untouched and keeps its counters.\n\nAs with a run that you trigger, the service rejects the retry with a `409 Conflict` response while the\nconfiguration has a run in the `QUEUED`, `RUNNING`, or `RESUMABLE` status.","operationId":"POST-importtool-retry-run","tags":["Runs"],"responses":{"200":{"description":"The request was successful. The retry run has been queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportRun"}}}},"401":{"$ref":"#/components/responses/Unauthorized_401"},"403":{"$ref":"#/components/responses/Forbidden_403"},"404":{"$ref":"#/components/responses/NotFound_404"},"409":{"$ref":"#/components/responses/Conflict_409"},"500":{"$ref":"#/components/responses/InternalServiceError_500"}}}}}}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://developer.emporix.io/api-references/readme/api-reference-33/runs.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
