API reference
Every client method, server-only endpoints, and rate limits.
Client methods
Redemption
The two calls your invite page uses:
authClient.invite.get({ token });
authClient.invite.redeem({ token, ... });Management
authClient.invite.create({ kind?, type?, email?, name?, role?, maxUses?, expiresIn?,
organizationId?, organizationRole?, teamId?, presetSeatLimit? });
authClient.invite.list({ status?, type?, kind?, email?, organizationId?, page?, limit? });
authClient.invite.resend({ inviteId, expiresIn? });
authClient.invite.revoke({ inviteId });
authClient.invite.delete({ inviteId });resend rotates the token and expiry on any pending invite, invalidating the previous link and redelivering it; see Resending an invitation.
Who may call these is covered in Who can do what.
Mode-specific primitives
Kept for compatibility; invite.redeem routes to the right one for you:
authClient.invite.accept({ token, password, name, email? });
authClient.invite.activate({ token });accept requires name (it is the flow that populates the profile) and carries the SIGN_UP-step additional fields; activate acts on an existing account, takes no name, and carries the CONFIRM-step additional fields.
Organization administration
authClient.invite.org.usage({ organizationId });
authClient.invite.org.setSeatLimit({ organizationId, seatLimit });
authClient.invite.org.disable({ organizationId, banMembers? });
authClient.invite.org.enable({ organizationId });
authClient.invite.org.delete({ organizationId, banMembers? });Server-only
These endpoints are never mounted as HTTP routes; they exist only on auth.api.
Create invites headlessly, with no session, for cron jobs and system integrations. Every invariant (email locks, seat limits, role validation) still runs; only the permission gates are skipped. Attribution falls back to your appName, then "System", and createdByUserId is stored as null:
await auth.api.createSystemInvite({
body: {
type: "private",
email: "ada@example.com",
inviter: { name: "Billing", email: "billing@acme.com" } // optional
}
});Trusted server code only
createSystemInvite skips authentication and the admin gate; whoever can call it can mint invites
for any role. Keep it in code paths you fully control, never behind a client-reachable route, and
never forward unvalidated client input into fields like role, organizationId, maxUses, or
inviter. It also thins the audit trail: system invites store a null createdByUserId and a
self-declared inviter, so attribution is only as trustworthy as the caller, with the null
createdByUserId keeping them distinguishable from human invites.
Preferred inviter name
inviter is the preferred display name for delivery: it flows into inviterName and
inviterEmail verbatim, and org-join invites carry organizationName as usual, so "Alex invited
you to join Acme" emails render the same as member-sent ones. Without it, the sender shows as your
app name or "System".
And for your own scheduler:
const { deleted } = await auth.api.cleanupExpiredInvites();Rate limits
Built-in limits: /invite/accept, /invite/activate, and /invite/redeem allow 5 requests per 60 seconds; /invite/get allows 10.
Better Auth stores rate-limit counters in memory by default. If you run more than one instance,
configure Better Auth's rateLimit.storage (for example "secondary-storage" with Redis) so the
limits are shared instead of per-pod. See Operations at scale.
Revoke, delete, and the email lock
In short: invite.revoke cancels an invite but keeps its protections active, invite.delete also removes the pre-created user and frees the address, and accepted invites are permanent audit records that cannot be deleted. The full semantics of the email lock, and why revoking is deliberately softer than deleting, are on the Security page.
Last updated on