diff --git a/cookbook/rain.mdx b/cookbook/rain.mdx
new file mode 100644
index 00000000..f114726e
--- /dev/null
+++ b/cookbook/rain.mdx
@@ -0,0 +1,225 @@
+---
+title: 'Use Turnkey wallets with Rain'
+sidebarTitle: "Rain integration"
+---
+
+## Overview
+
+[Rain](https://rain.xyz) is a card infrastructure platform that lets you issue credit cards backed by crypto wallets. In this guide, we'll walk through using Turnkey to create a self-custody wallet, apply for a Rain credit card linked to that wallet, and sign a funding authorization so the card is ready to spend.
+
+We'll use `@turnkey/react-wallet-kit` for browser-based authentication and wallet creation, and Turnkey's `signMessage` to authorize card funding. The user's keys never leave Turnkey's secure infrastructure.
+
+## Demo: Rain x Turnkey
+
+Watch a walkthrough of creating a self-custody wallet with Turnkey, linking a Rain credit card, and signing a funding authorization.
+
+
+
+
+
+---
+
+## Getting started
+
+Before you begin, make sure you've followed the [Turnkey Quickstart guide](/getting-started/quickstart).
+You should have:
+
+- A Turnkey **organization** and **Auth Proxy Config ID**
+- A **Rain API key** from the [Rain Developer Portal](https://docs.rain.xyz)
+
+You'll also need a backend proxy to safely forward requests to the Rain API without exposing your API key to the client.
+
+---
+
+## Install dependencies
+
+
+
+```bash npm
+npm i @turnkey/react-wallet-kit @turnkey/core react
+```
+
+```bash pnpm
+pnpm add @turnkey/react-wallet-kit @turnkey/core react
+```
+
+```bash yarn
+yarn add @turnkey/react-wallet-kit @turnkey/core react
+```
+
+
+
+## Setting up the Turnkey wallet
+
+We'll use `@turnkey/react-wallet-kit` to authenticate users via email OTP and create a wallet in one step.
+
+```tsx
+"use client";
+
+import { useTurnkey } from "@turnkey/react-wallet-kit";
+import { OtpType } from "@turnkey/core";
+
+export default function AuthPage() {
+ const {
+ initOtp,
+ completeOtp,
+ createApiKeyPair,
+ user,
+ wallets,
+ signMessage,
+ } = useTurnkey();
+
+ async function handleSignup(email: string, name: string) {
+ // 1. Send a verification code to the user's email
+ const otpId = await initOtp({
+ otpType: OtpType.Email,
+ contact: email,
+ });
+
+ // 2. After the user enters the code, verify and create the wallet
+ const publicKey = await createApiKeyPair();
+
+ await completeOtp({
+ otpId,
+ otpCode: "",
+ contact: email,
+ otpType: OtpType.Email,
+ publicKey,
+ createSubOrgParams: {
+ userName: name,
+ userEmail: email,
+ subOrgName: email,
+ customWallet: {
+ walletName: `${name} Wallet`,
+ walletAccounts: [
+ {
+ curve: "CURVE_SECP256K1",
+ pathFormat: "PATH_FORMAT_BIP32",
+ path: "m/44'/60'/0'/0",
+ addressFormat: "ADDRESS_FORMAT_ETHEREUM",
+ },
+ ],
+ },
+ },
+ });
+
+ // wallets[0].accounts[0].address now contains the new wallet address
+ }
+}
+```
+
+## Setting up the Rain API proxy
+
+Rain API calls require a server-side API key. Create an Express proxy to forward requests securely:
+
+```tsx
+import express from "express";
+
+const app = express();
+app.use(express.json());
+
+const RAIN_BASE = "https://api.raincards.xyz/v1";
+const API_KEY = process.env.RAIN_API_KEY!;
+
+async function rainFetch(path: string, body: object) {
+ const res = await fetch(`${RAIN_BASE}${path}`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ "Api-Key": API_KEY,
+ },
+ body: JSON.stringify(body),
+ });
+ return { status: res.status, data: await res.json() };
+}
+
+// Submit consumer application
+app.post("/api/rain/application", async (req, res) => {
+ const result = await rainFetch("/issuing/applications/user", req.body);
+ res.status(result.status).json(result.data);
+});
+
+// Create virtual card for a user
+app.post("/api/rain/users/:userId/cards", async (req, res) => {
+ const result = await rainFetch(
+ `/issuing/users/${req.params.userId}/cards`,
+ req.body
+ );
+ res.status(result.status).json(result.data);
+});
+```
+
+## Applying for a Rain card
+
+With the wallet created, submit a consumer application to Rain and then issue a virtual card:
+
+```tsx
+const walletAddress = wallets[0].accounts[0].address;
+
+// 1. Submit the consumer application
+const appRes = await fetch("/api/rain/application", {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({
+ firstName: "Alex",
+ lastName: "Demo",
+ birthDate: "1990-01-15",
+ email: "alex@example.com",
+ walletAddress,
+ // ... additional required fields
+ }),
+});
+
+const { id: userId } = await appRes.json();
+
+// 2. Issue a virtual credit card
+const cardRes = await fetch(`/api/rain/users/${userId}/cards`, {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({ type: "virtual" }),
+});
+
+const card = await cardRes.json();
+// card.last4, card.expirationMonth, card.expirationYear
+```
+
+## Signing a funding authorization
+
+To fund the card, use Turnkey's `signMessage` to sign an authorization payload from the user's wallet. The signature proves the wallet owner has approved the transfer. No private key ever leaves Turnkey's infrastructure.
+
+```tsx
+const account = wallets[0].accounts[0];
+
+const message = JSON.stringify({
+ action: "authorize_funding",
+ amount: 100,
+ currency: "rUSD",
+ wallet: account.address,
+ timestamp: new Date().toISOString(),
+});
+
+const signature = await signMessage({
+ message,
+ walletAccount: account,
+});
+
+// signature.r, signature.s, signature.v
+// Submit this signature to your backend to complete the funding
+```
+
+## Summary
+
+✅ You've now learned how to:
+
+- Authenticate users and create Turnkey wallets via email OTP using `@turnkey/react-wallet-kit`
+
+- Submit a consumer application to Rain and issue a virtual credit card linked to the wallet
+
+- Sign a funding authorization with `signMessage` so the card is ready to spend
+
+- Keep Rain API keys secure behind a server-side proxy
diff --git a/docs.json b/docs.json
index 3c0d612d..a7149f5f 100644
--- a/docs.json
+++ b/docs.json
@@ -254,6 +254,7 @@
{
"group": "Cookbook",
"pages": [
+ "cookbook/rain",
"cookbook/morpho",
"cookbook/aave",
"cookbook/breeze",
diff --git a/images/cookbook/rain-demo.mp4 b/images/cookbook/rain-demo.mp4
new file mode 100644
index 00000000..9e3e91ad
Binary files /dev/null and b/images/cookbook/rain-demo.mp4 differ