platform-sandbox-configure

v2026.09.24

MUST USE this skill for ANY sandbox request — including simply getting a sandbox's details, status, license type, or pending-activation state by name or ID. TRIGGER when the user: types "sandbox -help"/"sandbox help"; mentions a sandbox ID (07E prefix); asks to list or show sandboxes; asks for the details, status, license type, or config of a sandbox by name or ID; activates or discards a completed refresh; deletes a sandbox; verifies activation or deletion; creates or refreshes a sandbox. DO NOT TRIGGER when: the user wants to clone a sandbox.

GitHub
Install command
npx skhub add forcedotcom/platform-sandbox-configure
Markdown
SKILL.md

Sandbox Lifecycle Management

Manage Salesforce sandbox environments through Connect REST API — list inventory, activate or discard completed refreshes, create and refresh sandboxes, and permanently delete sandboxes.

When This Skill Owns the Task

Use platform-sandbox-configure when the work involves:

  • Listing or retrieving all sandboxes (GET /sandbox/reports)
  • Getting details or status of a specific sandbox by name or by ID (07E prefix)
  • Checking license usage and remaining capacity by license type (GET /sandbox/licenses)
  • Activating a sandbox after a refresh completes (applying the refresh)
  • Discarding a completed refresh (keeping existing sandbox data unchanged)
  • Permanently deleting a sandbox to free up licenses
  • Verifying activation or deletion completed
  • Creating a new sandbox (Developer, Developer Pro, Partial Copy, or Full)
  • Refreshing an existing sandbox with latest production data

Delegate elsewhere when the user is:

  • Cloning a sandbox → Tooling API (SandboxInfo sObject)
  • Generating a post-copy automation JSON config from an SOP → automation-sandbox-post-copy-config-generate
  • Applying/running a post-copy automation JSON config against a sandbox → automation-sandbox-post-copy-configure

Help (Interactive Menu)

When the user types sandbox -help or sandbox help, respond with ONLY a text message showing the numbered operation list below. Do NOT call any API or tool — just display this menu and wait for the user to reply with a number.

The agent MUST respond with this exact markdown (not in a code block — render it directly as a bullet list):

Sandbox Lifecycle Management

1. Inventory & Details

  • a. List all sandboxes — Names, types, statuses, IDs
  • b. Get details (by name) — Status, license, config
  • c. Get details (by ID) — Provide a 07E ID directly
  • d. Check license usage — Available vs. used counts by license type

2. Create & Refresh

  • a. Create a new sandbox — Dev, Dev Pro, Partial, Full
  • b. Refresh a sandbox — Latest production data

3. Activate, Discard & Delete

  • a. Activate a sandbox — Apply a completed refresh
  • b. Discard a refresh — Reject, keep existing data
  • c. Delete a sandbox — Permanent removal

4. Verify & Monitor

  • a. Verify activation status — Check if activate completed
  • b. Verify deletion status — Check if delete completed

5. Post-Copy Automation

  • a. Create Post Copy Automation JSON Configs — Generate a config from an SOP
  • b. Run Post Copy Automation — Apply a config JSON to a sandbox

Reply with a code (e.g. "3a") or describe what you need.

After the user replies, ask for the required input:

SelectionFollow-up question
1aNo input needed — proceed immediately
1b"What's the sandbox name?"
1c"What's the sandbox ID? (starts with 07E)"
1dNo input needed — proceed immediately
2aFirst call GET /sandbox/licenses (Section 9) and show available/used counts; then ask for name + license type (Developer, Developer_Pro, Partial_Copy, Full)
2bFirst call GET /sandbox/reports (Section 1) and list refresh-eligible sandboxes (isPendingActivation: false); then ask which to refresh
3a"Which sandbox? Provide a name or 07E ID."
3b"Which sandbox? Provide a name or 07E ID."
3c"Which sandbox? Provide a name or 07E ID."
4a"Which sandbox did you activate? Provide a name or 07E ID."
4b"Which sandbox did you delete? Provide a name or 07E ID."
5a"Delegating to the post-copy config generator — please share the SOP (file, text, or screenshot)."
5b"Delegating to the post-copy config runner — please share the config JSON file and the target sandbox."

Execute the corresponding operation below. Exception: 5a/5b delegate — 5a → automation-sandbox-post-copy-config-generate; 5b → automation-sandbox-post-copy-configure. This skill does not implement post-copy automation; do not generate or apply a config directly.


API Base

CRITICAL: For sandbox operations in this skill, use the Connect REST API. Two discovery paths exist:

  • By name: Call GET /sandbox/reports to list all sandboxes and find the matching one by sandboxName.
  • By ID (07E prefix): Call GET /sandbox/sandboxes/{sandboxId} directly — do NOT call /sandbox/reports.

