---
title: "listErpImports"
method: GET
path: "/v2/erp/imports"
tags: ["erp-imports"]
---

# listErpImports

`GET /v2/erp/imports`

List recent pricing-file import jobs for the org, newest first.

Pass `next_cursor` back as `cursor` for the next page. A page can be
shorter than `limit` and still have more behind it, so stop on
`next_cursor: null`.

## Query parameters

- `limit` integer
- `cursor` string

## Response `200`

Import jobs

- ErpImportList
  - `results` ErpImportJob[], required
    - `import_id` string, required — `imp_{ULID}` — time-ordered, also used as the job's correlation_id.
    - `org_id` string, required
    - `created_by` string
    - `integration_id` string — The integration owning the chosen use case. Absent until the first `:validate`.
    - `use_case_slug` string — The inbound use case whose mapping drives both phases. Absent until the first `:validate`, and MUTABLE — re-validating with a different use case replaces it.
    - `format` 'csv' | 'xlsx', required
    - `status` 'PENDING' | 'VALIDATING' | 'READY' | 'PROCESSING' | 'IMPORTED' | 'FAILED' | 'CANCELLING' | 'CANCELLED', required — PENDING → VALIDATING → READY → PROCESSING → IMPORTED, with FAILED reachable from any working status, and CANCELLING → CANCELLED reachable from VALIDATING or PROCESSING via :abort. Only IMPORTED and CANCELLED are terminal. READY and FAILED both accept a further `:validate`, which is how a wrong use case is corrected without re-uploading the file. IMPORTED means every row was handed to the platform, not that the platform finished — per-row outcomes live in monitoring, filtered by correlation_id. A file that fails validation is FAILED with error.code = VALIDATION_BLOCKED. READY is legitimately idle for as long as the user takes to confirm, so it carries no running work and never goes stale. CANCELLING is transient and cooperative: the abort has been recorded but the worker only notices at its next batch boundary. Rows already published stay published — a stop is not a rollback.
    - `s3_input_ref` S3Reference, required
      - `bucket` string, required
      - `key` string, required
    - `validation` ErpImportValidation — Validate-phase summary: what the file will create, and whether it may be confirmed. Absent until the validate phase completes. No per-row detail is kept — a rejected file is corrected and imported again.
      - `total_rows` integer, required — Data rows read from the file.
      - `blocking` integer, required
      - `warnings` integer, required
      - `entities` object, required — Distinct entities the file expresses, keyed by entity slug.
      - `issues` ErpImportIssue[] — Whole-file issues. At most 20 are kept; the count of everything found is in blocking and warnings. Warnings here are what `ack_warnings` on `:execute` acknowledges.
        - `code` 'UNIQUE_ID_COLUMN_MISSING' | 'MAPPED_COLUMN_MISSING' | 'MALFORMED_ROW' | 'INVALID_ENCODING' | 'EMPTY_FILE' | 'TOO_MANY_ROWS', required — Enum of possible issue codes.
        - `severity` 'warning' | 'blocking', required
        - `message` string, required — User-facing explanation. Lists at most 10 column names; `columns` has all of them.
        - `columns` string[] — The columns this issue is about, so clients render names rather than parsing the message.
    - `progress` ErpImportProgress — How far the currently running phase has got. Written at every batch boundary, so it advances during long runs rather than only at the end. `total_rows` is ABSENT during the validate phase until the file has been read to the end — there is deliberately no counting pass, since that would be a second unbounded read of the whole file. Render an indeterminate indicator while it is missing: dividing by a missing total yields a determinate bar pinned at 0%, which reads as a hung import.
      - `processed_rows` integer, required — Rows fully processed. An exact "the first N rows are done" watermark, not an estimate — it only advances once a batch has been completely handled.
      - `total_rows` integer — Rows in the file. Known only once a phase has read to EOF; the execute phase has it from the start, because validate recorded it first.
    - `error` ErpImportError — Why the import failed — present if and only if status = FAILED.
      - `code` 'VALIDATION_BLOCKED' | 'FILE_FORMAT_UNSUPPORTED' | 'FILE_UNAVAILABLE' | 'VALIDATE_TIMEOUT' | 'IMPORT_TIMEOUT' | 'USE_CASE_NOT_USABLE' | 'IMPORT_NO_PROGRESS' | 'INTERNAL_ERROR', required — Enum of possible error codes.
      - `message` string, required — User-facing explanation of `type`.
    - `correlation_id` string — Scopes this run in monitoring. Always equal to `import_id`.
    - `activity_id` string
    - `created_at` string, date-time, required
    - `updated_at` string, date-time, required
  - `next_cursor` string, nullable — Cursor for the next page, or null when there are no more rows.

## Other responses

- `400` — Bad request
- `403` — Forbidden - insufficient permissions
- `500` — Internal Server Error

---

[API](https://skmtc.net/epilot/apis/integration-toolkit-api.md) · [All operations](https://skmtc.net/epilot/apis/integration-toolkit-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/epilot/integration-toolkit-api/revisions/68961a011db0/schema)
