Skip to main content

Bulk Import API

Table of Contents

Top

upsquad/bulkimport/v1/bulkimport.proto

ApplyCsvRequest

ApplyCsvRequest commits a previously-previewed CSV in 50-row chunks.

FieldTypeLabelDescription
org_idstringorg_id is the tenant the CSV is applied to.
kindImportKindkind selects the row shape (users vs groups).
csv_payloadbytescsv_payload is the raw CSV bytes. Max 10 MiB.
request_idstringrequest_id is the client-generated idempotency key. ≤128 chars. Same (org_id, request_id) MUST short-circuit on retry.

ApplyCsvResponse

ApplyCsvResponse is one frame of the server-streaming apply response.

FieldTypeLabelDescription
kindApplyCsvResponse.Kindkind discriminates the frame type.
job_idstringjob_id is the import_jobs.id value.
statusJobStatusstatus is the current status of the job.
total_rowsint32total_rows is the total number of parsed rows.
processed_rowsint32processed_rows is the number of rows processed so far (running total).
error_rowsint32error_rows is the number of rows that failed validation / write.
row_errorsRowErrorrepeatedrow_errors is only populated on the terminal frame; truncated at 1000.

GetImportJobRequest

GetImportJobRequest fetches a single import_jobs row by id.

FieldTypeLabelDescription
org_idstringorg_id is the tenant (must match job.org_id).
job_idstringjob_id is the import_jobs.id value.

GetImportJobResponse

GetImportJobResponse returns the requested import job.

FieldTypeLabelDescription
jobImportJobjob is the persisted import_jobs row.

ImportJob

ImportJob is the domain model for a row in import_jobs.