Both paths return sandbox records with sandboxId (prefix 07E) which is required for all lifecycle mutation operations.

sf api request rest "/services/data/v66.0/sandbox/reports" --method GET

See references/api-response-shapes.md for the full response shape.

IMPORTANT: Do NOT use Tooling API (SandboxInfo/SandboxProcess) for discovery — mutation endpoints require the Connect REST API's sandboxId (07E), NOT SandboxInfo.Id (0GQ) or SandboxProcess.Id (0GR).

NEVER use SOQL / run_soql_query / sf data query for lifecycle reads (status, inventory, details, license, pending-activation). This data lives ONLY in the Connect REST API — no SObject returns it. (sf data query --use-tooling-api on SandboxInfo is still valid for Create/Refresh mutations, not a lifecycle read.)

Report API results exactly as they come back — never invent an error or a cause. count: 0 is a successful result (sandbox absent) — record not_found, don't reinterpret as a failure or retry via SOQL. If the API errors, capture the error body verbatim — do NOT speculate why (e.g. "must be a scratch org"); this endpoint doesn't report org edition/type, so any such guess is a fabrication.

Required permission: ManageSandboxes

Irreversible Actions — Always Confirm First

ActionWhy irreversible
CreateConsumes a license of the selected type
ActivateOverwrites sandbox with refreshed data
DiscardRefresh data is lost
DeleteSandbox permanently removed
Refresh with AutoActivate=trueAuto-applies on completion — same effect as Activate

Operations

1. List Sandbox Inventory

Endpoint: GET /services/data/v66.0/sandbox/reports

Returns a list of all sandboxes with their IDs, names, statuses, and license types.

sf api request rest "/services/data/v66.0/sandbox/reports" --method GET

See references/api-response-shapes.md for the full response shape.

Use when: User asks "show me all sandboxes", "how many sandboxes do I have", "what's the status of my sandboxes"

Key response fields:

  • sandbox.sandboxId (07E prefix) — Required for all mutation operations
  • sandbox.sandboxName — The sandbox name (top-level field)
  • sandbox.license — Developer, Developer Pro, Partial Copy, Full
  • sandbox.isPendingActivation — true if refresh is pending activation
  • sandbox.canActivate / canDelete / canDiscard — Permission flags

2. Get Sandbox Details

Endpoint: GET /services/data/v66.0/sandbox/sandboxes/{sandboxId}

Returns detailed info for a specific sandbox.

Use when: User asks about a specific sandbox's status, configuration, or metadata.

Key response fields:

  • status — Active, Pending Activation, Activating, Completed, etc.
  • isPendingActivation — true if a refresh completed and awaits user decision
  • sandboxType — Developer, DeveloperPro, PartialCopy, Full
  • sourceId — ID of the source org

3. Activate Sandbox (Apply Refresh)

Endpoint: PATCH /services/data/v66.0/sandbox/activate/{sandboxId}

CRITICAL DOMAIN RULE: This operation ONLY applies to sandboxes with a completed refresh in "Pending Activation" state. It applies the refreshed data to the sandbox. It does NOT "bring an inactive sandbox online" or "start" a sandbox.

Pre-conditions:

  • Sandbox must be in Pending Activation status
  • A refresh must have completed successfully
  • User must have ManageSandboxes permission

Before calling PATCH /activate:

  • Confirmed sandbox is in Pending Activation status via GET /sandbox/sandboxes/{id} (isPendingActivation: true)
  • Confirmed a refresh has completed successfully
  • Received explicit user confirmation — this overwrites the sandbox with the refreshed data and cannot be undone

Use when: User says "activate it", "apply the refresh", "use the latest data"

After activation: The sandbox runs with the newly refreshed production data.


4. Verify Activation

Endpoint: GET /services/data/v66.0/sandbox/sandboxes/{sandboxId}

Poll this endpoint after activation to confirm status changed to Active. This is a verification step, not a standalone user action.

Use when: Agent needs to confirm activation completed (called automatically after activate).


5. Discard Sandbox (Reject Refresh)

Endpoint: DELETE /services/data/v66.0/sandbox/discardsandbox/{sandboxId}

CRITICAL DOMAIN RULE: This operation ONLY applies to sandboxes with a completed refresh in "Pending Activation" state. It rejects the refresh — the existing sandbox continues running with its current data unchanged. It does NOT:

  • Free up licenses
  • Soft-delete or hide the sandbox
  • Reset the sandbox to match production

Pre-conditions:

  • Sandbox must be in Pending Activation status
  • A refresh must have completed

