PermuteDocs
Go to Permute

Apps · appsSiteUpdate

Save an app site draft

Verifies uploaded files and saves a complete manifest with a compare-and-set draft ref. Requires index.html. Build with relative asset URLs (Vite base ./); HTML receives a revision-specific base URL. Use spa=true for extensionless HTML navigation fallback. Omitted files are removed from the new draft only. Optional actions pin published action revisions as dependencies of the same app revision; omit it to preserve bindings or send [] to remove them. Query access follows current app grants and user permissions; source grant changes take effect without republishing. Saving and publishing require invocation permission on each selected action. App users still need their own action permissions. Publication additionally requires explicit app grants for every bound action. App admins manage these grants separately; saving or restoring a draft never grants access. Publish through the shared resource versioning API. No build or publication occurs here.

PUT/v1/apps/{applicationId}/site
betaapiKeyworkspace

When to use

Save a complete uploaded site as the app draft.

For agents

Use the draft ref read before editing; a conflict requires reconciliation. Build locally with relative asset URLs. Optional actions pins published action revisions with the site; omit it to preserve bindings or send [] to clear them. Binding grants no additional user permissions. Publication requires current app resource grants; approve them separately with apps.setGrant using app and target admin access. Save does not publish: use client.revisions.publish with the version token returned by revisions.list, checking that its draft matches your saved revision.

Example

typescript
import { PermuteClient } from '@permute/sdk';

const orgClient = new PermuteClient({
  apiKey: process.env.PERMUTE_API_KEY!,
});

const client = orgClient.withWorkspace(process.env.PERMUTE_WORKSPACE_ID!);

const result = await client.apps.saveSite('appl_abcdefghijklmnopqrstuvwx', {
  "site": {
    "files": [
      {
        "path": "index.html",
        "sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
        "size": 1024
      }
    ],
    "spa": true
  },
  "actions": [
    {
      "actionId": "actn_abcdefghijklmnopqrstuvwx",
      "revisionId": "rvsn_publishedaction"
    }
  ],
  "expectedDraft": {
    "revisionId": "rvsn_draft123",
    "sequence": 1
  }
});

Request body

json
{
  "site": {
    "files": [
      {
        "path": "index.html",
        "sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
        "size": 1024
      }
    ],
    "spa": true
  },
  "actions": [
    {
      "actionId": "actn_abcdefghijklmnopqrstuvwx",
      "revisionId": "rvsn_publishedaction"
    }
  ],
  "expectedDraft": {
    "revisionId": "rvsn_draft123",
    "sequence": 1
  }
}

Response

json
{
  "data": {
    "id": "appl_abcdefghijklmnopqrstuvwx",
    "workspaceId": "wksp_finance123",
    "name": "Operations portal",
    "description": "Internal operations portal",
    "deployment": {
      "status": "deploying",
      "url": "https://operations-portal-abcdefghijklmnopqrstuvwx.permute.site",
      "revisionId": "rvsn_draft123",
      "error": null
    },
    "draft": {
      "revisionId": "rvsn_draft123",
      "sequence": 1
    },
    "createdAt": "2026-09-30T12:00:00.000Z",
    "updatedAt": "2026-09-30T12:00:00.000Z"
  }
}