> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getpara.com/llms.txt
> Use this file to discover all available pages before exploring further.

# How Configuration Works

> Where Para reads configuration from — the partner record, SDK overrides, and deprecated modal props — and how they layer.

In v3, your **partner record** is the source of truth for how your integration looks and behaves — authentication methods, theme, external wallets, links, and more. You manage it in the [Developer Portal](https://developer.getpara.com), and the SDK reads it at runtime. Most settings no longer need to live in your app code.

**What you'll learn**

* Where Para reads each setting from, and how the layers combine
* What you can override in code with `configOverrides`, and what is partner-authoritative
* How the SDK enforces resolved configuration with `PartnerConfigError`
* Which `paraModalConfig` props are deprecated and what replaces them

## Where configuration comes from

Para resolves each setting from three layers. A higher layer only overrides the specific fields it sets — everything else falls through to the layer below.

```text theme={null}
SDK configOverrides   (code, per-instance)        ← highest priority
        ▼
Partner record        (Developer Portal)          ← the source of truth
        ▼
Deprecated ParaModal props (paraModalConfig.*)     ← fallback for un-migrated apps
```

<Note>
  This is a per-field merge, not all-or-nothing. If your partner record sets an OAuth allowlist but you override only the theme in code, you get your code theme **and** the partner's OAuth allowlist.
</Note>

## The partner record (source of truth)

The partner record is fetched from your API key when the SDK initializes. Configure it in the Developer Portal. It governs:

* **Authentication** — OAuth methods, email/phone toggles, 2FA, guest mode, auth layout
* **Branding & theme** — colors, font, border radius, logo, "hide wallet" language
* **External wallets** — supported wallets, connection mode, WalletConnect project ID, app description
* **App identity & links** — display name, homepage/social/support URLs, RPC URL
* **Other** — supported wallet types, account links, balance display

Because it lives on the partner record, you can change any of these in the portal **without redeploying your app**.

## Overriding in code with `configOverrides`

For per-instance overrides, pass `configOverrides` to `ParaProvider`. This is the supported, non-deprecated way to override partner config from code — useful when one API key powers multiple brand contexts, or for pointing `rpcUrl` at a local node during development.

```tsx theme={null}
<ParaProvider
  paraClientConfig={{ apiKey: process.env.NEXT_PUBLIC_PARA_API_KEY || "" }}
  configOverrides={{
    themeConfig: {
      foregroundColor: "#007AFF",
      backgroundColor: "#FFFFFF",
    },
    authConfig: {
      oAuthMethods: ["GOOGLE", "APPLE"],
    },
  }}
>
  {children}
</ParaProvider>
```

`configOverrides` is typed as `Partial<SdkOverridableAppConfig>` — the compiler only lets you override fields that are safe to set per-instance.

### What you can override

| Area                   | Overridable fields                                                                                                                             |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `themeConfig`          | All theme fields (colors, font, border radius, mix ratio, `cssOverrides`)                                                                      |
| `authConfig`           | `oAuthMethods`, `disableEmailLogin`, `disablePhoneLogin`, `twoFactorAuthEnabled`, `isGuestModeEnabled`                                         |
| `modalConfig`          | `hideWallets`, `authLayout`, `hideLogo`, `disableAddFundsPrompt`                                                                               |
| `externalWalletConfig` | `wallets`, `connectionOnly`, `includeWalletVerification`, `createLinkedEmbeddedForExternalWallets`, `walletConnectProjectId`, `appDescription` |
| `rpcUrl`               | The chain RPC URL (handy for local dev)                                                                                                        |

### What is partner-authoritative (cannot be overridden)

These are excluded from `SdkOverridableAppConfig` at the type level — the SDK cannot weaken them, and they live only on the partner record:

| Field                                         | Why                                        |
| --------------------------------------------- | ------------------------------------------ |
| `authConfig.supportedAuthMethods`             | Security posture                           |
| `supportedWalletTypes`                        | Security/policy boundary                   |
| `supportedAccountLinks`                       | Security/policy boundary                   |
| `balancesConfig`                              | Partner-level setting                      |
| `partnerLinks` (homepage/social/support URLs) | One per project                            |
| `appName`                                     | One per project                            |
| `farcasterConfig`                             | Read only by the backend (email templates) |

## Enforcement: `PartnerConfigError`

The SDK enforces the resolved auth and wallet configuration at its entry points (sign-up/login, OAuth, 2FA setup, guest wallet creation), not just in the modal. If you trigger something that is **explicitly disabled**, the call throws a `PartnerConfigError` with a stable `.code`.

```ts theme={null}
import { PartnerConfigError } from "@getpara/react-sdk";

try {
  await para.createGuestWallets();
} catch (e) {
  if (e instanceof PartnerConfigError && e.code === "GUEST_MODE_DISABLED") {
    // Guest mode is turned off for this partner — handle gracefully.
  }
}
```

| `code`                     | Thrown when                                                                                 |
| -------------------------- | ------------------------------------------------------------------------------------------- |
| `EMAIL_LOGIN_DISABLED`     | `authConfig.disableEmailLogin` is `true`                                                    |
| `PHONE_LOGIN_DISABLED`     | `authConfig.disablePhoneLogin` is `true`                                                    |
| `OAUTH_METHOD_NOT_ALLOWED` | An OAuth method isn't in the resolved `oAuthMethods` allowlist (`.detail` holds the method) |
| `TWO_FACTOR_DISABLED`      | `authConfig.twoFactorAuthEnabled` is explicitly `false`                                     |
| `GUEST_MODE_DISABLED`      | `authConfig.isGuestModeEnabled` is explicitly `false`                                       |

<Info>
  **Unset means "not configured", not "disabled."** A field that has never been set stays permissive; the gate only fires on an explicit choice (a `true` disable flag, an explicit `false` opt-in flag, or a defined OAuth allowlist). This keeps upgrades non-breaking: restrictions take effect once you configure them in the portal or with `configOverrides`, not before.
</Info>

<Note>
  The default `<ParaModal />` hides disabled options, so you typically only hit `PartnerConfigError` from **custom UI** or **direct SDK calls**, or when a deprecated fallback conflicts with higher-priority resolved config.
</Note>

## Deprecated: configuring via `paraModalConfig` props

These `paraModalConfig` props still work, but they're the **lowest-priority fallback** and are deprecated — they'll be removed in the next major release. Each emits a one-time console warning. Configure them on the partner record (Developer Portal) instead, or use `configOverrides` for per-instance overrides.

| Deprecated `paraModalConfig` prop        | Configure instead via                                                     |
| ---------------------------------------- | ------------------------------------------------------------------------- |
| `oAuthMethods`                           | Portal authentication / `configOverrides.authConfig.oAuthMethods`         |
| `disableEmailLogin`, `disablePhoneLogin` | Portal authentication / `configOverrides.authConfig.*`                    |
| `twoFactorAuthEnabled`                   | Portal authentication / `configOverrides.authConfig.twoFactorAuthEnabled` |
| `isGuestModeEnabled`                     | Portal authentication / `configOverrides.authConfig.isGuestModeEnabled`   |
| `authLayout`                             | Portal authentication / `configOverrides.modalConfig.authLayout`          |
| `hideWallets`                            | Portal / `configOverrides.modalConfig.hideWallets`                        |
| `theme`                                  | Portal branding / `configOverrides.themeConfig`                           |
| `logo`                                   | Portal branding / `configOverrides.modalConfig.logo`                      |
| `supportedAccountLinks`                  | Portal (partner-authoritative)                                            |
| `balances`                               | Portal (partner-authoritative)                                            |

<Warning>
  Because props are the lowest layer, a value you set in code is **overridden** by the same setting on the partner record. If a prop seems to have no effect, check whether the partner record sets it.
</Warning>

See the [Migration Guide](/v3/introduction/migration-to-v3) for step-by-step migration of each prop.

## Next steps

* [Style the Modal](/v3/react/guides/customization/modal-theming) — theme, fonts, and CSS overrides
* [Customization Basics](/v3/react/guides/customization/modal) — the full `paraModalConfig` reference
* [Migrating to v3](/v3/introduction/migration-to-v3) — what changed and how to move config to the partner record
