Migrate users to Identity Pools
Migrate users from external CIAM platforms into SecureAuth Identity Pools while maintaining data integrity and security at scale.
💡 Why this matters
Consolidate user data from multiple platforms into SecureAuth for better security, compliance, and operational efficiency. Supports large-scale migrations (~1.5 million users in 30 minutes).
Prerequisites:
- Identity Pool configured
- System workspace access
- Client application with manage_configurationscope

Phase 1: Prepare migration data
Format your data structure
Follow the Import Tenant Configuration API schema requirements.
| Data type | Required fields | Purpose | 
|---|---|---|
| users | id,user_pool_id,tenant_id | Core user information | 
| user_credentials | id,user_id,payload | Login credentials | 
| user_identifiers | id,user_id,identifier | Email or phone identifiers | 
| user_verifiable_addresses | id,user_id,address | Contact information | 
Generate unique identifiers
Create version 4 UUIDs for all records to ensure API idempotency and avoid duplicates during retries.
Handle password migration
Choose your password migration strategy:
| Strategy | Configuration | Use case | 
|---|---|---|
| Migrate passwords | Leave expires_atunset or1900-01-01T00:00:00Z | Users keep existing passwords | 
| Force password reset | Set expires_atto past date | Enhanced security, users must reset | 
⚠️ Security note
Forced password reset provides better security but requires user communication plan.
Phase 2: Import users
Get system access token
curl --location --request POST 'https://example.com/tenant_id/system/oauth2/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'client_id=YOUR_CLIENT_ID' \
--data-urlencode 'client_secret=YOUR_CLIENT_SECRET'
Verify: Token response includes manage_configuration scope
Submit import batches
curl --location --request PUT 'https://example.com/api/identity/system/{tid}/configuration' \
-H 'Authorization: Bearer {ACCESS_TOKEN}' \
-d @user-batch.json
Performance guidelines:
- Batch size: Up to 100 users per request
- Parallel requests: Up to 8 simultaneous requests
- Expected throughput: ~1.5 million users in 30 minutes
Verify: 204 NO CONTENT response confirms successful import
Phase 3: Handle import conflicts
Configure conflict resolution using the mode parameter:
| Mode | Behavior | When to Use | 
|---|---|---|
| ignore (default) | Skip conflicting records | Standard migration | 
| fail | Stop on conflicts | Testing/validation | 
| update | Overwrite existing records | Data updates | 
Example with update mode:
curl --location --request PUT 'https://example.com/api/identity/system/{tid}/configuration?mode=update'
Export users (testing only)
⚠️ Warning
Export API not production-ready for large user bases. Use only for testing or beta purposes.
Export user data
curl --location --request GET 'https://example.com/api/identity/system/{tid}/configuration' \
--header 'Authorization: Bearer {ACCESS_TOKEN}'
Result: 200 OK response returns tenant configuration as JSON
Verification and Testing
Test these scenarios:
- Import small batch → Verify users appear in Identity Pool
- Test login with migrated user → Confirm authentication works
- Test password reset flow → Verify expired credentials behavior
Monitor these metrics:
- Import success rate: Should be >95%
- API response times: Should be <2 seconds
- Error patterns: Track and resolve common issues
Troubleshooting
Import failures:
- 400 Bad Request→ Check JSON format and required fields
- 401 Unauthorized→ Verify access token and scope
- 409 Conflict→ User already exists, check import mode
Password issues:
- Users can't login → Check expires_atconfiguration
- "Credential expired" error → Users need password reset via forgot password flow
Performance issues:
- Slow imports → Reduce batch size or parallel requests
- Timeouts → Check network connectivity and retry failed batches
Recovery steps:
- Use same UUIDs to retry failed imports (API is idempotent)
- Check error logs for specific failure reasons
- Test with smaller batches if bulk import fails
Sample Data Format
Minimal example for two users:
{
  "users": [
    {
      "id": "58e6184f-8e38-4193-b889-965b34326c7f",
      "user_pool_id": "caku6lrphdd3cfqro3mg",
      "tenant_id": "default",
      "status": "active",
      "payload": {
        "name": "John Doe",
        "given_name": "John",
        "family_name": "Doe"
      }
    }
  ],
  "user_credentials": [
    {
      "id": "e89e254c-f538-4ae2-9150-4d4580bcf886",
      "user_id": "58e6184f-8e38-4193-b889-965b34326c7f",
      "type": "password",
      "expires_at": "2019-08-24T14:15:22Z",
      "payload": {
        "hashed_password": {
          "config": {
            "method": "sha",
            "sha": {
              "function": "SHA-256",
              "salt": "lJgayFHwYelZGmrBnYqt"
            }
          },
          "value": "eUJBxl+dwVjPgwC2cm1K+hYNWFRly/RdCT/bgmIBowo="
        }
      }
    }
  ],
  "user_identifiers": [
    {
      "id": "b7108442-7f1e-40b9-a4d9-0c9ab3b0d18b",
      "user_id": "58e6184f-8e38-4193-b889-965b34326c7f",
      "identifier": "john.doe@example.com",
      "type": "email"
    }
  ]
}