Skip to content

Create a user import job.

POST
/api/admin/jobs/users/import
Code sample: Shell / cURL
curl --request POST \
--url https://auth.example.com/api/admin/jobs/users/import \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "file_key": "imports/default/018f3f7c/users.csv", "size_bytes": 4096, "content_type": "text/csv", "checksum_sha256": "9d6f965ac832e40a5c8a5d7aa7a4b1e0e67f...", "options": { "skip_header": true, "on_duplicate": "skip", "validate_only": false } }'

Registration state is read-only: CSV registration_state and user_type=anonymous are rejected. Updating an existing guest with user_type=end_user preserves guest registration; promotion requires the account upgrade flow. Queues a users/import job for an already uploaded CSV artifact. The handler verifies tenant ownership, content type, size, checksum, and import options before creating the pending job. CSV headers and cell values are normalized before schema validation. Group conditions evaluate only validated, persisted attributes after account publication, never raw CSV columns. New accounts use the durable account-directory creation workflow. A row awaiting publication remains uncounted in processed/succeeded totals and resumes with the same job/row identity; progress logs expose directory_pending. Existing users are updated on their verified account storage route. A replay of this job’s own account creation precedes duplicate-email handling. Optional columns ial (IAL1, IAL2 or IAL3) and ial_verified_at (a date, or a date-time with a time zone; the time of the import when omitted) assert the identity assurance of the person. A new account is created with it as import evidence of the job, in place of the tenant’s default IAL (assurance.default_ial, recorded as tenant-policy evidence when a row gives none). For an existing account (on_duplicate=update), a row with an ial replaces what earlier imports asserted, and a row without one keeps it; evidence of other sources is never touched. A claim is the level with its verification time (ial_verified_at, or the time the job was created when the row gives none), so the same level without a date in a later import is a new verification, while the same job processed again records nothing new. A CSV import is an administrator’s action: it is not held to the ceiling on what SCIM tokens may assert (assurance.scim_max_ial). ial_verified_at without ial, an unknown ial, a time in the future and a date that does not exist (February 30, month 13) fail the row. The columns are read as assurance only where the tenant has no custom attribute named ial or ial_verified_at (such names cannot be given to a custom attribute, nor an inactive one with such a name made active): while it has, a row with the column fails (also when only validated; checked for each such row) until the attribute is renamed or the column removed. Import evidence is identified by its content (person, ial, ial_verified_at; the time of the job when the row gives none), from any job: identical content never re-activates evidence that was revoked, whoever revoked it, so a row processed again after a failure records nothing new. Evidence of an existing account is written only after its row was updated, so a row that fails changes none; a row whose evidence step failed after the update is reported as assurance_update_failed (retryable) and is imported again. When the tenant default cannot be read, a row without ial fails with default_ial_unavailable (retryable) and creates nothing; import it again. When a new account was written but its evidence could not be recorded, the row is not counted: the job tries it again (up to five times), which finds the row’s creation operation and completes it, recording the evidence once; after that the row fails as assurance_initial_failed (retryable) and its creation stays unfinished.

Media type application/json
object
file_key
string
r2_key
string
size_bytes
integer
>= 1
content_type
string
checksum_sha256
string
options
object
skip_header
boolean
default: true
on_duplicate
string
default: skip
Allowed values: update skip error
validate_only
boolean
key
additional properties
key
additional properties
Example
{
"file_key": "imports/default/018f3f7c/users.csv",
"size_bytes": 4096,
"content_type": "text/csv",
"checksum_sha256": "9d6f965ac832e40a5c8a5d7aa7a4b1e0e67f...",
"options": {
"skip_header": true,
"on_duplicate": "skip",
"validate_only": false
}
}

User import job accepted response.

Media type application/json
object
job_id
required
string
status
required
string
Allowed values: pending
job_type
required
string
created_at
required
string format: date-time
estimated_completion
required
string format: date-time
key
additional properties
Example
{
"status": "pending"
}

Error response.

Media type application/json
object
error
string
message
string
error_description
string
key
additional properties
Example generated
{
"error": "example",
"message": "example",
"error_description": "example"
}

Error response.

Media type application/json
object
error
string
message
string
error_description
string
key
additional properties
Example generated
{
"error": "example",
"message": "example",
"error_description": "example"
}

Error response.

Media type application/json
object
error
string
message
string
error_description
string
key
additional properties
Example generated
{
"error": "example",
"message": "example",
"error_description": "example"
}

Error response.

Media type application/json
object
error
string
message
string
error_description
string
key
additional properties
Example generated
{
"error": "example",
"message": "example",
"error_description": "example"
}

Error response.

Media type application/json
object
error
string
message
string
error_description
string
key
additional properties
Example generated
{
"error": "example",
"message": "example",
"error_description": "example"
}

Error response.

Media type application/json
object
error
string
message
string
error_description
string
key
additional properties
Example generated
{
"error": "example",
"message": "example",
"error_description": "example"
}