Before calling DELETE /discardsandbox:

  • Confirmed sandbox is in Pending Activation status via GET /sandbox/sandboxes/{id} (isPendingActivation: true)
  • Confirmed this is a discard (reject refresh), NOT a delete (permanent removal)
  • Received explicit user confirmation — the refresh data will be permanently lost and cannot be undone

Use when: User says "discard the refresh", "keep existing data", "don't apply the refresh", "reject the refresh"

WARNING: Discard is not reversible. The user will need to trigger a new refresh if they want fresh production data later.


6. Delete Sandbox (Permanent)

Endpoint: DELETE /services/data/v66.0/sandbox/deletesandbox/{sandboxId}

Permanently removes a sandbox and frees the license.

Pre-conditions:

  • Sandbox must exist
  • User must have ManageSandboxes permission

Before calling DELETE /deletesandbox:

  • Surfaced sandbox details (name, license, status) with user and received explicit delete approval

Use when: User says "delete this sandbox", "remove it permanently", "free up the license"

WARNING: This is irreversible. Always confirm with the user before executing. Surface the sandbox name, license, and status as a safety check.

If asked to restore a deleted sandbox: No recovery path is documented today — escalate to Support rather than guessing at one.


7. Create a New Sandbox

Creates a new sandbox from scratch. Two approaches are supported — pick based on the user's preference; default to Approach A unless the user asks for a definition file or a repeatable DX blueprint.

Pre-conditions:

  • Available license of the requested type must exist in the org
  • Sandbox name must be unique and not already in use
  • User must have ManageSandboxes permission

