# Quickstart

Register your app, complete the iframe handshake, and authenticate your first member.

Source: https://zetapad.com/developers/docs/quickstart

## Prerequisites

You need a completed Zetapad profile with Developer access enabled by an administrator, a hosted web app, and a backend that can keep a client secret and server-side visitor sessions. Only enabled profiles see Developers and can manage apps or use previews. Every app requires backend login, including apps with zero scopes; a small serverless function is sufficient. Your app must use an origin separate from Zetapad. Public apps require HTTPS; local previews have the exceptions described in [embedding](https://zetapad.com/developers/docs/embedding).

## Register your app

1. Open the [developer dashboard](https://zetapad.com/campus/developers).
2. Create an app with a name, description, launch URL, and required permissions.
3. Save the one-time client secret on your backend as `ZETAPAD_CLIENT_SECRET`.
4. Save the app's client ID as `ZETAPAD_CLIENT_ID`. The client ID remains visible on the app page.

Request only the profile fields your app uses. You may register `scopes: []`: backend userinfo still returns the stable shared server `userId` after approval and credential exchange. Never include the secret in a URL, browser bundle, analytics, or logs.

## Prepare the launch page

Allow Zetapad to embed your app by sending this HTTP response header on every app document:

```http
Content-Security-Policy: frame-ancestors https://zetapad.com https://www.zetapad.com;
```

Merge this directive into your existing CSP. Remove conflicting `X-Frame-Options: DENY` or `SAMEORIGIN` headers. See [embedding](https://zetapad.com/developers/docs/embedding) for sandbox limitations.

If the app must run only in Zetapad, initially render only a public loading shell and apply the [access-control guide](https://zetapad.com/developers/docs/access-control). Protected data and app controls become available only after the server verifies authentication.

## Add the integration

Use the complete [browser example](https://zetapad.com/developers/docs/examples/browser) and [server example](https://zetapad.com/developers/docs/examples/server). Supply your framework's routing, session middleware, `startYourApp`, and `showLoginError`.

The required sequence is:

1. Install the message listener and check `event.source === window.parent` and the exact trusted `event.origin`.
2. Call `ready` with empty params and retain its `launchId`.
3. Fetch a random challenge from your backend's `GET /zetapad/state` endpoint. Store it in the same server-side session used for login.
4. Send version 2 `authenticate` with `{ launchId, state }` and wait for member consent. The success reply contains only the one-use `code`, `expiresIn`, and echoed `state`.
5. Submit the returned code and echoed state to your backend's `POST /zetapad/login`.
6. Validate and consume the session challenge, exchange the code at `POST https://zetapad.com/v1/apps/token`, and store the access token on your backend.
7. Read `GET https://zetapad.com/v1/apps/userinfo` using the bearer token, establish the server session, and then start the app. Use the verified `userId` to store persistent experiences across apps; later protected actions resolve it from that session.

The `/zetapad/state` and `/zetapad/login` endpoints belong to your app. Zetapad supplies `/v1/apps/token` and `/v1/apps/userinfo`.

The iframe bridge exposes no member IDs or profiles. Your backend may return approved display fields after login. Do not create a session from browser-supplied identity or start the app when backend login fails. See [why verification belongs on the backend](https://zetapad.com/developers/docs/authentication#why-the-backend-is-required).

## Add campus calls

To use a member's existing call in your app, register `calls:read` and add `calls:control` for invitations or call actions. App calls are available by default; permissions and native per-call approval still apply. After the normal backend login, follow the [calls guide](https://zetapad.com/developers/docs/calls) and [hosted call example](https://zetapad.com/developers/docs/examples/calls) to attach, select speaker tiles or audio-only, and hand presentation back to Zetapad. Your backend uses REST and your browser mounts hosted iframes.

## Verify in Preview

Use Preview on your unpublished app's developer page. Only its developer owner can launch an unpublished preview. Approve the registered permissions, confirm that login finishes, and check that fields outside those permissions are omitted.

If you require exclusive Zetapad access, open the app URL in a separate browser tab and confirm that it returns a blocked page. Also verify that direct requests to protected API endpoints fail without a valid app session.

## Publish

Publish the HTTPS launch URL to list the app in [Rooms](https://zetapad.com/campus/rooms). You can edit its name, description, URL, and scopes while it stays published. Saves invalidate issued app access; members reopen and authenticate, with fresh consent for scope or origin changes. See [publishing and app lifecycle](https://zetapad.com/developers/docs/publishing).