FieldTypeLabelDescription
idstringid is the row primary key (uuid).
org_idstringorg_id is the tenant.
kindImportKindkind is the row shape.
statusJobStatusstatus is the lifecycle state.
total_rowsint32total_rows is the number of data rows in the CSV.
processed_rowsint32processed_rows is the number of rows processed.
error_rowsint32error_rows is the number of rows that errored.
errorsRowErrorrepeatederrors is the capped per-row error list (≤1000).
started_atgoogle.protobuf.Timestampstarted_at is when the job transitioned to running.
completed_atgoogle.protobuf.Timestampcompleted_at is when the job reached a terminal status.
created_atgoogle.protobuf.Timestampcreated_at is when the job row was inserted.
updated_atgoogle.protobuf.Timestampupdated_at is the latest write timestamp.
submitted_by_member_idstringsubmitted_by_member_id is the uploader's member id; empty for SCIM.
source_refstringsource_ref is the opaque source pointer (vault:// or scim_sync_runs.id).

PreviewCsvRequest

PreviewCsvRequest parses a CSV in-memory and diffs against current state.

FieldTypeLabelDescription
org_idstringorg_id is the tenant under which the CSV is interpreted. Must match the caller's RLS scope.
kindImportKindkind selects the row shape (users vs groups).
csv_payloadbytescsv_payload is the raw CSV bytes. Max 10 MiB (≈10k rows).

PreviewCsvResponse

PreviewCsvResponse is one frame of the server-streaming preview response. Exactly one of row or summary is set per frame.

FieldTypeLabelDescription
rowPreviewRowrow is emitted for every parsed CSV row in order.
summaryPreviewSummarysummary is the terminal frame with aggregate counters.

PreviewRow

PreviewRow is the diff classification for a single CSV row.

FieldTypeLabelDescription
row_indexint32row_index is 1-based and excludes the header row.
outcomeRowOutcomeoutcome is the diff classification.
keystringkey is the lookup value (email for users, path for groups) the server used to resolve the row against current state.
error_messagestringerror_message is populated when outcome=ERROR.
changed_fieldsstringrepeatedchanged_fields lists the field names that differ from current state when outcome=UPDATE. Empty otherwise.

PreviewSummary

PreviewSummary is the terminal aggregate of a PreviewCsv stream.

FieldTypeLabelDescription
total_rowsint32total_rows is the number of data rows parsed (excluding header).
create_countint32create_count is the number of rows with outcome=CREATE.
update_countint32update_count is the number of rows with outcome=UPDATE.
noop_countint32noop_count is the number of rows with outcome=NOOP.
error_countint32error_count is the number of rows with outcome=ERROR.

RowError

RowError is a structured per-row error entry.

FieldTypeLabelDescription
row_indexint32row_index is 1-based (data-row index, header excluded).
codestringcode is a stable machine-readable error code.
messagestringmessage is the human-readable error detail.

ApplyCsvResponse.Kind

Kind names the event shape carried by this frame.

NameNumberDescription
KIND_UNSPECIFIED0Default zero value — never valid on the wire.
KIND_JOB_ACCEPTED1JOB_ACCEPTED fires once when the import_jobs row is inserted (or resolved from idempotency cache). Contains the job id.
KIND_CHUNK_PROCESSED2CHUNK_PROCESSED fires after each 50-row chunk commits.
KIND_JOB_COMPLETED3JOB_COMPLETED is the terminal event. Contains the final status and counters.

ImportKind

ImportKind names the shape the CSV payload targets. These match the CHECK enum on import_jobs.kind (migration 068) exactly.

NameNumberDescription
IMPORT_KIND_UNSPECIFIED0Default zero value — never valid on the wire.
IMPORT_KIND_CSV_USERS1CSV payload targets members (users).
IMPORT_KIND_CSV_GROUPS2CSV payload targets org_units (groups).

JobStatus

JobStatus mirrors the CHECK enum on import_jobs.status.

NameNumberDescription
JOB_STATUS_UNSPECIFIED0Default zero value — never valid on the wire.
JOB_STATUS_QUEUED1Inserted, awaiting work.
JOB_STATUS_RUNNING2Actively being processed.
JOB_STATUS_SUCCEEDED3Completed with zero row errors.
JOB_STATUS_PARTIAL4Completed but one or more rows errored.
JOB_STATUS_FAILED5Terminal failure before any row was committed.

RowOutcome

RowOutcome classifies the diff/apply outcome for a single CSV row.

NameNumberDescription
ROW_OUTCOME_UNSPECIFIED0Default zero value — never valid on the wire.
ROW_OUTCOME_CREATE1Row represents a new entity to be created.
ROW_OUTCOME_UPDATE2Row represents an update to an existing entity.
ROW_OUTCOME_NOOP3Row matches current state exactly; no write required.
ROW_OUTCOME_ERROR4Row failed validation and will not be applied.
ROW_OUTCOME_SKIPPED5Apply-only: row was skipped because idempotency kicked in.

BulkImportService

BulkImportService is the Connect-RPC surface for CSV preview + apply.

Method NameRequest TypeResponse TypeDescription
PreviewCsvPreviewCsvRequestPreviewCsvResponse streamPreviewCsv parses and validates a CSV payload without touching tenant state. The server streams one PreviewCsvResponse per parsed row followed by a terminal summary response.
ApplyCsvApplyCsvRequestApplyCsvResponse streamApplyCsv commits the parsed rows in 50-row chunks. Idempotent on (org_id, request_id): a retry returns the original job's progress without re-executing side effects, but ONLY when the prior job is in a terminal state (succeeded / partial / failed). A retry that hits a non-terminal row (queued / running) is rejected with FailedPrecondition so partial work is never misreported as complete (#619). The server streams one ApplyCsvResponse per chunk plus a terminal response with kind=JOB_COMPLETED.
GetImportJobGetImportJobRequestGetImportJobResponseGetImportJob returns the current state of a previously-submitted import job. Primarily used by the console to resume progress tracking after a transient network drop.

Scalar Value Types

.proto TypeNotesC++JavaPythonGoC#PHPRuby
doubledoubledoublefloatfloat64doublefloatFloat
floatfloatfloatfloatfloat32floatfloatFloat
int32Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead.int32intintint32intintegerBignum or Fixnum (as required)
int64Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead.int64longint/longint64longinteger/stringBignum
uint32Uses variable-length encoding.uint32intint/longuint32uintintegerBignum or Fixnum (as required)
uint64Uses variable-length encoding.uint64longint/longuint64ulonginteger/stringBignum or Fixnum (as required)
sint32Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s.int32intintint32intintegerBignum or Fixnum (as required)
sint64Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s.int64longint/longint64longinteger/stringBignum
fixed32Always four bytes. More efficient than uint32 if values are often greater than 2^28.uint32intintuint32uintintegerBignum or Fixnum (as required)
fixed64Always eight bytes. More efficient than uint64 if values are often greater than 2^56.uint64longint/longuint64ulonginteger/stringBignum
sfixed32Always four bytes.int32intintint32intintegerBignum or Fixnum (as required)
sfixed64Always eight bytes.int64longint/longint64longinteger/stringBignum
boolboolbooleanbooleanboolboolbooleanTrueClass/FalseClass
stringA string must always contain UTF-8 encoded or 7-bit ASCII text.stringStringstr/unicodestringstringstringString (UTF-8)
bytesMay contain any arbitrary sequence of bytes.stringByteStringstr[]byteByteStringstringString (ASCII-8BIT)