stack/docs/templates/sdk/objects/stack-app.mdx
Madison 4b06bca59e
init emails docs (#848)
<!--

Make sure you've read the CONTRIBUTING.md guidelines:
https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md

-->

Updates existing docs to include emails endpoints, and adds new docs for
emails in general docs, as well as SDK docs.
<!-- ELLIPSIS_HIDDEN -->


----

> [!IMPORTANT]
> Introduces server-side email sending API and updates documentation to
include comprehensive guides and SDK references for email functionality.
> 
>   - **Behavior**:
> - Introduces `sendEmail` API in `route.tsx` for sending emails with
HTML or templates.
>     - Handles errors like missing user IDs and schema errors.
>   - **Documentation**:
> - Adds `concepts/emails.mdx` detailing email types, sending methods,
and configuration.
> - Updates `docs-platform.yml` and `meta.json` to include email
documentation.
> - Adds `sdk/types/email.mdx` for `SendEmailOptions` type reference.
>   - **UI/Style**:
>     - Adds badge style for `sendEmailOptions` in `method-layout.tsx`.
> 
> <sup>This description was created by </sup>[<img alt="Ellipsis"
src="https://img.shields.io/badge/Ellipsis-blue?color=175173">](https://www.ellipsis.dev?ref=stack-auth%2Fstack-auth&utm_source=github&utm_medium=referral)<sup>
for 2edeb57734. You can
[customize](https://app.ellipsis.dev/stack-auth/settings/summaries) this
summary. It will automatically update as commits are pushed.</sup>

----


<!-- ELLIPSIS_HIDDEN -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Introduced server-side email sending API with templates, theming,
variables, and notification categories.

* **Documentation**
* Added comprehensive Emails concept guide and SDK references
(sendEmail, SendEmailOptions).
* Extended SDK index and platform navigation to include Email docs for
Next/React/JS.
  * Added an “Emails” functional tag to API docs and route metadata.

* **Style**
  * Added a distinct badge style for SendEmailOptions in the docs UI.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Konsti Wohlwend <n2d4xc@gmail.com>
2025-08-21 12:05:48 -05:00

988 lines
28 KiB
Plaintext

---
title: StackApp
full: true
---
This is a detailed reference for the `StackApp` object. If you're looking for a more high-level overview, please read the [respective page in the Concepts section](../../concepts/stack-app.mdx).
## Overview
- [StackClientApp](#stackclientapp) - Client-level permissions for frontend code
- [StackServerApp](#stackserverapp) - Server-level permissions with full access
---
# StackClientApp
A [`StackApp`](../../concepts/stack-app.mdx) with client-level permissions. It contains most of the useful methods and hooks for your client-side code.
{/* IF_PLATFORM: react-like */}
Most commonly you get an instance of `StackClientApp` by calling [`useStackApp()`](../hooks/use-stack-app.mdx) in a Client Component.
{/* END_PLATFORM */}
## Table of Contents
<ClickableTableOfContents code={`type StackClientApp = {
new(options): StackClientApp; //$stack-link-to:#stackclientappnewoptions
getUser([options]): Promise<User>; //$stack-link-to:#stackclientappgetuseroptions
// NEXT_LINE_PLATFORM react-like
⤷ useUser([options]): User; //$stack-link-to:#stackclientappuseuseroptions
getProject(): Promise<Project>; //$stack-link-to:#stackclientappgetproject
// NEXT_LINE_PLATFORM react-like
⤷ useProject(): Project; //$stack-link-to:#stackclientappuseproject
signInWithOAuth(provider): void; //$stack-link-to:#stackclientappsigninwithoauthprovider
signInWithCredential([options]): Promise<...>; //$stack-link-to:#stackclientappsigninwithcredentialoptions
signUpWithCredential([options]): Promise<...>; //$stack-link-to:#stackclientappsignupwithcredentialoptions
sendForgotPasswordEmail(email): Promise<...>; //$stack-link-to:#stackclientappsendforgotpasswordemailemail
sendMagicLinkEmail(email): Promise<...>; //$stack-link-to:#stackclientappsendmagiclinkemailemail
};`} />
## Constructor
<MethodSection>
<MethodLayout>
<MethodContent>
Creates a new `StackClientApp` instance.
Because each app creates a new connection to Stack Auth's backend, you should re-use existing instances wherever possible.
{/* IF_PLATFORM: react-like */}
<Info type="info">
This object is not usually constructed directly. More commonly, you would construct a [`StackServerApp`](#stackserverapp) instead, pass it into a [`<StackProvider />`](../../components/stack-provider.mdx), and then use `useStackApp()` hook to obtain a `StackClientApp`.
The [setup wizard](../../getting-started/setup.mdx) does these steps for you, so you don't need to worry about it unless you are manually setting up Stack Auth.
If you're building a client-only app and don't have a [`SECRET_SERVER_KEY`](../../rest-api/overview#should-i-use-client-or-server-access-type), you can construct a `StackClientApp` directly.
</Info>
{/* END_PLATFORM */}
**Parameters:**
<div className="indented">
<ParamField path="options" type="object">
An object containing multiple properties.
<Accordion title="Show Parameters">
<Markdown src="../../snippets/stack-app-constructor-options-before-ssk.mdx" />
<Markdown src="../../snippets/stack-app-constructor-options-after-ssk.mdx" />
</Accordion>
</ParamField>
</div>
</MethodContent>
<MethodAside>
<AsideSection title="Signature">
```typescript
declare new(options: {
tokenStore: "nextjs-cookie" | "cookie" | { accessToken: string, refreshToken: string } | Request;
baseUrl?: string;
projectId?: string;
publishableClientKey?: string;
urls: {
...
};
noAutomaticPrefetch?: boolean;
}): StackClientApp;
```
</AsideSection>
<AsideSection title="Examples">
<Tabs defaultValue="creating-new-app">
<TabsList>
<TabsTrigger value="creating-new-app">Creating new app</TabsTrigger>
<TabsTrigger value="using-useStackApp">Using useStackApp</TabsTrigger>
</TabsList>
<TabsContent value="creating-new-app">
```typescript
const stackClientApp = new StackClientApp({
tokenStore: "nextjs-cookie",
baseUrl: "https://api.stack-auth.com",
projectId: "123",
publishableClientKey: "123",
urls: {
home: "/",
},
});
```
</TabsContent>
<TabsContent value="using-useStackApp">
{/* IF_PLATFORM: react-like */}
```typescript
"use client";
function MyReactComponent() {
const stackClientApp = useStackApp();
}
```
{/* END_PLATFORM */}
</TabsContent>
</Tabs>
</AsideSection>
</MethodAside>
</MethodLayout>
</MethodSection>
<CollapsibleMethodSection method="getUser" signature="[options]" appType="StackClientApp" defaultOpen={false}>
<MethodLayout>
<MethodContent>
Gets the current user.
**Parameters:**
- `options?` (object) - Optional configuration
- `or?` - What to do if user not found: `"return-null"` | `"redirect"` | `"throw"`
**Returns:** `Promise<CurrentUser | null>` - The current user, or `null` if not signed in
</MethodContent>
<MethodAside>
<AsideSection title="Signature">
```typescript
declare function getUser(
options?: {
or?: "return-null" | "redirect" | "throw"
}
): Promise<CurrentUser | null>;
```
</AsideSection>
<AsideSection title="Examples">
```typescript
// Basic usage
const userOrNull = await stackClientApp.getUser();
console.log(userOrNull); // null if not signed in
// With redirect on no user
const user = await stackClientApp.getUser({ or: "redirect" });
console.log(user); // always defined; redirects to sign-in page if not signed in
```
</AsideSection>
</MethodAside>
</MethodLayout>
</CollapsibleMethodSection>
{/* IF_PLATFORM: react-like */}
<CollapsibleMethodSection method="useUser" signature="[options]" appType="StackClientApp" defaultOpen={false}>
<MethodLayout>
<MethodContent>
React hook version of `getUser()`. Functionally equivalent to [`getUser()`](#stackclientappgetuseroptions), but as a React hook.
Equivalent to the [`useUser()`](../hooks/use-user.mdx) standalone hook (which is an alias for `useStackApp().useUser()`).
**Parameters:**
- `options?` (object) - Same as `getUser()`
**Returns:** `CurrentUser | null`
</MethodContent>
<MethodAside>
<AsideSection title="Signature">
```typescript
declare function useUser(
options?: {
or?: "return-null" | "redirect" | "throw"
}
): CurrentUser | null;
```
</AsideSection>
<AsideSection title="Examples">
<Tabs defaultValue="basic-usage">
<TabsList>
<TabsTrigger value="basic-usage">Basic Usage</TabsTrigger>
<TabsTrigger value="with-redirect">With Redirect</TabsTrigger>
<TabsTrigger value="page-protection">Page Protection</TabsTrigger>
</TabsList>
<TabsContent value="basic-usage">
```jsx
"use client";
function MyReactComponent() {
const user = useUser();
return user ? <div>Hello, {user.name}</div>
: <div>Not signed in</div>;
}
```
</TabsContent>
<TabsContent value="with-redirect">
```tsx
"use client";
function MyReactComponent() {
const user = useUser();
console.log(user); // null if not signed in
const user = useUser({ or: "redirect" }); // redirects to sign-in page if necessary
console.log(user); // always defined
const user = useUser({ or: "throw" }); // throws an error if not signed in
console.log(user); // always defined
}
```
</TabsContent>
<TabsContent value="page-protection">
```tsx
"use client";
function MyProtectedComponent() {
// Note: This component is protected on the client-side.
// It does not protect against malicious users, since
// they can just comment out the `useUser` call in their
// browser's developer console.
//
// For server-side protection, see the Stack Auth documentation.
useUser({ or: "redirect" });
return <div>You can only see this if you are authenticated</div>;
}
```
</TabsContent>
</Tabs>
</AsideSection>
</MethodAside>
</MethodLayout>
</CollapsibleMethodSection>
{/* END_PLATFORM */}
<CollapsibleMethodSection method="getProject" appType="StackClientApp" defaultOpen={false}>
<MethodLayout>
<MethodContent>
Gets the current project.
**Parameters:**
- No parameters
**Returns:** `Promise<Project>`
</MethodContent>
<MethodAside>
<AsideSection title="Signature">
```typescript
declare function getProject(): Promise<Project>;
```
</AsideSection>
<AsideSection title="Examples">
```typescript
const project = await stackClientApp.getProject();
```
</AsideSection>
</MethodAside>
</MethodLayout>
</CollapsibleMethodSection>
{/* IF_PLATFORM: react-like */}
<CollapsibleMethodSection method="useProject" appType="StackClientApp" defaultOpen={false}>
<MethodLayout>
<MethodContent>
React hook version of `getProject()`.
**Parameters:**
- No parameters
**Returns:** `Project`
</MethodContent>
<MethodAside>
<AsideSection title="Signature">
```typescript
declare function useProject(): Project;
```
</AsideSection>
<AsideSection title="Examples">
getting the current project in a react component
```typescript
function MyReactComponent() {
const project = useProject();
}
```
</AsideSection>
</MethodAside>
</MethodLayout>
</CollapsibleMethodSection>
{/* END_PLATFORM */}
<CollapsibleMethodSection method="signInWithOAuth" signature="provider" appType="StackClientApp" defaultOpen={false}>
<MethodLayout>
<MethodContent>
Initiates the OAuth sign-in process with the specified provider.
**Parameters:**
- `provider` (string) - The OAuth provider type
**Returns:** `Promise<void>`
</MethodContent>
<MethodAside>
<AsideSection title="Signature">
```typescript
declare function signInWithOAuth(provider: string): Promise<void>;
```
</AsideSection>
<AsideSection title="Examples">
```typescript
await stackClientApp.signInWithOAuth("google");
```
</AsideSection>
</MethodAside>
</MethodLayout>
</CollapsibleMethodSection>
<CollapsibleMethodSection method="signInWithCredential" signature="[options]" appType="StackClientApp" defaultOpen={false}>
<MethodLayout>
<MethodContent>
Sign in using email and password credentials.
**Parameters:**
- `options` (object)
- `email` (string) - User's email
- `password` (string) - User's password
- `noRedirect?` (boolean) - Whether to skip redirect after sign-in
**Returns:** `Promise<Result<undefined, KnownErrors["EmailPasswordMismatch"]>>`
</MethodContent>
<MethodAside>
<AsideSection title="Signature">
```typescript
declare function signInWithCredential(options: {
email: string;
password: string;
noRedirect?: boolean;
}): Promise<Result<undefined, KnownErrors["EmailPasswordMismatch"]>>;
```
</AsideSection>
<AsideSection title="Examples">
```typescript
const result = await stackClientApp.signInWithCredential({
email: "test@example.com",
password: "password",
});
if (result.status === "error") {
console.error("Sign in failed", result.error.message);
}
```
</AsideSection>
</MethodAside>
</MethodLayout>
</CollapsibleMethodSection>
<CollapsibleMethodSection method="signUpWithCredential" signature="[options]" appType="StackClientApp" defaultOpen={false}>
<MethodLayout>
<MethodContent>
Sign up using email and password credentials.
**Parameters:**
- `options` (object)
- `email` (string) - User's email
- `password` (string) - User's password
- `noRedirect?` (boolean) - Whether to skip redirect after sign-up
**Returns:** `Promise<Result<undefined, KnownErrors["UserWithEmailAlreadyExists"] | KnownErrors["PasswordRequirementsNotMet"]>>`
</MethodContent>
<MethodAside>
<AsideSection title="Signature">
```typescript
declare function signUpWithCredential(options: {
email: string;
password: string;
noRedirect?: boolean;
}): Promise<Result<undefined, KnownErrors["UserWithEmailAlreadyExists"] | KnownErrors["PasswordRequirementsNotMet"]>>;
```
</AsideSection>
<AsideSection title="Examples">
```typescript
const result = await stackClientApp.signUpWithCredential({
email: "test@example.com",
password: "password",
});
if (result.status === "error") {
console.error("Sign up failed", result.error.message);
}
```
</AsideSection>
</MethodAside>
</MethodLayout>
</CollapsibleMethodSection>
<CollapsibleMethodSection method="sendForgotPasswordEmail" signature="email" appType="StackClientApp" defaultOpen={false}>
<MethodLayout>
<MethodContent>
Send a forgot password email to an email address.
**Parameters:**
- `email` (string) - The email to send the forgot password email to
**Returns:** `Promise<Result<undefined, KnownErrors["UserNotFound"]>>`
</MethodContent>
<MethodAside>
<AsideSection title="Signature">
```typescript
declare function sendForgotPasswordEmail(email: string): Promise<Result<undefined, KnownErrors["UserNotFound"]>>;
```
</AsideSection>
<AsideSection title="Examples">
```typescript
const result = await stackClientApp.sendForgotPasswordEmail("test@example.com");
if (result.status === "success") {
console.log("Forgot password email sent");
} else {
console.error("Failed to send forgot password email", result.error.message);
}
```
</AsideSection>
</MethodAside>
</MethodLayout>
</CollapsibleMethodSection>
<CollapsibleMethodSection method="sendMagicLinkEmail" signature="email" appType="StackClientApp" defaultOpen={false}>
<MethodLayout>
<MethodContent>
Send a magic link/OTP sign-in email to an email address.
**Parameters:**
- `email` (string) - The email to send the magic link to
**Returns:** `Promise<Result<{ nonce: string }, KnownErrors["RedirectUrlNotWhitelisted"]>>`
</MethodContent>
<MethodAside>
<AsideSection title="Signature">
```typescript
declare function sendMagicLinkEmail(email: string): Promise<Result<{ nonce: string }, KnownErrors["RedirectUrlNotWhitelisted"]>>;
```
</AsideSection>
<AsideSection title="Examples">
```typescript
const result = await stackClientApp.sendMagicLinkEmail("test@example.com");
```
</AsideSection>
</MethodAside>
</MethodLayout>
</CollapsibleMethodSection>
---
# StackServerApp
Like `StackClientApp`, but with [server permissions](../../concepts/stack-app.mdx#client-vs-server). Has full read and write access to all users.
<Info type="warning">
Since this functionality should only be available in environments you trust (ie. your own server), it requires a [`SECRET_SERVER_KEY`](../../rest-api/overview.mdx).
In some cases, you may want to use a [`StackServerApp`](#stackserverapp) on the client; an example for this is an internal dashboard that only your own employees have access to.
We generally recommend against doing this unless you are aware of and protected against the (potentially severe) security implications of
exposing [`SECRET_SERVER_KEY`](../../rest-api/overview.mdx) on the client.
</Info>
## Table of Contents
<ClickableTableOfContents code={`type StackServerApp =
// Inherits all functionality from StackClientApp
& StackClientApp //$stack-link-to:#stackclientapp
& {
new(options): StackServerApp; //$stack-link-to:#stackserverappnewoptions
getUser([id][, options]): Promise<ServerUser | null>; //$stack-link-to:#stackserverappgetuseridoptions
// NEXT_LINE_PLATFORM react-like
⤷ useUser([id][, options]): ServerUser; //$stack-link-to:#stackserverappuseuseridoptions
listUsers([options]): Promise<ServerUser[]>; //$stack-link-to:#stackserverapplistusersoptions
// NEXT_LINE_PLATFORM react-like
⤷ useUsers([options]): ServerUser[]; //$stack-link-to:#stackserverappuseusersoptions
createUser([options]): Promise<ServerUser>; //$stack-link-to:#stackserverappcreateuseroptions
sendEmail(options): Promise<Result<void, KnownErrors>>; //$stack-link-to:#stackserverappsendemailoptions
getTeam(id): Promise<ServerTeam | null>; //$stack-link-to:#stackserverappgetteamid
// NEXT_LINE_PLATFORM react-like
⤷ useTeam(id): ServerTeam; //$stack-link-to:#stackserverappuseteamid
listTeams(): Promise<ServerTeam[]>; //$stack-link-to:#stackserverapplistteams
// NEXT_LINE_PLATFORM react-like
⤷ useTeams(): ServerTeam[]; //$stack-link-to:#stackserverappuseteams
createTeam([options]): Promise<ServerTeam>; //$stack-link-to:#stackserverappcreateteamoptions
}`} />
## Constructor
<MethodSection>
<MethodLayout>
<MethodContent>
Creates a new `StackClientApp` instance.
**Parameters:**
<ParamField path="options" type="object">
An object containing multiple properties.
<Accordion title="Show Parameters">
<Markdown src="../../snippets/stack-app-constructor-options-before-ssk.mdx" />
<ParamField path="secretServerKey" type="string">
The secret server key of the app, as found on Stack Auth's dashboard. Defaults to the value of the `SECRET_SERVER_KEY` environment variable.
</ParamField>
<Markdown src="../../snippets/stack-app-constructor-options-after-ssk.mdx" />
</Accordion>
</ParamField>
</MethodContent>
<MethodAside>
<AsideSection title="Signature">
```typescript
declare new(options: {
tokenStore: "nextjs-cookie" | "cookie" | { accessToken: string, refreshToken: string } | Request;
baseUrl?: string;
projectId?: string;
publishableClientKey?: string;
urls: {
...
};
noAutomaticPrefetch?: boolean;
}): StackServerApp;
```
</AsideSection>
<AsideSection title="Examples">
<Tabs defaultValue="StackServerApp-custom-sign-in-page">
<TabsList>
<TabsTrigger value="StackServerApp-custom-sign-in-page">Create a StackServerApp with a custom sign-in page</TabsTrigger>
</TabsList>
<TabsContent value="StackServerApp-custom-sign-in-page">
```typescript
const stackServerApp = new StackServerApp({
tokenStore: "nextjs-cookie",
urls: {
signIn: '/my-custom-sign-in-page',
},
});
```
</TabsContent>
</Tabs>
</AsideSection>
</MethodAside>
</MethodLayout>
</MethodSection>
<CollapsibleMethodSection method="getUser" signature="[id], [options]" appType="StackServerApp" defaultOpen={false}>
<MethodLayout>
<MethodContent>
Enhanced version of `StackClientApp.getUser()` with server permissions.
**Overloads:**
1. `getUser(id: string): Promise<ServerUser | null>` - Get user by ID
2. `getUser(options?: { or?: "return-null" | "redirect" | "throw" }): Promise<CurrentServerUser | null>` - Get current user
</MethodContent>
<MethodAside>
<AsideSection title="Signature">
```typescript
// This function has two overloads:
declare function getUser(id: string): Promise<ServerUser | null>;
declare function getUser(
options?: {
or?: "return-null" | "redirect" | "throw"
}
): Promise<CurrentServerUser | null>;
```
</AsideSection>
<AsideSection title="Examples">
<Tabs defaultValue="get-current-user">
<TabsList>
<TabsTrigger value="get-current-user">Get Current User</TabsTrigger>
<TabsTrigger value="get-user-by-id">Get User by ID</TabsTrigger>
</TabsList>
<TabsContent value="get-current-user">
```typescript
const user = await stackServerApp.getUser();
console.log(user); // CurrentServerUser
```
</TabsContent>
<TabsContent value="get-user-by-id">
```typescript
const user = await stackServerApp.getUser("12345678-1234-1234-1234-123456789abc");
console.log(user); // ServerUser
```
</TabsContent>
</Tabs>
</AsideSection>
</MethodAside>
</MethodLayout>
</CollapsibleMethodSection>
{/* IF_PLATFORM react-like */}
<CollapsibleMethodSection method="useUser" signature="[id], [options]" appType="StackServerApp" defaultOpen={false}>
Functionally equivalent to [`getUser()`](#stackserverappgetuserid-options), but as a React hook.
<Info type="info">
This should be used on the server-side only.
</Info>
</CollapsibleMethodSection>
{/* END_PLATFORM */}
<CollapsibleMethodSection method="listUsers" signature="[options]" appType="StackServerApp" defaultOpen={false}>
<MethodLayout>
<MethodContent>
Lists all users on the project.
**Parameters:**
<div className="indented">
<ParamField path="options" type="object">
An object containing multiple properties.
<Accordion title="Show options properties">
<ParamField path="cursor" type="string">
The cursor to start the result set from.
</ParamField>
<ParamField path="limit" type="number">
The maximum number of items to return. If not provided, it will return all users.
</ParamField>
<ParamField path="orderBy" type="'signedUpAt'">
The field to sort the results by. Currently, only `signedUpAt` is supported.
</ParamField>
<ParamField path="desc" type="boolean" default="false">
Whether to sort the results in descending order.
</ParamField>
<ParamField path="query" type="string">
A query to filter the results by. This is a free-text search on the user's display name and emails.
</ParamField>
</Accordion>
</ParamField>
</div>
**Returns:** `Promise<ServerUser[] & { nextCursor: string | null }>`
</MethodContent>
<MethodAside>
<AsideSection title="Signature">
```typescript
declare function listUsers(options?: {
cursor?: string;
limit?: number;
orderBy?: "signedUpAt";
desc?: boolean;
query?: string;
}): Promise<ServerUser[] & { nextCursor: string | null }>;
```
</AsideSection>
<AsideSection title="Examples">
```typescript
const users = await stackServerApp.listUsers({ limit: 20 });
console.log(users);
if (users.nextCursor) {
const nextPageUsers = await stackServerApp.listUsers({
cursor: users.nextCursor,
limit: 20
});
console.log(nextPageUsers);
}
```
</AsideSection>
</MethodAside>
</MethodLayout>
</CollapsibleMethodSection>
{/* IF_PLATFORM react-like */}
<CollapsibleMethodSection method="useUsers" signature="[options]" appType="StackServerApp" defaultOpen={false}>
Functionally equivalent to [`listUsers()`](#stackserverapplistusersoptions), but as a React hook.
<Info type="info"> This should be used on the server-side only.</Info>
</CollapsibleMethodSection>
{/* END_PLATFORM */}
<CollapsibleMethodSection method="createUser" signature="[options]" appType="StackServerApp" defaultOpen={false}>
<MethodLayout>
<MethodContent>
Creates a new user from the server.
**Parameters:**
- `options?` (object)
- `primaryEmail?` (string) - User's primary email
- `primaryEmailVerified?` (boolean) - Whether email is verified
- `primaryEmailAuthEnabled?` (boolean) - Whether email auth is enabled
- `password?` (string) - User's password
- `otpAuthEnabled?` (boolean) - Enable OTP/magic link auth
- `displayName?` (string) - User's display name
**Returns:** `Promise<ServerUser>`
</MethodContent>
<MethodAside>
<AsideSection title="Signature">
```typescript
declare function createUser(options?: {
primaryEmail?: string;
primaryEmailVerified?: boolean;
primaryEmailAuthEnabled?: boolean;
password?: string;
otpAuthEnabled?: boolean;
displayName?: string;
}): Promise<ServerUser>;
```
</AsideSection>
<AsideSection title="Examples">
<Tabs defaultValue="password-auth">
<TabsList>
<TabsTrigger value="password-auth">Password Auth</TabsTrigger>
<TabsTrigger value="magic-link-auth">Magic Link Auth</TabsTrigger>
</TabsList>
<TabsContent value="password-auth">
```typescript
const user = await stackServerApp.createUser({
primaryEmail: "test@example.com",
primaryEmailAuthEnabled: true,
password: "password123",
});
```
</TabsContent>
<TabsContent value="magic-link-auth">
```typescript
const user = await stackServerApp.createUser({
primaryEmail: "test@example.com",
primaryEmailVerified: true,
primaryEmailAuthEnabled: true,
otpAuthEnabled: true,
});
```
</TabsContent>
</Tabs>
</AsideSection>
</MethodAside>
</MethodLayout>
</CollapsibleMethodSection>
<CollapsibleMethodSection method="sendEmail" signature="[options]" appType="StackServerApp" defaultOpen={false}>
<MethodLayout>
<MethodContent>
Send custom emails to users. You can send either custom HTML emails or use predefined templates with variables.
**Parameters:**
- `options` ([SendEmailOptions](../types/email#sendemailoptions)) - Email configuration and content
**Returns:** `Promise<Result<void, KnownErrors>>`
The method returns a `Result` object that can contain specific error types:
- `RequiresCustomEmailServer` - No custom email server configured
- `SchemaError` - Invalid email data provided
- `UserIdDoesNotExist` - One or more user IDs don't exist
</MethodContent>
<MethodAside>
<AsideSection title="Signature">
```typescript
declare function sendEmail(options: SendEmailOptions): Promise<Result<void, KnownErrors>>;
```
</AsideSection>
<AsideSection title="Examples">
<Tabs defaultValue="html-email">
<TabsList>
<TabsTrigger value="html-email">Send HTML Email</TabsTrigger>
<TabsTrigger value="template-email">Send Template Email</TabsTrigger>
</TabsList>
<TabsContent value="html-email">
```typescript
const result = await stackServerApp.sendEmail({
userIds: ['user-1', 'user-2'],
subject: 'Welcome to our platform!',
html: '<h1>Welcome!</h1><p>Thanks for joining us.</p>',
});
if (result.status === 'error') {
console.error('Failed to send email:', result.error);
}
```
</TabsContent>
<TabsContent value="template-email">
```typescript
const result = await stackServerApp.sendEmail({
userIds: ['user-1'],
templateId: 'welcome-template',
variables: {
userName: 'John Doe',
activationUrl: 'https://app.com/activate/token123',
},
});
if (result.status === 'error') {
console.error('Failed to send email:', result.error);
}
```
</TabsContent>
</Tabs>
</AsideSection>
</MethodAside>
</MethodLayout>
</CollapsibleMethodSection>
## Team Management
<CollapsibleMethodSection method="getTeam" signature="[id]" appType="StackServerApp" defaultOpen={false}>
<MethodLayout>
<MethodContent>
Get a team by its ID.
**Parameters:**
- `id` (string) - Team ID
**Returns:** `Promise<ServerTeam | null>`
</MethodContent>
<MethodAside>
<AsideSection title="Signature">
```typescript
declare function getTeam(id: string): Promise<ServerTeam | null>;
```
</AsideSection>
<AsideSection title="Examples">
```typescript
const team = await stackServerApp.getTeam("team_id_123");
```
</AsideSection>
</MethodAside>
</MethodLayout>
</CollapsibleMethodSection>
{/* IF_PLATFORM react-like */}
<CollapsibleMethodSection method="useTeam" signature="[id]" appType="StackServerApp" defaultOpen={false}>
Functionally equivalent to [`getTeam(id)`](#stackserverappgetteamid), but as a React hook.
<Info type="info"> This should be used on the server-side only.</Info>
</CollapsibleMethodSection>
{/* END_PLATFORM */}
<CollapsibleMethodSection method="listTeams" appType="StackServerApp" defaultOpen={false}>
<MethodLayout>
<MethodContent>
Lists all teams on the current project.
**Returns:** `Promise<ServerTeam[]>`
</MethodContent>
<MethodAside>
<AsideSection title="Signature">
```typescript
declare function listTeams(): Promise<ServerTeam[]>;
```
</AsideSection>
<AsideSection title="Examples">
```typescript
const teams = await stackServerApp.listTeams();
console.log(teams);
```
</AsideSection>
</MethodAside>
</MethodLayout>
</CollapsibleMethodSection>
{/* IF_PLATFORM react-like */}
<CollapsibleMethodSection method="useTeams" appType="StackServerApp" defaultOpen={false}>
Functionally equivalent to [`listTeams()`](#stackserverapplistteams), but as a React hook.
<Info type="info"> This should be used on the server-side only.</Info>
</CollapsibleMethodSection>
{/* END_PLATFORM */}
<CollapsibleMethodSection method="createTeam" signature="[options]" appType="StackServerApp" defaultOpen={false}>
<MethodLayout>
<MethodContent>
Creates a team without adding a user to it.
**Parameters:**
- `data` (object)
- `displayName` (string) - Team display name
- `profileImageUrl?` (string | null) - Team profile image URL
**Returns:** `Promise<ServerTeam>`
</MethodContent>
<MethodAside>
<AsideSection title="Signature">
```typescript
declare function createTeam(data: {
displayName: string;
profileImageUrl?: string | null;
}): Promise<ServerTeam>;
```
</AsideSection>
<AsideSection title="Examples">
```typescript
const team = await stackServerApp.createTeam({
displayName: "New Team",
profileImageUrl: "https://example.com/profile.jpg",
});
```
</AsideSection>
</MethodAside>
</MethodLayout>
</CollapsibleMethodSection>