---
title: "Approve or reject a roster import"
method: GET
path: "/roster/{rosterId}/import"
tags: ["Roster"]
---

# Approve or reject a roster import

`GET /roster/{rosterId}/import`

Records a decision on a roster job that has finished validation and, when approved, starts ingesting its rows.

**When to use:** call this once a roster has been reviewed and someone has decided whether its data should be written into the platform.

**Preconditions:** supply the `tenant-id` header, the job's `rosterId`, and the `action` query parameter, which is matched case-insensitively. The roster must be in `VALIDATED`, `IN_PROGRESS`, or `VALIDATION_FAILED` state; a job in any other state is rejected with 400. A roster still in `PRE_PROCESSING` is a special case - it can only be rejected, never approved, and only by a provider data administrator who does not also hold the roster analyst role.

**Outcomes:** `approved` moves the roster to `APPROVED` and queues ingestion, so its rows begin flowing into the platform; `rejected` moves it to `CANCELLED` and no further processing takes place.

**Note on the HTTP method:** this endpoint is exposed as a GET but changes state and triggers ingestion. Treat it as a write - never issue it speculatively, prefetch it, or allow it to be cached or retried automatically.

**What you get back:** the roster job reflecting the decision. Not idempotent - approving a roster twice can queue ingestion twice. The job's `data` object carries its status, file details, and record counters; see `GET /roster/{id}` for the full list of keys it can hold.

## Path parameters

- `rosterId` string, required

## Query parameters

- `action` string, required

## Headers

- `tenant-id` string, required

## Response `200`

The roster job after the decision was applied, at its new status.

- RosterResponse
  - `id` string
  - `tenantId` string
  - `templateId` string
  - `createdAt` string, date
  - `createdBy` string
  - `updatedAt` string, date
  - `updatedBy` string
  - `data` RosterJobData — Payload of a roster import job. Keys appear as processing progresses - none is guaranteed present at every stage, and new keys may be introduced by newer features, so treat unknown keys as valid. Key names mirror RosterDataRecord.
    - `status` 'PENDING' | 'IN_PROGRESS' | 'VALIDATION_IN_PROGRESS' | 'VALIDATION_FAILED' | 'PRE_PROCESSING' | 'VALIDATED' | 'COMPLETED' | 'APPROVED' | 'PARTIAL_IMPORTED' | 'REVALIDATE' | 'FAILED' | 'CANCELLED' — Current stage of the job. See the roster read operations' descriptions for the meaning of each value.
    - `jobType` 'PRACTITIONER' | 'FACILITY' | 'GROUP' — Kind of entity the file contains. GROUP uploads require the tenant's supportGroupRosters configuration.
    - `templateId` string — Identifier of the roster template describing the file's column layout.
    - `description` string — Free-text note supplied when the roster was uploaded.
    - `filename` string — Name of the file currently attached to the job.
    - `filePath` string — Storage path of that file, relative to the bucket.
    - `bucketName` string — Storage bucket holding the file.
    - `sheetName` string — Worksheet read from the file, for .xlsx uploads only.
    - `initialFilename` string — The file first uploaded, retained after a reupload replaces it.
    - `initialFilePath` string — Storage path of the first uploaded file, retained after a reupload.
    - `uploadCount` integer — How many times a file has been uploaded to this job; 1 until the first reupload.
    - `orderedFileColumns` string — The file's column headers in the order they appear in the header row, joined by the ",/" separator.
    - `totalRecords` integer — Rows found in the file.
    - `validRecords` integer — Rows that passed validation.
    - `invalidRecords` integer — Rows that failed validation.
    - `completedRecords` integer — Rows that were ingested successfully.
    - `failedRecords` integer — Rows that could not be ingested.
    - `rosterFileUrl` string — Time-limited link to the uploaded roster file. Present on the single-job read only.
    - `templateUrl` string — Time-limited link to the template the roster was mapped with. Present on the single-job read only.
    - `mappingsFileUrl` string — Time-limited link to the resolved column mappings. Present on the single-job read only.
    - `failureReasons` string — Validation or ingestion errors explaining why rows did not succeed.
    - `importedAt` string — When ingestion finished, as an ISO-8601 timestamp in UTC.
    - `roster-export-path` string — Storage path of the failed-records export, present once one has been generated.
    - `roster-export-url` string — Time-limited link to the failed-records export, present once one has been generated.
  - `invalidCount` integer
  - `validCount` integer
  - `completedCount` integer
  - `failedCount` integer

## Other responses

- `400` — Returned for every decision that cannot be applied: `action` is not `approved` or `rejected`, the roster is in a state that does not accept a decision (including an attempt to approve a roster still in `PRE_PROCESSING`), no roster job with the supplied `rosterId` exists, or a `PRE_PROCESSING` rejection was attempted by a caller whose role does not allow it. All of these currently surface as 400 - not 404 or 403 - so read the error message to distinguish the cause.
- `401` — Returned when the request carries no valid authentication.
- `403` — Returned when the caller lacks the UPDATE_ROSTER permission for this tenant.

---

[API](https://skmtc.net/certifyos/apis/certify-api-layer.md) · [All operations](https://skmtc.net/certifyos/apis/certify-api-layer/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/certifyos/certify-api-layer/revisions/563848e0ecc0/schema)
