Skip to content

Product documentation

UserImport

Bulk user import — synchronous batches and asynchronous jobs, with pre-hashed passwords carried over so migrated users sign in without a reset (SSO-1992).

UserImport

Bulk user import — synchronous batches and asynchronous jobs, with pre-hashed passwords carried over so migrated users sign in without a reset (SSO-1992).

Base URL: https://api.stg.thoryn.org

Operations

MethodPathSummaryScopes
POST/api/v1/users/importBulk-import users synchronouslytenant:users.import
POST/api/v1/users/import/auth0Bulk-import users from an Auth0 export synchronouslytenant:users.import
POST/api/v1/users/import/auth0/jobsSubmit an asynchronous Auth0-export import jobtenant:users.import
POST/api/v1/users/import/cognitoBulk-import users from a Cognito export synchronouslytenant:users.import
POST/api/v1/users/import/cognito/jobsSubmit an asynchronous Cognito-export import jobtenant:users.import
GET/api/v1/users/import/jobsList import jobstenant:users.import
POST/api/v1/users/import/jobsSubmit an asynchronous bulk-import jobtenant:users.import
GET/api/v1/users/import/jobs/{id}Get an import jobtenant:users.import
POST/api/v1/users/import/jobs/{id}/cancelCancel an import jobtenant:users.import

Operation details

POST /api/v1/users/import

Bulk-import users synchronously

Imports up to 500 users into the caller's tenant and returns the per-row outcome. Partial success is normal: one bad row never aborts the batch, and a user whose email already exists is skipped rather than overwritten. Rows may carry a pre-hashed password so migrated users sign in without a reset. For larger batches use POST /api/v1/users/import/jobs. Pass ?dryRun=true to validate the batch without writing any row — the response is the same shape, read as a prediction (CREATED = would-create, SKIPPED_DUPLICATE = would-skip, ERROR = would-fail with that reason).

  • Operation ID: userImportImportUsers
  • Required scopes: tenant:users.import

Parameters:

NameInRequiredTypeDescription
dryRunquerynobooleanWhen true, validate the batch and return the predicted per-row outcome without writing any user. Same validation and same response shape as a real import; zero rows are created. Defaults to false (a real import).

Request body (required): application/jsonImportUsersRequest

Responses:

StatusDescriptionBody
200OKobject
401Unauthorized — bearer token missing, expired, signed by an untrusted issuer, or missing the tnt tenant claim.Problem (problem+json)
403Forbidden — token lacks a required tenant:* scope, or the tnt claim does not match the tenant addressed by the request path.Problem (problem+json)

POST /api/v1/users/import/auth0

Bulk-import users from an Auth0 export synchronously

Maps a standard Auth0 bulk user-export (a JSON array of user objects) into the platform's import model and imports up to 500 users into the caller's tenant, returning the per-row outcome. Auth0 bcrypt password hashes (custom_password_hash or passwordHash) are carried over verbatim so migrated users sign in without a reset. Partial success is normal. For larger exports use POST /api/v1/users/import/auth0/jobs. Pass ?dryRun=true to validate the whole export without writing any row — the response is the same shape, read as a prediction.

  • Operation ID: userImportImportAuth0Users
  • Required scopes: tenant:users.import

Parameters:

NameInRequiredTypeDescription
dryRunquerynobooleanWhen true, validate the batch and return the predicted per-row outcome without writing any user. Same validation and same response shape as a real import; zero rows are created. Defaults to false (a real import).

Request body (required): application/jsonAuth0User[]

Responses:

StatusDescriptionBody
200OKobject
401Unauthorized — bearer token missing, expired, signed by an untrusted issuer, or missing the tnt tenant claim.Problem (problem+json)
403Forbidden — token lacks a required tenant:* scope, or the tnt claim does not match the tenant addressed by the request path.Problem (problem+json)

POST /api/v1/users/import/auth0/jobs

Submit an asynchronous Auth0-export import job

Maps a standard Auth0 bulk user-export (a JSON array of user objects) into the platform's import model and submits it as an asynchronous job (up to 10 000 users). Each user's federation provider is resolved against the caller's configured federation members before the job is enqueued: a resolvable provider is normalised to its platform type and enqueued, an unresolvable one is rejected up front (unresolved_federation_provider) and never enqueued. Returns 202 with the enqueued job plus any up-front rejections ({job, rejected}); when every row is rejected the response is 200 with a null job. Poll, list and cancel the job through the shared /api/v1/users/import/jobs surface — this is the same job model, not a parallel one.

  • Operation ID: userImportCreateAuth0Job
  • Required scopes: tenant:users.import

Request body (required): application/jsonAuth0User[]

Responses:

StatusDescriptionBody
200OKobject
401Unauthorized — bearer token missing, expired, signed by an untrusted issuer, or missing the tnt tenant claim.Problem (problem+json)
403Forbidden — token lacks a required tenant:* scope, or the tnt claim does not match the tenant addressed by the request path.Problem (problem+json)

POST /api/v1/users/import/cognito

Bulk-import users from a Cognito export synchronously

