---
title: API reference
description: Every authentication method, type and error code in the Zeitlos SDK.
sidebarLabel: API reference
---

The auth surface of `@zeitlosapp/sdk`, reached as `client.auth`. It is browser-safe: the
session is an httpOnly cookie, so these calls work from client components as well as server
code.

## createClient

```ts
import { createClient } from '@zeitlosapp/sdk';

const client = createClient(); // zero-config in a hosted app
```

It'll know automatically how to talk to the Zeitlos authentication endpoints.
Only in local development if you changed the `ports.auth` variable in your `zeitlos.dev.json`, you'll need to tell the client how to reach the auth endpoints. See [local development](/authentication/local-development) for more details.

> [!NOTE]
> The Zeitlos authentication endpoints are living under `/__auth`. This means any URL under
> that path won't be routed to your app, so you can't use URLs beginning with `/__auth`.

## createClientForUser

Binds a server request's session to the client, so every auth call carries it:

```ts
import { cookies } from 'next/headers';
import { createClientForUser } from '@zeitlosapp/sdk';

const client = createClientForUser({ cookies: await cookies() });
const user = await client.auth.getUser();
```

Accepts one of `{ cookies }` (a Next cookie store or a raw cookie string), `{ request }` (a
`Request`, `NextRequest` or Node `IncomingMessage`), or `{ headers }` (a `Headers` or a Node
headers record).

## Methods

| Method                                  | Returns                       |
| --------------------------------------- | ----------------------------- |
| `signUp({ email, password, name })`     | `AuthUser`                    |
| `signIn({ email, password })`           | `AuthUser`                    |
| `signOut()`                             | `void`                        |
| `getUser()`                             | `AuthUser \| null`            |
| `getUser({ profile: true })`            | `AuthUserWithProfile \| null` |
| `updateProfile(patch)`                  | the updated profile values    |
| `sendVerificationEmail({ email })`      | `void`                        |
| `forgetPassword({ email })`             | `void`                        |
| `resetPassword({ token, newPassword })` | `void`                        |

```ts
await client.auth.signUp({ email, password, name });
await client.auth.signIn({ email, password });
await client.auth.signOut();

const user = await client.auth.getUser();
const me = await client.auth.getUser({ profile: true });
await client.auth.updateProfile({ bio: 'Hello' });

await client.auth.sendVerificationEmail({ email });
await client.auth.forgetPassword({ email });
await client.auth.resetPassword({ token, newPassword });
```

`getUser` is the one call that does not throw when there is no session — it returns `null`.

### Optional inputs

| Call                    | Extra field   | Effect                                        |
| ----------------------- | ------------- | --------------------------------------------- |
| `sendVerificationEmail` | `callbackURL` | Override where the user lands after verifying |
| `forgetPassword`        | `redirectTo`  | Override the reset page for this call         |

## Types

```ts
interface AuthUser {
  id: string;
  email: string;
  emailVerified: boolean;
  name?: string;
  image?: string | null;
  createdAt?: string;
}

interface AuthUserWithProfile<P> extends AuthUser {
  profile: MaskedProfile<P>;
}

type ProfileValues = Record<string, string | string[] | null>;
```

`MaskedProfile<P>` makes every field of `P` optional and nullable — absent when not visible
to the caller, `null` when visible but unset. See
[Profile fields](/authentication/profile-fields/).

## Errors

Auth calls throw `ZeitlosError` with a machine-readable `.code`:

```ts
import { ZeitlosError } from '@zeitlosapp/sdk';

try {
  await client.auth.signIn({ email, password });
} catch (err) {
  if (err instanceof ZeitlosError && err.code === 'EMAIL_NOT_VERIFIED') {
    await client.auth.sendVerificationEmail({ email });
  }
}
```

| Code                            | When                                                  |
| ------------------------------- | ----------------------------------------------------- |
| `INVALID_EMAIL_OR_PASSWORD`     | `signIn` credentials didn't match                     |
| `USER_ALREADY_EXISTS`           | `signUp` with an already-registered email             |
| `EMAIL_NOT_VERIFIED`            | `signIn` blocked because the email isn't verified     |
| `RESET_PASSWORD_NOT_CONFIGURED` | `forgetPassword` with no reset page configured        |
| `INVALID_TOKEN`                 | `resetPassword` with an expired or already-used token |

The list isn't exhaustive — treat unknown codes generically.

## Not in the SDK

This is the **end-user** surface: your own session and your own profile. Administrative
operations — listing users, editing someone else's profile, defining profile fields — happen
in the dashboard or through the [MCP server](/getting-started/mcp-server/).
