Create a user (admin)
Create a new user directly via the admin API.
Create a user from the server, bypassing the normal sign-up / confirmation flow. The user is created in the confirmed state by default (when email_confirm: true or phone_confirm: true is passed), so you can immediately issue them a session via sign_in_with_password or by generating a magic link.
Service-role key required
This endpoint requires the project's service_role key. Never call it from a browser, mobile app, or any client you don't fully control.
Signature
supabase.auth.admin.create_user(attributes)attributes is a hash. Pass it as a literal ({ email: "..." }) or use Ruby's hash-literal shorthand (email: "...").
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
email | String | Optional | The user's email address. Required unless you supply phone. |
phone | String | Optional | The user's phone in E.164 format. Required unless you supply email. |
password | String | Optional | Plaintext password. If omitted the user is created without a password (passwordless sign-in flows only). |
email_confirm | Boolean | Optional | When true, marks the email as already confirmed so the user can sign in immediately. Defaults to false (user must confirm via email link first). |
phone_confirm | Boolean | Optional | When true, marks the phone as already confirmed so the user can sign in immediately. Defaults to false. |
user_metadata | Hash | Optional | Arbitrary user-supplied metadata. Mutable by the user via update_user. Exposed in JWT claims. |
app_metadata | Hash | Optional | Application-controlled metadata. Mutable ONLY by service_role. Use for roles, plan tier, or any field the user must not be able to forge. |
role | String | Optional | Postgres role to embed in the JWT for RLS. Defaults to "authenticated". |
ban_duration | String | Optional | Go duration string (e.g. "24h", "168h0m0s") to ban the user for. Pass "none" to unban. |
id | String | Optional | Override the generated UUID. Useful when migrating an external user store. |
Returns
A Struct with a single :user field carrying the full Types::User (id, email, phone, app_metadata, user_metadata, identities, factors, timestamps). On failure raises Supabase::Auth::Errors::AuthApiError — common causes are duplicate email/phone (422) or a malformed payload.
Example — confirmed user with metadata
response = supabase.auth.admin.create_user(
email: "ada@example.com",
password: "correct horse battery staple",
email_confirm: true,
user_metadata: { display_name: "Ada Lovelace" },
app_metadata: { plan: "pro", role: "owner" }
)
response.user.id # => "8d7f5c4b-..."
response.user.email # => "ada@example.com"
response.user.app_metadata # => { "plan" => "pro", "role" => "owner", "provider" => "email", ... }Example — passwordless user (magic-link only)
response = supabase.auth.admin.create_user(
email: "guest@example.com",
email_confirm: true
)
# Now generate a one-time magic link to hand to the user:
link = supabase.auth.admin.generate_link(
type: "magiclink",
email: "guest@example.com"
)Example — phone-first user
supabase.auth.admin.create_user(
phone: "+15555550123",
phone_confirm: true,
user_metadata: { source: "imported_from_legacy_system" }
)