Maps an Amazon Cognito user-pool export (a JSON array of user objects, each with a Username and a Name/Value Attributes list) into the platform's import model and imports up to 500 users into the caller's tenant, returning the per-row outcome. Cognito does not export password hashes, so migrated users are created password-less and sign in via password reset or federation. Partial success is normal. For larger exports use POST /api/v1/users/import/cognito/jobs. Pass ?dryRun=true to validate the whole export without writing any row — the response is the same shape, read as a prediction.

  • Operation ID: userImportImportCognitoUsers
  • Required scopes: tenant:users.import

Parameters:

NameInRequiredTypeDescription
dryRunquerynobooleanWhen true, validate the batch and return the predicted per-row outcome without writing any user. Same validation and same response shape as a real import; zero rows are created. Defaults to false (a real import).

Request body (required): application/jsonCognitoUser[]

Responses:

StatusDescriptionBody
200OKobject
401Unauthorized — bearer token missing, expired, signed by an untrusted issuer, or missing the tnt tenant claim.Problem (problem+json)
403Forbidden — token lacks a required tenant:* scope, or the tnt claim does not match the tenant addressed by the request path.Problem (problem+json)

POST /api/v1/users/import/cognito/jobs

Submit an asynchronous Cognito-export import job

Maps an Amazon Cognito user-pool export (a JSON array of user objects) into the platform's import model and submits it as an asynchronous job (up to 10 000 users). Each user's federation provider is resolved against the caller's configured federation members before the job is enqueued: a resolvable provider is normalised to its platform type and enqueued, an unresolvable one is rejected up front (unresolved_federation_provider) and never enqueued. Returns 202 with the enqueued job plus any up-front rejections ({job, rejected}); when every row is rejected the response is 200 with a null job. Poll, list and cancel the job through the shared /api/v1/users/import/jobs surface — the same job model, not a parallel one. Cognito exports carry no password hashes, so migrated users sign in via reset or federation.

  • Operation ID: userImportCreateCognitoJob
  • Required scopes: tenant:users.import

Request body (required): application/jsonCognitoUser[]

Responses:

StatusDescriptionBody
200OKobject
401Unauthorized — bearer token missing, expired, signed by an untrusted issuer, or missing the tnt tenant claim.Problem (problem+json)
403Forbidden — token lacks a required tenant:* scope, or the tnt claim does not match the tenant addressed by the request path.Problem (problem+json)

GET /api/v1/users/import/jobs

List import jobs

Cursor-paginated list of the caller's tenant's import jobs, newest first. limit defaults to 20, hard-capped at 100. The list view omits per-row error detail — poll GET /api/v1/users/import/jobs/{id} for that.

  • Operation ID: userImportList
  • Required scopes: tenant:users.import

Parameters:

NameInRequiredTypeDescription
limitquerynointeger
cursorquerynostring

Responses:

StatusDescriptionBody
200OKobject
401Unauthorized — bearer token missing, expired, signed by an untrusted issuer, or missing the tnt tenant claim.Problem (problem+json)
403Forbidden — token lacks a required tenant:* scope, or the tnt claim does not match the tenant addressed by the request path.Problem (problem+json)

POST /api/v1/users/import/jobs

Submit an asynchronous bulk-import job

Accepts up to 10 000 users and returns 202 with the job resource. The batch is encrypted at rest and drained in the background; poll GET /api/v1/users/import/jobs/{id} for live counters. Same wire shape and same partial-failure semantics as the synchronous endpoint.

  • Operation ID: userImportCreateJob
  • Required scopes: tenant:users.import

Request body (required): application/jsonImportUsersRequest

Responses:

StatusDescriptionBody
200OKobject
401Unauthorized — bearer token missing, expired, signed by an untrusted issuer, or missing the tnt tenant claim.Problem (problem+json)
403Forbidden — token lacks a required tenant:* scope, or the tnt claim does not match the tenant addressed by the request path.Problem (problem+json)

GET /api/v1/users/import/jobs/{id}

Get an import job

Returns the job's status, live counters and per-row errors. A job belonging to another tenant is indistinguishable from one that does not exist — both are 404.

  • Operation ID: userImportGetJob
  • Required scopes: tenant:users.import

Parameters:

NameInRequiredTypeDescription
idpathyesstring

Responses:

StatusDescriptionBody
200OKobject
401Unauthorized — bearer token missing, expired, signed by an untrusted issuer, or missing the tnt tenant claim.Problem (problem+json)
403Forbidden — token lacks a required tenant:* scope, or the tnt claim does not match the tenant addressed by the request path.Problem (problem+json)

POST /api/v1/users/import/jobs/{id}/cancel

Cancel an import job

Stops a pending or in_progress job: the poller checks between chunks and the encrypted payload is wiped identically to the completed/failed terminal paths. A job already in a terminal state (including one already cancelled) is 409 job_not_cancellable.

  • Operation ID: userImportCancelJob
  • Required scopes: tenant:users.import

Parameters:

NameInRequiredTypeDescription
idpathyesstring

Responses:

StatusDescriptionBody
200OKobject
401Unauthorized — bearer token missing, expired, signed by an untrusted issuer, or missing the tnt tenant claim.Problem (problem+json)
403Forbidden — token lacks a required tenant:* scope, or the tnt claim does not match the tenant addressed by the request path.Problem (problem+json)