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

# App Events

> Use App Events to let your app communicate with UptopiaKit via postMessage and trigger platform capabilities.

# App Events

**App Events are the communication bridge** between your app’s logic and UptopiaKit. With App Events, developers can write simple message-based integrations to **invoke built-in capabilities** of UptopiaKit and supported miniapp platforms — all while keeping your app portable.

There are two ways to use App Events:

* **Default App Events (built-in)** — a set of standard events that **UptopiaKit creates automatically** for every app. You can use these immediately, without any dashboard setup.
* **Custom App Events** — events you define and configure in the dashboard for app-specific behaviors (the original model described in this document).

## How it works

Your app runs inside an UptopiaKit-managed frame. When your app wants to call a capability, it **sends a postMessage to the parent window (UptopiaKit)** with a specific payload format. UptopiaKit receives the message from the iframe and executes the corresponding logic.

High-level flow:

1. For **default events**, you can send the documented payloads directly (see **Default App Events** below).
2. For **custom events**, you define an App Event in the dashboard.
3. In your app code, you send `window.parent.postMessage(payload)` from inside the iframe.
4. UptopiaKit validates the message and triggers the requested capability.
5. For some events, UptopiaKit sends a **response message back to your app** via `postMessage`.

For security, prefer sending messages with the correct `targetOrigin` instead of `*` when possible.

## Default App Events

When a new app is created, UptopiaKit registers these default App Events that you can call immediately from your app code.

You **do not** need to create them in the dashboard.

### 1) ADD\_MINI\_APP

Adds your mini app for the current user **on the host platform** (for example, on Farcaster or The Base App).

When triggered, this event asks the host platform to open its native **“add miniapp”** UI. The exact UX depends on the platform, but typically:

* The user sees a popup/modal from the platform.
* After confirmation, your miniapp is added/pinned/installed in the user’s account or client.

**Request payload (from app → UptopiaKit)**

```js theme={null}
const payload = {
  name: "ADD_MINI_APP",
};

window.parent.postMessage(payload /*, targetOrigin */);
```

There is no structured response for this event; handle UI state changes in your app as needed (for example, optimistically updating UI after sending the event or reacting to platform-level changes if exposed elsewhere).

### 2) COMPOSE\_CAST

Opens a share/composer UI (e.g., on Farcaster) with provided text and optional embeds.

**Request payload**

```js theme={null}
const payload = {
  name: "COMPOSE_CAST",
  data: {
    text: "I just scored 8 on this game. Go play now!",
    embeds: [screenshot1_url, screenshot2_url], // optional
  },
};

window.parent.postMessage(payload /*, targetOrigin */);
```

Notes:

* `data.text` is the full text you want to share.
* `data.embeds` is optional; if it’s missing, UptopiaKit will typically default to sharing the app link (platform-specific behavior).

### 3) OPEN\_URL

Opens a URL in the user’s browser from within the miniapp.

**Request payload**

```js theme={null}
const payload = {
  name: "OPEN_URL",
  data: {
    url: "https://uptopia.xyz",
  },
};

window.parent.postMessage(payload /*, targetOrigin */);
```

Make sure to validate and sanitize URLs on your side as well.

### 4) IAP (In-app Purchases)

Triggers in-app purchase flows or lists available IAP packages for the current app.

**Request payload**

```js theme={null}
const payload = {
  name: "IAP",
  data: {
    packageId: "optional-package-id", // optional – only needed for BUY
    type: "BUY" || "LIST",
  },
};

window.parent.postMessage(payload /*, targetOrigin */);
```

* `type: 'BUY'` — attempts to purchase a specific package.
* `type: 'LIST'` — asks UptopiaKit for the list of available IAP packages.

**Response payloads (from UptopiaKit → app)**

Listen for messages in your app:

```js theme={null}
window.addEventListener("message", (event) => {
  // TODO: check event.origin
  const res = event.data;

  if (res?.type === "IAP_RES") {
    // Result of BUY
    // res.payload: { status: 0 | 1, packageId?: string }
  }

  if (res?.type === "IAP_LIST") {
    // Result of LIST
    // res.payload: Array<{
    //   id: string;
    //   name: string;
    //   packageId: string;
    //   price: number;
    //   description: string;
    //   gameId: string;
    //   status: 'active' | 'inactive';
    // }>
  }
});
```

Shapes:

```js theme={null}
// BUY result
const res = {
  type: "IAP_RES",
  payload: {
    status: 0 || 1, // implementation-dependent (e.g. 1 = success, 0 = failed)
    packageId: "string" || undefined,
  },
};

// LIST result
const res = {
  type: "IAP_LIST",
  payload: [
    {
      id: "string",
      name: "string",
      packageId: "string",
      price: 0,
      description: "",
      gameId: "string",
      status: "active" || "inactive",
    },
  ],
};
```

Your app should interpret `status` and update UI accordingly.

### 5) AUTH

Manages basic authentication-related flows and retrieves user information **from the underlying miniapp platform account** (for example, the user on Farcaster or The Base App).

Your app can use this information as a **basic authentication layer** or to associate in-game / in-app profiles with the platform user:

* `wallet` — the user’s wallet address as known by the host/platform (if available).
* `userId` — a stable identifier for the user on that platform.

> This is **not** a full OAuth flow; think of it as a lightweight identity + session bridge that lets you link your own user model to the platform user.

**Request payload**

```js theme={null}
const payload = {
  name: "AUTH",
  data: {
    packageId: "string", // optional, if your auth or entitlements are tied to a package
    type: "LOGIN" || "LOGOUT" || "GET_USER_INFOR",
  },
};

window.parent.postMessage(payload /*, targetOrigin */);
```

