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

# Set up

> Configure backend-held credentials for embedded-wallet or custom-signer sponsorship.

Sponsorship configuration differs by client. Embedded wallets give Rhinestone a short-lived application token and a separate, single-use sponsorship grant. Custom signer integrations prepare sponsored transactions on a backend that holds the project API key.

<Warning>
  Keep private signing keys and API keys on your backend. Never put either
  credential in browser or mobile code.
</Warning>

## Configure sponsorship

<Tabs>
  <Tab title="Embedded wallet">
    ### Embedded wallets backend

    Embedded wallets use two endpoints on your backend:

    | Endpoint | Purpose | Typical lifetime |
    | - | - | - |
    | `GET /api/sponsorship/access-token` | Mints the app and project identity token. | 1 hour |
    | `POST /api/sponsorship/extension-token` | Mints a single-use grant from the wallet's canonical draft input or prepared transaction envelope. | 5 minutes |

    Use the values from the JWT key registered on the Dashboard's [**JWT keys** screen](https://dashboard.rhinestone.dev/keys/jwt):

    | Value | Purpose |
    | - | - |
    | Private JWK | Signs tokens. Store it only on the backend. |
    | Integrator ID | JWT `iss` claim. |
    | Project ID | JWT `sub` claim. It must match the project that owns the registered key. |
    | App ID | A label you choose for the deployment, such as `production`. |
    | Key ID | JWT `kid` header. It selects the registered public key. |

    `@rhinestone/wallet/server` reads these values from `RHINESTONE_JWT_PRIVATE_KEY`, `RHINESTONE_INTEGRATOR_ID`, `RHINESTONE_PROJECT_ID`, `RHINESTONE_APP_ID`, and `RHINESTONE_KEY_ID`. Its `extensionToken()` helper normalizes both embedded-wallet request shapes to the canonical intent input before signing.

    ```ts theme={null}
    // lib/sponsorship.ts
    import { createSponsorshipSigner } from "@rhinestone/wallet/server";

    export const sponsorshipSigner = createSponsorshipSigner();
    ```

    Mount each operation at the URL used by your client. Authenticate your normal application session before minting:

    ```ts theme={null}
    // app/api/sponsorship/access-token/route.ts
    import { sponsorshipSigner } from "@/lib/sponsorship";

    export async function GET(request: Request) {
      await requireApplicationSession(request);
      return Response.json({ token: await sponsorshipSigner.accessToken() });
    }
    ```

    ```ts theme={null}
    // app/api/sponsorship/extension-token/route.ts
    import { sponsorshipSigner } from "@/lib/sponsorship";

    export async function POST(request: Request) {
      await requireApplicationSession(request);
      const { intentOp } = await request.json();
      return Response.json({
        token: await sponsorshipSigner.extensionToken(intentOp),
      });
    }
    ```

    These are application-owned handlers for the embedded-wallet SDK, not Caucasus quote bodies. `requireApplicationSession` represents your application's session validation.

    <Warning>
      This minimal route shape is not a production policy. Configure issuance
      checks, bind the requested account to the authenticated session, and
      understand the current enforcement boundary described in [Policies and
      security](./policies-and-security).
    </Warning>

    ### Embedded wallets client

    Use these endpoint URLs in the shared [client initialization](/wallets/embedded-wallets/accounts#initialize-the-client):

    ```ts theme={null}
    import { WalletClient } from "@rhinestone/wallet";

    export const wallet = new WalletClient({
      providerUrl: "https://passkey.1auth.app",
      clientId: "my-app",
      sponsorship: {
        accessTokenUrl: "/api/sponsorship/access-token",
        extensionTokenUrl: "/api/sponsorship/extension-token",
      },
    });
    ```

    The embedded wallet sends cookies to these endpoint URLs. Your backend still decides how to authenticate the application session and whether to issue a sponsorship grant.

    ### Managed Solana setup

    The same endpoints sponsor `wallet.deploy({ chain })` for managed Solana setup, including transaction fees and wallet rent. Setup is app-paid and has no user-paid fallback. Each creation or enrollment can request a separate grant; retries can request more.

    Your backend must accept the current canonical Solana input and validate it through `shouldSponsor.intent`. EVM `account`, `calls`, or `appFees` filters reject Solana-only setup and spends even when their callbacks would return `true`. See [Solana issuance policy](./policies-and-security#managed-solana-issuance) and [Set up a Solana wallet](/wallets/embedded-wallets/accounts#set-up-a-solana-wallet). Follow [Migration](/wallets/embedded-wallets/migration-guide) when upgrading the client and sponsorship backend.

    ### Application authentication is not sponsorship

    The access token identifies the app and project. The embedded wallet needs it for both sponsored and user-paid intents. Only an extension token grants permission to spend sponsorship, and each `jti` can be redeemed once.

    Validate the full request before minting and use compatible client and server helpers for intent-bound grants. A digest in a token is not sufficient unless it matches the contract enforced downstream. See [Policies and security](./policies-and-security#current-enforcement-boundary) before exposing token endpoints to an untrusted client.
  </Tab>

  <Tab title="Custom signer">
    Run the sponsorship-enabled SDK flow on your backend with its project API key:

    ```ts theme={null}
    import { RhinestoneSDK } from "@rhinestone/sdk";

    const rhinestone = new RhinestoneSDK({
      auth: {
        mode: "apiKey",
        apiKey: process.env.RHINESTONE_API_KEY!,
      },
    });
    ```

    Authenticate your application's request, validate the account and transaction, then use this backend SDK instance to prepare, sign, and submit according to your signer architecture. Follow the [Custom signer quickstart](/wallets/custom-signer/quickstart) for account initialization; do not duplicate its signer configuration in a browser-facing sponsorship client.

    <Note>
      The SDK's `experimental_jwt` mode authenticates direct clients. SDK v3 uses
      the `sdk-3.0.0-caucasus` approval contract. Upgrade backend helpers before
      clients: `getIntentExtensionToken` runs once per sponsored prepare, before
      the quote request, never at submission. Denied or failed approval stops
      preparation without a user-paid fallback. Authentication alone does not
      authorize an intent. See [Custom signer policies](./policies-and-security#sdk-jwt-approval).
    </Note>
  </Tab>

  <Tab title="REST API">
    ### Bind sponsorship grants

    Keep API keys backend-only and pin `x-api-version: 2026-09.caucasus` on quotes, submission, and reads. Request fee coverage with [`options.sponsorship`](./sponsor-fees#request-fee-coverage).

    For singular intent-bound grants, validate the exact received `account`, optional `source`, nested `destination`, and `options` against your application's policy before issuance. Use sponsorship scope `intent` and the `sdk-3.0.0-caucasus` approval contract. The [sponsorship migration](/api-reference/api-versioning#update-sponsorship) defines the canonical input and SHA-256 digest over RFC 8785 JSON, encoded as lowercase hex. Preserve wire values, explicit `false` flags, and array order; omit absent `source` and default absent `options` to `{}`. Do not reuse Blanc digests.

    The orchestrator verifies this binding when an intent-scoped grant requests sponsorship. Setting the HTTP header alone does not make SDK browser grants intent-bound. Intent-bound grants cannot authorize sponsored estimates.
  </Tab>
</Tabs>

Next, choose [which fees to sponsor](./sponsor-fees) and configure [policies and budgets](./policies-and-security).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.