---
title: "Toggle whether anyone can open the app with no login"
method: PUT
path: "/app/{id}/public"
---

# Toggle whether anyone can open the app with no login

`PUT /app/{id}/public`

## Request

- Base URL: `https://charm.ing`
- URL: `https://charm.ing/app/{id}/public`
- Auth: HTTP bearer

Owner-only. When `public: true`, anyone with the URL can open the live hosted App Viewer with no login and receives Viewer access (`app:read` only). Public visitors can read App data but cannot edit source or run mutating operations, except an operation whose route declares `callers`. Template and Listed are separate settings. When `public: false`, anonymous visitors can no longer open the hosted App. Existing App data is retained. Idempotent calls are no-ops.

## Request body

- object
  - `public` boolean, required

## Response `200`

Public state updated.

- AppPublicResponse: New public state plus the public URL when public is true.
  - `public` boolean, required
  - `public_url` string, nullable, required: Public URL when `public: true` (friendly `/{handle}/{app-name}` form when available, `/app/{id}` otherwise). Anyone can open the live hosted App Viewer with no login and read its data, but cannot change data or source. `null` when `public: false`.

## Other responses

- `400`: Body is not `{ public: boolean }`.
- `401`: User-scoped auth required.
- `403`: Caller does not own this app.
- `404`: App not found.
- `409`: Race: the row was concurrently re-attributed (e.g. `userId` cleared) between the ownership pre-check and the service-layer mutation. Defense-in-depth — extremely unlikely in practice.

---

[API](https://skmtc.dev/charm/apis/charming-api.md) · [All operations](https://skmtc.dev/charm/apis/charming-api/llms.txt) · [OpenAPI document](https://skmtc.dev/charm/apis/charming-api/revisions/a9d06c419b3a?raw)