Before creating — always confirm first:

  • Collected Name/License; asked about that license's optional inputs (references/definition-file-approach.md)

  • Shown this confirmation summary — common fields plus the license's own fields:

    Creating a new sandbox — please confirm:

    • Name: <SandboxName>
    • Description: <Description or "(none)">
    • Create From: Production
    • License: <Developer | Developer Pro | Partial Copy | Full>
    • (plus this license's fields — see references/definition-file-approach.md)

    Feel free to change any of these before I proceed.

  • Received explicit confirmation — this consumes a license of the selected type

Approach A — Tooling API record (direct)

API: Tooling API — SandboxInfo sObject

Required inputs:

  • SandboxName — Name for the new sandbox (alphanumeric, max 10 chars)
  • LicenseType — One of: Developer, Developer_Pro, Partial_Copy, Full

Optional inputs:

  • Description — sandbox purpose
  • Features — storage upgrade: Developer→400 MB, Developer_Pro→2 GB (irreversible); not for Partial_Copy/Full
  • ApexClassId — Apex class implementing SandboxPostCopy (runs post-creation)
  • ActivationUserGroupId — Access group (default: All Active Users)
  • TemplateId / HistoryDays / CopyChatter / CopyArchivedActivities — Partial_Copy/Full-only; per-license table in references/definition-file-approach.md
# Create a Developer sandbox
sf data create record --sobject SandboxInfo --use-tooling-api --values "SandboxName='mybox' LicenseType='Developer'"

Approach B — Sandbox definition file (Salesforce CLI)

DX-native path: write a JSON definition file, then sf org create sandbox --definition-file <file> --alias <name> --target-org <org>. Prefer for a checked-in, repeatable config or name-based Apex/group references. See references/definition-file-approach.md for the JSON example, command, and field table.

After creation: A SandboxProcess record is created with Status = Processing. The sandbox copy begins immediately.

Wrong type created: Delete and recreate with the correct type.

Renaming: Not a standalone action — only takes effect via a Refresh's SandboxName input.


8. Refresh an Existing Sandbox

Refreshes a sandbox with the latest production data. Two approaches are supported — pick based on the user's preference; default to Approach A unless the user asks for a definition file.

Approach A — Tooling API record (direct)

API: Tooling API — SandboxInfo sObject (PATCH)

Refreshes by updating the existing SandboxInfo record.

Required inputs:

  • Sandbox name — to look up the SandboxInfo record ID (0GQ prefix)

Optional inputs:

  • SandboxName — New name for the refreshed sandbox (if user wants to rename it; alphanumeric, max 10 chars)
  • Description — New or updated description for the sandbox
  • AutoActivate — true to auto-activate when refresh completes (default: false)
  • Features — storage upgrade: Developer→400 MB, Developer_Pro→2 GB (irreversible); not for Partial_Copy/Full
  • ActivationUserGroupId — Access group (default: All Active Users)
  • TemplateId / HistoryDays / CopyChatter — Partial_Copy/Full-only; per-license table in references/definition-file-approach.md

Before triggering refresh — always confirm first:

  • Collected the sandbox name; asked about its license's optional inputs (references/definition-file-approach.md)

  • Shown this confirmation summary:

    Refreshing sandbox <name> — please confirm:

    • Rename to: <SandboxName or "(no change)">
    • Description: <Description or "(no change)">
    • Auto-Activate: <Yes | No (default)>
    • Sandbox Access: <ActivationUserGroupId or "All Active Users">
    • (plus this license's fields — see references/definition-file-approach.md)

    Feel free to change any of these before I proceed.

  • Received explicit confirmation — refresh overwrites the sandbox with production data; Auto-Activate=Yes applies automatically (equivalent to Activate)

Steps:

# 1. Look up SandboxInfo record Id by name
sf data query --query "SELECT Id, SandboxName, LicenseType, Description FROM SandboxInfo WHERE SandboxName = '<name>'" --use-tooling-api --json

# 2. PATCH to trigger refresh; include SandboxName/Description only if the user changed them
# Description is free text — escape any embedded single quotes (' -> \') before interpolating
sf data update record --sobject SandboxInfo --use-tooling-api --record-id <0GQ-id> --values "AutoActivate=true SandboxName='<newName>' Description='<description>'"

Approach B — Sandbox definition file (Salesforce CLI)

Refresh from the same JSON definition-file blueprint used for create, using sf org refresh sandbox --name <name> --definition-file <file> --target-org <org>. See references/definition-file-approach.md for the JSON example, command, and field table.

Pre-conditions:

  • Sandbox must exist and be in a refreshable state
  • Refresh interval must have elapsed (Developer = 1 day, Dev Pro = 1 day, Partial = 5 days, Full = 29 days)
  • User must have ManageSandboxes permission

After refresh: A new SandboxProcess record is created with Status = Processing. If AutoActivate=true, the sandbox activates automatically when done. Otherwise it enters Pending Activation state.

Refresh interval not met: State the last-refreshed date and eligible date. For a fresher copy sooner, a clone (delegated) works if a spare license exists.


9. Check License Usage

Endpoint: GET /services/data/v66.0/sandbox/licenses

Returns license capacity, usage, and remaining counts per license type — no sandbox name or ID needed.

sf api request rest "/services/data/v66.0/sandbox/licenses" --method GET

See references/api-response-shapes.md for the full response shape.

Use when: User asks "how many sandbox licenses do I have left", "what's my license usage", "can I create another Full sandbox", or before creating/refreshing a sandbox to confirm capacity exists for that licenseType.

Key response fields:

  • licenseType — DEVELOPER, DEVELOPER_PRO, PARTIAL, FULL
  • limit — Total licenses of this type
  • used — Currently allocated
  • available — Remaining (i.e. limit - used)

Create/Refresh blocked by a license limit: offer to pick an available type, free one up by deleting a stale sandbox, ask the admin for a license increase, or — if it's an expired Courtesy Full Copy — purchase/convert it.


Decision Guide for Agents

Resolve sandboxId first: by name, call GET /sandbox/reports and match sandboxName; by ID (07E prefix), call GET /sandbox/sandboxes/{sandboxId} directly — don't call /sandbox/reports.

User says...OperationKey check
"Show all my sandboxes"GET /sandbox/reports—
"What's the status of X?"GET /sandbox/reports (by name) or GET /sandbox/sandboxes/{id} (by ID)—
"Activate sandbox X"1. Resolve sandboxId<br>2. PATCH /sandbox/activate/{sandboxId}Must be isPendingActivation: true; confirm with user first
"Discard the refresh on X"1. Resolve sandboxId<br>2. DELETE /sandbox/discardsandbox/{sandboxId}Must be isPendingActivation: true; confirm with user first
"Delete sandbox X"1. Resolve sandboxId<br>2. DELETE /sandbox/deletesandbox/{sandboxId}Confirm with user first

Common Mistakes to Avoid

MistakeCorrect understanding
Using activate to "start" any sandboxActivate ONLY applies completed refreshes
Using discard to "hide" or "soft-delete"Discard ONLY rejects a pending refresh
Activating without checking status firstAlways verify isPendingActivation = true
Skipping confirmation on Create, Activate, Discard, Delete, or Refresh with AutoActivate=trueSee Irreversible Actions above — always confirm first
Offering AutoActivate during CreateRefresh-only field
Offering ApexClassId during RefreshCreate-only field
Discovery
Tags

No tags published for this skill.

Version
Latest version metadata

Version

v2026.09.24

Published

Sep 24, 2026

Category

Uncategorized

License

Apache-2.0

Source path

skills/platform-sandbox-configure

Default branch

main

Latest commit

5c7ac82

Tree SHA

d2b5791