---
title: "Update security headers"
method: PUT
path: "/api/apps/{app_id}/security/headers"
---

# Update security headers

`PUT /api/apps/{app_id}/security/headers`

<Info>This API is in beta. Endpoints, fields, and behavior may still change, so avoid depending on it in production.</Info>

Changes the app's security header settings and returns them as they now stand.

Send only the settings you want to change. A setting you leave out keeps its value.

A change applies to the published app right away, with no need to deploy it again. It doesn't affect the builder's preview.

Turning on a setting that [Get security scan](/api-reference/get-security-scan) recommends in `header_recommendations` removes that recommendation from the scan result.

This is limited to 30 requests a minute per app for each workspace's personal API keys, so every key in a workspace shares one allowance. Some workspaces have a different limit.

<Note>This endpoint accepts a personal API key belonging to a user with editor access to the app. A read-only key is refused, and workspace API keys are not accepted.</Note>

## Path parameters

- `app_id` string, required — ID of the app.

## Request body

- object
  - `prevent_iframe_embedding` boolean — Set `true` to stop every site from showing the published app in a frame. Set `false` to lift that block, so framing follows the app's other settings and its workspace's policy again.
  - `restrict_browser_features` boolean — Set `true` to make the published app send a restrictive `Permissions-Policy` header, or `false` to stop sending it.

## Response `200`

The app's security header settings after the change.

- SecurityHeadersSettingsResponse — The app's security header settings.
  - `result` SecurityHeadersSettingsResult, required — Security header settings for one app.
    - `prevent_iframe_embedding` boolean, required — Whether the app blocks every site from showing it in a frame (`true`) or not (`false`). When `true`, the published app sends `X-Frame-Options: DENY`.
    - `restrict_browser_features` boolean, required — Whether the published app sends a restrictive `Permissions-Policy` header (`true`) or not (`false`). It lets only the app's own pages use the camera, microphone, location, payment, and USB features, and turns off the magnetometer and gyroscope.
    - `embedding_origins` string[], nullable, required — Sites the app itself allows to frame it, or `null` when the app has no list of its own.
    - `org_embedding_origins` string[], nullable, required — Sites the app's workspace allows to frame its apps, or `null` when the workspace sets no list or its plan doesn't include one.
    - `org_prevent_iframe_embedding` boolean, required — Whether the app's workspace blocks framing for all of its apps (`true`) or not (`false`).
    - `app_policy` AppEmbeddingPolicyResult, required — An app's own framing policy.
      - `mode` 'inherit' | 'block_all' | 'allowlist', required — What the app's own setting says. `inherit` means the app sets no policy and follows its workspace, `block_all` means no site can frame it, and `allowlist` means only `origins` can.
      - `origins` string[], nullable, required — Sites allowed to frame the app when `mode` is `allowlist`, or `null` for the other modes.
    - `effective_policy` EffectiveEmbeddingPolicyResult, required — A published app's framing policy after its workspace policy is applied.
      - `mode` 'anyone' | 'block_all' | 'allowlist', required — Who can show the published app in a frame. `anyone` means any site can, `block_all` means no site can, and `allowlist` means only `origins` can.
      - `source` 'default' | 'app' | 'workspace', required — Where the policy comes from. `app` is the app's own setting, `workspace` is its workspace's policy, and `default` means neither sets one.
      - `origins` string[], nullable, required — Sites allowed to frame the app when `mode` is `allowlist`, or `null` for the other modes.
    - `app_allowlist_locked_by_workspace` boolean, required — Whether the app's workspace controls which sites can frame its apps (`true`), so the app can't set a list of its own, or not (`false`).

## Other responses

- `401` — Missing or invalid credentials.
- `403` — You don't have editor access to this app, your API key is read-only, or you used a workspace API key.
- `404` — App not found.
- `422` — The body is missing or isn't a JSON object, has an unknown field, or has a value that can't be read as a boolean.
- `429` — Too many updates for this app in the last minute.

## Changes

- **2026-09-30** `63675fa5257c` — 1 info
  - endpoint added

[Change history](https://skmtc.dev/idealspot/apis/base44-app-management-api/changes/api/apps/:app_id/security/headers/put.md)

---

[API](https://skmtc.dev/idealspot/apis/base44-app-management-api.md) · [All operations](https://skmtc.dev/idealspot/apis/base44-app-management-api/llms.txt) · [OpenAPI document](https://skmtc.dev/idealspot/apis/base44-app-management-api/revisions/e58d4ff7b1f8?raw)
