Migrate from Kinde
1. Export from Kinde
Section titled “1. Export from Kinde”As the account Owner, go to Settings → Export data and download the JSON export. Kinde includes password hashes together with the hashing algorithm and salt configuration — the most complete self-service export of any hosted provider.
2. Map the fields
Section titled “2. Map the fields”| Kinde JSON field | Import row field |
|---|---|
email | email |
first_name + last_name | displayName |
id (kp_…) | sourceUserId |
hashed_password | passwordHash |
hashing algorithm (e.g. bcrypt) | passwordHashAlgorithm |
| salt / salt position details | passwordHashParams (JSON string) |
3. Import
Section titled “3. Import”const rows = kindeUsers.map(u => ({ email: u.email, displayName: [u.first_name, u.last_name].filter(Boolean).join(" ") || null, sourceUserId: u.id, passwordHashAlgorithm: u.hashing_method || null, // e.g. "bcrypt" passwordHash: u.hashed_password || null, passwordHashParams: u.salt ? JSON.stringify({ salt: u.salt, saltPosition: u.salt_position }) : null,}));// POST in batches of 500 — same loop as the Clerk guide, with source: "kinde".See the Clerk guide for the batching loop and the foreign-key re-mapping SQL —
only source: "kinde" and the field mapping differ.
Gotchas
Section titled “Gotchas”- Social login carries over by email — same Google/Apple/etc. button, same account, no OAuth app changes.
- Hashes are stored dormant. Axowl login is passwordless (magic link / social / passkey); the hash+salt material is kept for provenance. See how the import works.