List roster jobs for the tenant
GET/roster
Returns a page of roster import jobs belonging to the tenant named in the tenant-id header.
When to use: call this to browse or monitor roster jobs; for a single job, use GET /roster/{id}, which additionally returns a download link for the uploaded file.
Pagination: three schemes are available and exactly one should be used per request - offset paging with page and size, forward cursor paging with startAfterId, or backward cursor paging with endAtId. Combining them in a single request produces undefined results.
Sorting and filtering: sortBy chooses the field to order by and defaults to createdAt, while sortDirection accepts ASC or DESC and defaults to DESC. The optional filter parameter takes a URL-encoded JSON object supporting eq, neq, gt, gte, lt, lte, in, nin, and contains; tenantId is applied automatically from the header and must not be included.
What you get back: an envelope carrying the roster jobs in data, along with pagination links and a total count where the underlying store reports one. Read-only; no state is mutated. Note: when the upstream data layer fails (including an unparseable filter), this endpoint currently returns 200 with an empty body rather than an error status - treat an empty (non-envelope) body as a retryable failure, not as an empty result set.
Fields carried in data. A roster job's payload is a free-form object, so its keys are documented here rather than as schema properties. Not every key is present at every stage - counters and result keys appear as processing progresses.
Status and type
status: current stage of the job. Each value means:PENDING: accepted and queued; validation has not started.PRE_PROCESSING: held for review before validation, for uploads that require it.VALIDATION_IN_PROGRESS: rows are being checked against the roster's schema.VALIDATION_FAILED: validation finished and at least one row failed; the job waits for corrections.VALIDATED: every row passed validation; the job is waiting for an approve or reject decision.REVALIDATE: corrected rows have been resubmitted and validation is running again.APPROVED: the import was approved and ingestion has been queued.IN_PROGRESS: rows are being written into the platform.COMPLETED: ingestion finished;completedRecordsandfailedRecordsreport the outcome.FAILED: the job stopped on an error and did not finish.CANCELLED: the import was rejected, or the job was cancelled before ingestion.
jobType: kind of entity the file contains - PRACTITIONER, FACILITY, or GROUP (GROUP uploads require the tenant's supportGroupRosters configuration).templateId: identifier of the roster template describing the file's column layout.description: free-text note supplied when the roster was uploaded.
File
filename: name of the file currently attached to the job.filePath: storage path of that file, relative to the bucket.bucketName: storage bucket holding the file.sheetName: worksheet read from the file, for .xlsx uploads only.initialFilename,initialFilePath: the file first uploaded, retained after a reupload replaces it.uploadCount: how many times a file has been uploaded to this job; 1 until the first reupload.attemptNumber: which upload attempt the job is on. UnlikeuploadCountthis increments on every reupload, including an internal admin's. Absent on jobs that predate attempt tracking.attempts: summaries of finished upload attempts, oldest first. Bounded, not complete: the job record keeps only the more recent attempts so it stays small - how many is configurable, and a size guard on the stored array can leave fewer - so readattemptsTruncatedfor how many summaries were dropped. Returned on single-job reads and on list responses.GET /roster/{id}/attemptsserves this same bounded set; it does not return the dropped summaries.attemptsTruncated: how many attempt summaries were dropped fromattemptsto keep the job record small; greater than zero meansattemptsis not the full history. The dropped summaries are not served byGET /roster/{id}/attemptseither - their row-level data is retained in the row history store for attempts that were captured, and is not reachable through this API.orderedFileColumns: the file's column headers, in the order they appear in the header row.
Counters (populated as validation and ingestion progress)
totalRecords: rows found in the file.validRecords,invalidRecords: rows that passed and failed validation.softErrorRecords: rows whose only issues are soft warnings (VALIDATED_WITH_WARNINGS) — still imported on approval; disjoint frominvalidRecords(CP-37160).completedRecords,failedRecords: rows that were ingested successfully and rows that were not.
Links (generated per request on the single-job read, and short-lived)
rosterFileUrl: time-limited link to the uploaded roster file.templateUrl: time-limited link to the template the roster was mapped with.mappingsFileUrl: time-limited link to the resolved column mappings.
Results
failureReasons: validation or ingestion errors explaining why rows did not succeed.importedAt: when ingestion finished, as an ISO-8601 timestamp in UTC.roster-export-path,roster-export-url: storage path and time-limited link for the failed-records export, present once one has been generated.
Request
Responses
- 200
- 401
- 403
A page of roster jobs for the tenant, ordered by the requested sort field.
Returned when the request carries no valid authentication.
Returned when the caller lacks the READ_ROSTER permission for this tenant.