Overview
The invite plugin supports two types of invitations:
Private invites : Sent to a specific email address with email notification
Public invites : Generic invitation tokens/links that anyone can use
Private invites
Private invites are sent to a specific email address. The plugin automatically determines if the user needs to create a new account or upgrade their existing role.
Basic example
const result = await authClient . invite . create ({
email: "[email protected] " ,
role: "member" ,
});
// Result: { status: true, message: "The invitation was sent" }
You must configure sendUserInvitation in your server setup to send private invites. See Email integration .
Server-side creation
const result = await auth . api . createInvite ({
body: {
email: "[email protected] " ,
role: "admin" ,
},
headers: request . headers , // Include session cookies
});
Public invites
Public invites create a shareable token or URL that anyone can use. Useful for referral programs, open sign-ups, or sharing via social media.
Create a public invite
const result = await authClient . invite . create ({
role: "member" ,
// No email = public invite
});
// Result: { status: true, message: "<token or url>" }
The message field contains either the token or complete URL, depending on your senderResponse configuration.
Get URL instead of token
const result = await authClient . invite . create ({
role: "member" ,
senderResponse: "url" ,
});
// Result: { status: true, message: "http://localhost:3000/invite/abc123?callbackURL=..." }
Configuration options
All options from createInviteBodySchema are available:
The role to assign to the invited user.
Email address for private invites. Omit for public invites.
tokenType
'token' | 'code' | 'custom'
Type of token to generate. Defaults to server configuration. tokenType : "code" // Generates 6-digit code like "A1B2C3"
Maximum number of times this invite can be used. Defaults to 1 for private invites, unlimited for public invites. maxUses : 10 // Allow 10 people to use this invite
Token expiration time in seconds. expiresIn : 7 * 24 * 60 * 60 // 7 days
Where to redirect new users to create their account. redirectToSignUp : "/auth/signup"
Where to redirect existing users to sign in. redirectToSignIn : "/auth/login"
Where to redirect users after accepting the invite (when already logged in). Use {token} placeholder. redirectToAfterUpgrade : "/dashboard?invite={token}"
Whether to share the inviter’s name with the invitee.
How to return the invite to the sender (public invites only). senderResponse : "url" // Return complete URL instead of token
Default redirect type for public invites. senderResponseRedirect : "signIn"
Custom invite URL template. Use {token} and {callbackUrl} placeholders. customInviteUrl : "https://myapp.com/join?token={token}&next={callbackUrl}"
Use cases
Invite new team member (private)
await authClient . invite . create ({
email: "[email protected] " ,
role: "member" ,
expiresIn: 7 * 24 * 60 * 60 , // 7 days
});
Upgrade existing user role (private)
Create referral link (public)
const result = await authClient . invite . create ({
role: "member" ,
senderResponse: "url" ,
maxUses: 100 ,
expiresIn: 30 * 24 * 60 * 60 , // 30 days
});
const shareUrl = result . message ;
// Share this URL on social media, email, etc.
Time-limited signup code (public)
const result = await authClient . invite . create ({
role: "member" ,
tokenType: "code" ,
maxUses: 1 ,
expiresIn: 15 * 60 , // 15 minutes
});
const code = result . message ; // e.g., "A1B2C3"
// Display this code to the user
Example UI component
React
Next.js Server Action
Next.js Client Component
import { useState } from "react" ;
import { authClient } from "./client" ;
function InviteForm () {
const [ email , setEmail ] = useState ( "" );
const [ role , setRole ] = useState ( "member" );
const [ loading , setLoading ] = useState ( false );
const [ error , setError ] = useState ( "" );
const handleSubmit = async ( e : React . FormEvent ) => {
e . preventDefault ();
setLoading ( true );
setError ( "" );
try {
await authClient . invite . create ({
email ,
role ,
});
alert ( "Invitation sent!" );
setEmail ( "" );
} catch ( err ) {
setError ( err . message || "Failed to send invitation" );
} finally {
setLoading ( false );
}
};
return (
< form onSubmit = { handleSubmit } >
< input
type = "email"
value = { email }
onChange = { ( e ) => setEmail ( e . target . value ) }
placeholder = "Email address"
required
/>
< select value = { role } onChange = { ( e ) => setRole ( e . target . value ) } >
< option value = "member" > Member </ option >
< option value = "admin" > Admin </ option >
</ select >
< button type = "submit" disabled = { loading } >
{ loading ? "Sending..." : "Send Invite" }
</ button >
{ error && < p className = "error" > { error } </ p > }
</ form >
);
}
Permission checks
The plugin respects your canCreateInvite configuration:
// Server configuration
invite ({
canCreateInvite : async ({ invitedUser , inviterUser , ctx }) => {
// Only admins can invite admins
if ( invitedUser . role === 'admin' && inviterUser . role !== 'admin' ) {
return false ;
}
return true ;
},
})
If permission is denied, the create endpoint throws an error:
try {
await authClient . invite . create ({ email: "[email protected] " , role: "admin" });
} catch ( error ) {
if ( error . errorCode === "INSUFFICIENT_PERMISSIONS" ) {
alert ( "You don't have permission to create this invite" );
}
}
Private invites require sendUserInvitation to be configured on the server. Attempts to create private invites without email configuration will fail with an INTERNAL_SERVER_ERROR.
Next steps
Activating invites Handle invitation activation flow
Email integration Configure email sending for invitations