# Apps platform

> Package custom objects, UI, automations, settings and integrations into one JSON app definition that any Kustomer org can install, configure and update.

Source: https://developer.kustomer.com/docs/apps

A Kustomer **app** is a JSON document, the **app definition**, that declares everything an integration needs: custom objects and their attributes, UI inside the agent desktop, workflows and the actions and triggers they use, settings for admins, OAuth connections, and webhooks. You register the definition once. Each org that installs it gets every component created in their account, configured with their own settings, and updated when they choose to move to a new version.

You don't host anything for most apps. Kustomer stores and runs the KViews, workflows, actions, hooks and settings pages. You only host code when you want your own UI in an iframe or your own API behind an action.

_An app definition on the left with top-level keys app, settings, auth, klasses, kviews, widgets, hooks, triggers, actions, workflows, commands, outboundWebhooks, i18n and changelog. Selecting a key highlights where it appears in a mock Kustomer desktop: App Directory listing, settings page, navigation-rail widget, timeline object, insight card and details, or the behind-the-scenes workflows, hook URL, webhooks and commands._

## What you can build

| You want to                                                        | Use                                       | Guide                                                                                                                                    |
| ------------------------------------------------------------------ | ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| Store orders, subscriptions, devices or bookings next to customers | `klasses`                                 | [Klasses](https://developer.kustomer.com/docs/apps/klasses)                                                                              |
| Add your fields to customers, companies or conversations           | `klasses` with `metadata.standard`        | [Klasses](https://developer.kustomer.com/docs/apps/klasses#add-attributes-to-standard-objects)                                           |
| Show your data in the timeline or the insights panel               | `kviews`                                  | [KViews](https://developer.kustomer.com/docs/apps/kviews)                                                                                |
| Embed your own hosted UI next to the agent                         | `kviews` with `DynamicCard`, or `widgets` | [KViews](https://developer.kustomer.com/docs/apps/kviews#embed-your-own-ui), [Widgets](https://developer.kustomer.com/docs/apps/widgets) |
| Accept data from your platform and act on it                       | `hooks`, `triggers`, `workflows`          | [Workflows, actions and triggers](https://developer.kustomer.com/docs/apps/workflows-actions-triggers)                                   |
| Let admins call your API from any workflow                         | `actions`                                 | [Actions](https://developer.kustomer.com/docs/apps/workflows-actions-triggers#actions-call-your-api)                                     |
| Call your API from your UI without exposing a key                  | `commands`                                | [Commands](https://developer.kustomer.com/docs/apps/kviews#call-apis-with-commands)                                                      |
| Ask each org for an API key, subdomain or preference               | `settings`, `settingsPageConfig`          | [Settings](https://developer.kustomer.com/docs/apps/settings)                                                                            |
| Connect to a third-party API with the admin's OAuth grant          | `auth.oauth2`                             | [OAuth for apps](https://developer.kustomer.com/docs/apps/oauth#call-third-party-apis-with-oauth)                                        |
| Let your hosted service call the Kustomer API as a user            | `redirectUris` and the OAuth provider     | [OAuth for apps](https://developer.kustomer.com/docs/apps/oauth#call-kustomer-as-a-user)                                                 |
| Receive Kustomer events in your service from every install         | `outboundWebhooks`                        | [Outbound webhooks](https://developer.kustomer.com/docs/apps/workflows-actions-triggers#outbound-webhooks)                               |

## Private and public apps

**Private**

A private app is registered by your org and can only be installed by your org. It's the right choice for internal tooling, for one customer's custom integration, and for developing and testing any app.

When you register a private app, Kustomer appends your org ID to its name to keep it globally unique: `acme_orders` becomes `acme_orders_<orgId>`. Component names are rewritten to match. See [Register and install](https://developer.kustomer.com/docs/apps/register-and-install#names-are-namespaced).

**Public**

A public app appears in every org's App Directory. You build and test it as a private app, then submit the definition to Kustomer for review. Kustomer publishes the approved version under its plain name, without an org suffix.

The API you register private apps with only accepts `"visibility": "private"`. See [Publish to the marketplace](https://developer.kustomer.com/docs/apps/marketplace).

## The lifecycle

```mermaid
sequenceDiagram
  autonumber
  participant Dev as You
  participant Apps as Kustomer apps API
  participant Org as Installing org
  Dev->>Apps: POST /v1/apps/available (app definition)
  Apps->>Apps: Validate every component (dry run)
  Apps-->>Dev: 201, version registered
  Org->>Apps: Install app version
  Apps->>Apps: Dry run in the org, then create components
  Org->>Org: Admin fills in settings, connects OAuth
  Dev->>Apps: POST a new version (bumped semver)
  Org->>Apps: Update to the new version
  Apps->>Apps: Create new, update changed, remove dropped components
```

1. **Register.** You `POST` the definition. Kustomer validates every component against the services that will own it, so a broken workflow or KView fails registration with nothing half-created.
2. **Install.** An admin installs from **Settings › Apps**, or you call the install endpoint. Kustomer validates again in that org (for example, a name clash with a Klass the org already has) and then creates each component.
3. **Configure.** Admins fill in settings, connect any OAuth account, and review the workflows the app installed.
4. **Update.** Each change ships as a new semver version. Installed orgs keep running their version until they update.

## Your first app in five minutes

#### Get an API key

Create an API key with the `org.admin.apps` role in a sandbox org. Registering an app can't be undone from the UI, so don't experiment in production.

#### Write a definition

```json title="acme_orders.json"
{
  "app": "acme_orders",
  "version": "0.1.0",
  "title": "Acme Orders",
  "description": "Orders from Acme, on the customer timeline.",
  "visibility": "private",
  "klasses": [
    {
      "name": "acme_orders-order",
      "icon": "cart",
      "color": "#5B6CF9",
      "metadata": {
        "properties": {
          "orderNumberStr": { "displayName": "Order number" },
          "totalNum": { "displayName": "Total" },
          "placedAt": { "displayName": "Placed" }
        }
      }
    }
  ],
  "changelog": {
    "0.1.0": "{{October 2026}} First version."
  }
}
```

#### Register it

```bash title="cURL"
curl -X POST "https://acme.api.kustomerapp.com/v1/apps/available" \
  -H "Authorization: Bearer $KUSTOMER_API_KEY" \
  -H "Content-Type: application/json" \
  --data @acme_orders.json
```

```bash title="kusty"
kusty api POST /v1/apps/available --data @acme_orders.json
```

The `201` response contains the namespaced name, such as `acme_orders_5f8481c6a22ab5b9d5f2dd8a`, and the version ID `acme_orders_5f8481c6a22ab5b9d5f2dd8a-0.1.0`.

#### Install it

Open **Settings › Apps › App Directory**, find **Acme Orders**, and select **Install**. Or call the API:

```bash title="cURL"
curl -X POST "https://acme.api.kustomerapp.com/v1/apps/install" \
  -H "Authorization: Bearer $KUSTOMER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"app": "acme_orders_5f8481c6a22ab5b9d5f2dd8a", "version": "0.1.0"}'
```

#### Use it

Create an order with [`POST /v1/customers/{id}/klasses/acme_orders-order`](https://developer.kustomer.com/api/core-resources/create-customer-kobject-custom-object). Klass names aren't namespaced, so you use the name from your definition. The order appears on the customer's timeline with the cart icon.

> **Start from the starter repo:** [`kustomer/kustomer-apps-starter-configs`](https://github.com/kustomer/kustomer-apps-starter-configs) contains example definitions and an `npm run register-new-version` script that reads your org's API base URL and token from `.env`. It's the fastest way to get a register-edit-register loop going.

## Where to go next

- [App definition anatomy](https://developer.kustomer.com/docs/apps/app-definition): Every top-level key, its type and its rules.
- [Klasses](https://developer.kustomer.com/docs/apps/klasses): Custom objects and attributes on standard objects.
- [KViews](https://developer.kustomer.com/docs/apps/kviews): JSX in the timeline and insights panel, plus the Cards SDK.
- [Workflows, actions and triggers](https://developer.kustomer.com/docs/apps/workflows-actions-triggers): Hooks in, actions out, workflows in between.
- [Register and install](https://developer.kustomer.com/docs/apps/register-and-install): Endpoints, namespacing, errors and troubleshooting.
- [Publish to the marketplace](https://developer.kustomer.com/docs/apps/marketplace): Review requirements and the submission checklist.

> **For AI agents:** An app definition is a single JSON document validated against a strict schema: unknown top-level keys are rejected. Generate it, register it with `kusty api POST /v1/apps/available --data @app.json`, and read the error's `title` and `source` to fix validation failures. Always bump `version` before re-registering.