* `type: "LOGIN"` — asks the platform/UptopiaKit to make sure the user is signed in and then returns their identifiers.
* `type: "LOGOUT"` — requests a sign-out / session clear for the current user.
* `type: "GET_USER_INFOR"` — fetches the current user info if already logged in (without forcing a login flow).

**Response payload (from UptopiaKit → app)**

```js theme={null}
window.addEventListener("message", (event) => {
  // TODO: check event.origin
  const res = event.data;

  // For AUTH flows, UptopiaKit sends `res` with the following shape:
  // {
  //   wallet: string;
  //   userId: string;
  // }
});
```

Shape:

```js theme={null}
const res = {
  wallet: "string",
  userId: "string",
};
```

Depending on `type` and user state, fields may be empty/undefined (for example, after `LOGOUT` or if the user declined login). Your app can treat `(wallet, userId)` as the “logged-in user” and map that to your own internal user/session.

## Custom App Events

In addition to the default events above, you can still define **custom App Events** for your specific use cases.

### Create a custom App Event

Each custom App Event requires these fields in the dashboard:

* **Name**: recommended format is uppercase with underscores, e.g. **ABC\_XYZ**.
* **Type**: one of the supported event types (custom types managed by UptopiaKit).
* **Data**: a JSON definition for event data (used by the event and for validation/templates).

## Supported event types

Some event types are **used by default events**, and you can also reuse them for your own custom App Events if appropriate:

* **Add Mini App**: triggers a popup to add your mini app for users on platforms like Farcaster and The Base App.
* **Compose Cast**: triggers a share popup to compose a post on Farcaster (content and a link to open your miniapp).
* **Open URL**: opens a URL in the user’s browser from within the miniapp.
* **IAP**: triggers IAP flows (BUY/LIST) for in-app purchases.
* **AUTH / other internal types**: used by default App Events as described above.

Custom App Events should follow the same **name + data** contract as default ones.

## Payload contract (from your app)

Regardless of default or custom events, your app sends a message from the iframe to the UptopiaKit parent window with this minimal structure:

* **name**: string — the App Event Name (e.g., `ADD_MINI_APP`, `COMPOSE_CAST`, `OPEN_URL`, `IAP`, `AUTH`, or a custom name).
* **data**: object (optional) — runtime values used by the event.

Notes:

* The **Name must match** the event you created in the dashboard (for custom events) or one of the default event names above.
* **Only messages from the embedded app** running inside UptopiaKit (or its managed preview) are handled.
* **Do not include sensitive information** in `data`.

## Listening for responses (from UptopiaKit)

For events that return data (e.g., **IAP**, **AUTH**), register a listener in your app:

```js theme={null}
window.addEventListener("message", (event) => {
  // Always validate origin in production
  // if (event.origin !== 'https://your-uptopia-origin') return;

  const res = event.data;

  // Switch by res.type or by known shape, depending on the event.
  // See the per-event sections above for exact response shapes.
});
```

## Examples

### Example: Add Mini App (default)

```js theme={null}
const payload = {
  name: "ADD_MINI_APP",
};

window.parent.postMessage(payload);
```

### Example: Compose Cast (default)

```js theme={null}
const payload = {
  name: "COMPOSE_CAST",
  data: {
    text: "I just scored 8 on this game. Go play now!",
    embeds: [screenshot1_url, screenshot2_url], // optional
  },
};

window.parent.postMessage(payload);
```

### Example: Open URL (default)

```js theme={null}
const payload = {
  name: "OPEN_URL",
  data: {
    url: "https://uptopia.xyz",
  },
};

window.parent.postMessage(payload);
```

### Example: IAP BUY and LIST (default, with response handling)

```js theme={null}
// BUY
window.parent.postMessage({
  name: "IAP",
  data: {
    type: "BUY",
    packageId: "my-package-id",
  },
});

// LIST
window.parent.postMessage({
  name: "IAP",
  data: {
    type: "LIST",
  },
});

// Listen for responses
window.addEventListener("message", (event) => {
  const res = event.data;

  if (res?.type === "IAP_RES") {
    // handle buy result
  }

  if (res?.type === "IAP_LIST") {
    // handle list of packages
  }
});
```

### Example: AUTH (default)

```js theme={null}
// Login and get user info from the host platform (Farcaster / The Base App)
window.parent.postMessage({
  name: "AUTH",
  data: {
    type: "LOGIN",
  },
});

// Listen for user info
window.addEventListener("message", (event) => {
  const res = event.data;
  // res: { wallet: string; userId: string }

  // Example: map platform user to your own user/session
  // loginWithPlatformUser(res.userId, res.wallet);
});
```

## Validation and handling

* UptopiaKit validates the **event name, type, and data**. Unknown events or invalid payloads may be **ignored or rejected**.
* **Exact names matter**: use the same uppercase-with-underscores Name as defined in the dashboard (for custom events) or one of the documented default names.
* Ensure the app is **Active** and running inside an UptopiaKit context; otherwise, the message may not be handled.

## Security notes

* **Do not include secrets** (API keys, tokens, personal data) in event payloads.
* **Validate and sanitize URLs** when using `OPEN_URL`.
* Prefer specifying a **targetOrigin** in `postMessage` to restrict recipients.

## Related topics

* Apps overview: [/kit/core-concepts/apps](/kit/core-concepts/apps)
* Versioning: [/kit/core-concepts/versioning](/kit/core-concepts/versioning)
* Teams and permissions: [/kit/core-concepts/teams](/kit/core-concepts/teams)
