> ## Documentation Index
> Fetch the complete documentation index at: https://gcore-doc-1894.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Set up automatic snapshot creation

export const MethodSection = ({children}) => children ?? null;

export const MethodSwitch = ({children}) => {
  const tabs = React.Children.toArray(children).map(c => {
    if (!c || !c.props) return null;
    if (c.props.id) return c;
    const inner = c.props.children;
    if (inner && inner.props && inner.props.id) return inner;
    return null;
  }).filter(Boolean);
  const firstId = tabs.length > 0 ? tabs[0].props.id : "";
  const [active, setActive] = React.useState(firstId);
  React.useEffect(() => {
    try {
      const saved = localStorage.getItem("gcore_docs_method");
      if (saved && tabs.find(t => t.props.id === saved)) {
        setActive(saved);
      }
    } catch (_) {}
  }, []);
  React.useEffect(() => {
    try {
      document.querySelectorAll("h2[id], h3[id]").forEach(heading => {
        const visible = heading.offsetParent !== null;
        document.querySelectorAll(`a[href="#${heading.id}"]`).forEach(link => {
          if (link.closest("h1,h2,h3,h4,h5,h6")) return;
          const li = link.closest("li");
          if (li) li.style.display = visible ? "" : "none";
        });
      });
    } catch (_) {}
    window.dispatchEvent(new Event("scroll"));
  }, [active]);
  const handleClick = id => {
    setActive(id);
    try {
      localStorage.setItem("gcore_docs_method", id);
    } catch (_) {}
  };
  return <div>
      <div className="not-prose flex gap-0 border-b border-zinc-200 dark:border-zinc-800 mb-8 mt-2" role="tablist">
        {tabs.map(tab => {
    const isActive = active === tab.props.id;
    return <button key={tab.props.id} role="tab" aria-selected={isActive} onClick={() => handleClick(tab.props.id)} className={["px-4 py-2 text-sm font-medium border-b-2 -mb-px transition-colors cursor-pointer", isActive ? "border-primary text-primary" : "border-transparent text-zinc-500 hover:text-zinc-800 dark:hover:text-zinc-200"].join(" ")}>
              {tab.props.label}
            </button>;
  })}
      </div>

      {tabs.map(tab => <div key={tab.props.id} style={{
    display: active === tab.props.id ? "" : "none"
  }}>
          {tab.props.children}
        </div>)}
    </div>;
};

<MethodSwitch>
  <MethodSection id="portal" label="Customer Portal">
    <p>Snapshot Schedules automate snapshot creation for selected volumes on a recurring basis. When the **Max resource count** limit is reached, the system deletes the oldest snapshot in the schedule before creating a new one, while snapshots created outside the schedule are not affected.</p>

    ## Create a snapshot schedule

    <p>At least one [volume](/cloud/virtual-instances/volumes/create-and-configure-volumes) must exist in the target region before creating a schedule.</p>

    1. In the [Gcore Customer Portal](https://portal.gcore.com), navigate to **Cloud** > **Storage** > **Snapshot Schedules**.

    <Frame>
      <img src="https://mintcdn.com/gcore-doc-1894/Dsn9N5qugAZ3zecV/images/docs/cloud/virtual-instances/snapshots/set-up-automatic-snapshot-creation/set-up-automatic-snapshot-creation-image1.png?fit=max&auto=format&n=Dsn9N5qugAZ3zecV&q=85&s=87414faef80bf7c225822ccda3a6b263" alt="Snapshot Schedules page with Create Snapshot Schedule button" width="1024" height="490" data-path="images/docs/cloud/virtual-instances/snapshots/set-up-automatic-snapshot-creation/set-up-automatic-snapshot-creation-image1.png" />
    </Frame>

    2. Click **Create Snapshot Schedule** in the page header.

    3. On the **Create Snapshot Schedule** page, enter a **Schedule name**.

    <Frame>
      <img src="https://mintcdn.com/gcore-doc-1894/Dsn9N5qugAZ3zecV/images/docs/cloud/virtual-instances/snapshots/set-up-automatic-snapshot-creation/set-up-automatic-snapshot-creation-image2.png?fit=max&auto=format&n=Dsn9N5qugAZ3zecV&q=85&s=63aef9890b165fea6dfcab2089e93580" alt="Create Snapshot Schedule form with schedule name, type, and volume fields" width="1536" height="730" data-path="images/docs/cloud/virtual-instances/snapshots/set-up-automatic-snapshot-creation/set-up-automatic-snapshot-creation-image2.png" />
    </Frame>

    4. In the **Volumes** section, open the **Select Volumes** dropdown and select one or more volumes. Both boot and regular volumes can be included.

    <Frame>
      <img src="https://mintcdn.com/gcore-doc-1894/Dsn9N5qugAZ3zecV/images/docs/cloud/virtual-instances/snapshots/set-up-automatic-snapshot-creation/set-up-automatic-snapshot-creation-image4.png?fit=max&auto=format&n=Dsn9N5qugAZ3zecV&q=85&s=6930c87e76049acbac7f6aae69453c6b" alt="Select Volumes dropdown with boot and regular volumes listed" width="1536" height="730" data-path="images/docs/cloud/virtual-instances/snapshots/set-up-automatic-snapshot-creation/set-up-automatic-snapshot-creation-image4.png" />
    </Frame>

    5. Select a **Schedule Type** and configure the timing fields that appear below it.

    <Frame>
      <img src="https://mintcdn.com/gcore-doc-1894/Dsn9N5qugAZ3zecV/images/docs/cloud/virtual-instances/snapshots/set-up-automatic-snapshot-creation/set-up-automatic-snapshot-creation-image3.png?fit=max&auto=format&n=Dsn9N5qugAZ3zecV&q=85&s=f281c0cce91bb59338b9770f16150d9e" alt="Schedule Type dropdown showing Daily, Weekly, Monthly, Yearly, and Period options" width="1536" height="730" data-path="images/docs/cloud/virtual-instances/snapshots/set-up-automatic-snapshot-creation/set-up-automatic-snapshot-creation-image3.png" />
    </Frame>

    **Daily** — set one or more times of day using the **Time** field. Click **Add time** to add additional run times.

    **Weekly** — select **Week Day** values and a **Time**. Multiple time rows can be added with **Add time**.

    <Frame>
      <img src="https://mintcdn.com/gcore-doc-1894/Dsn9N5qugAZ3zecV/images/docs/cloud/virtual-instances/snapshots/set-up-automatic-snapshot-creation/set-up-automatic-snapshot-creation-image5.png?fit=max&auto=format&n=Dsn9N5qugAZ3zecV&q=85&s=1d952617e9e1583c51f4f24762a255f0" alt="Weekly schedule fields with week day selector and time field" width="1536" height="730" data-path="images/docs/cloud/virtual-instances/snapshots/set-up-automatic-snapshot-creation/set-up-automatic-snapshot-creation-image5.png" />
    </Frame>

    **Monthly** and **Yearly** — select the calendar values shown in the form and set a **Time**.

    **Period** — in **Repeat every**, enter an interval and select the unit (for example, 7 **Days** for a weekly interval). The minimum interval is 1 hour.

    <Frame>
      <img src="https://mintcdn.com/gcore-doc-1894/Dsn9N5qugAZ3zecV/images/docs/cloud/virtual-instances/snapshots/set-up-automatic-snapshot-creation/set-up-automatic-snapshot-creation-image6.png?fit=max&auto=format&n=Dsn9N5qugAZ3zecV&q=85&s=4aaf2b567c855cd30efb31ee9dbae9cd" alt="Period schedule fields with repeat every interval and unit selector" width="1536" height="730" data-path="images/docs/cloud/virtual-instances/snapshots/set-up-automatic-snapshot-creation/set-up-automatic-snapshot-creation-image6.png" />
    </Frame>

    6. Set **Max resource count** — the maximum number of snapshots the schedule keeps at one time. When the limit is reached, the oldest snapshot in the schedule is deleted before a new one is created.

    7. Set **Retention (optional)** — the number of days after which a snapshot is deleted. Even if retention has not expired, an older snapshot may still be removed when **Max resource count** is reached.

    8. Review the **Estimated cost** panel after volumes are selected, then click **Create Schedule**.

    <p>The schedule appears on the **Snapshot Schedules** page and starts running when created.</p>

    <Info>
      Snapshot storage counts toward project quotas. If creation fails with a quota error, reduce existing snapshots or [Request](/cloud/getting-started/request-a-quota-increase).
    </Info>

    ## Disable and enable a schedule

    1. In the Customer Portal, navigate to **Cloud** > **Storage** > **Snapshot Schedules**.

    2. Click the schedule name to open its settings.

    3. Use the enable/disable control at the top of the page to pause or resume the schedule, then save the changes.

    <p>When enabled, the schedule status is **Active**.</p>

    ## Delete a schedule

    1. In the Customer Portal, navigate to **Cloud** > **Storage** > **Snapshot Schedules**.

    2. Click the three-dot icon at the end of the schedule row.

    3. Select **Delete** from the menu and confirm the action.

    <p>Deleting a schedule does not delete snapshots that were already created.</p>
  </MethodSection>

  <MethodSection id="api" label="REST API">
    <p>Snapshot Schedules take volume snapshots on a recurring cadence. The Cloud API names this resource a lifecycle policy.</p>

    <p>Create a policy with volumes and a schedule, pause it, or delete it. Deleting a policy leaves existing snapshots in place.</p>

    <Info>
      An [API token](/account-settings/api-tokens) is required, along with a
      [project ID](/api-reference/cloud/projects/list-projects),
      a [region ID](/api-reference/cloud/regions/list-regions),
      and at least one [volume](/cloud/virtual-instances/volumes/create-and-configure-volumes) in that region.
    </Info>

    <p>Set the following environment variables before running the examples:</p>

    ```bash theme={null}
    export GCORE_API_KEY="{YOUR_API_KEY}"
    export GCORE_CLOUD_PROJECT_ID="{YOUR_PROJECT_ID}"
    export GCORE_CLOUD_REGION_ID="{YOUR_REGION_ID}"
    ```

    ## Create a snapshot schedule

    <p>A policy is created in one call: name, `volume_snapshot` action, volume IDs, and a schedule. The response is the policy object — there is no task to poll.</p>

    | Parameter    | Required | Description                                        |
    | ------------ | -------- | -------------------------------------------------- |
    | `action`     | Yes      | Must be `volume_snapshot`                          |
    | `name`       | Yes      | Snapshot Schedule name                             |
    | `volume_ids` | Yes      | One or more volume UUIDs in the same region        |
    | `schedules`  | Yes      | One cron or interval schedule, up to 10 per policy |
    | `status`     | No       | `active` (default) or `paused`                     |

    <p>Schedule timing maps to the Portal schedule types as follows.</p>

    | Portal type | API `type` | Timing fields                                                       |
    | ----------- | ---------- | ------------------------------------------------------------------- |
    | Daily       | `cron`     | `hour` and `minute`                                                 |
    | Weekly      | `cron`     | `day_of_week`, `hour`, and `minute`                                 |
    | Monthly     | `cron`     | `day`, `hour`, and `minute`                                         |
    | Yearly      | `cron`     | `month`, `day`, `hour`, and `minute`                                |
    | Period      | `interval` | `weeks`, `days`, `hours`, and `minutes`. Minimum interval is 1 hour |

    <p>`max_quantity` is the Portal **Max resource count**. `retention_time.days` is optional retention. Multiple daily run times use a comma-separated `hour` value (`3,15`).</p>

    <Tabs>
      <Tab title="Python SDK">
        ```python theme={null}
        from gcore import Gcore

        client = Gcore()

        volume = next(iter(client.cloud.volumes.list()))

        policy = client.cloud.lifecycle_policies.create(
            action="volume_snapshot",
            name="daily-boot-snapshots",
            volume_ids=[volume.id],
            schedules=[
                {
                    "type": "cron",
                    "hour": "3",
                    "minute": "30",
                    "max_quantity": 7,
                    "retention_time": {"days": 14},
                }
            ],
        )
        print(policy.id, policy.status)
        ```
      </Tab>

      <Tab title="Go SDK">
        ```go theme={null}
        package main

        import (
        	"context"
        	"fmt"

        	gcore "github.com/G-Core/gcore-go"
        	"github.com/G-Core/gcore-go/cloud"
        )

        func main() {
        	client := gcore.NewClient()
        	ctx := context.Background()

        	volumes, err := client.Cloud.Volumes.List(ctx, cloud.VolumeListParams{})
        	if err != nil {
        		panic(err)
        	}

        	policy, err := client.Cloud.LifecyclePolicies.New(ctx, cloud.LifecyclePolicyNewParams{
        		Action:    cloud.LifecyclePolicyNewParamsActionVolumeSnapshot,
        		Name:      "daily-boot-snapshots",
        		VolumeIDs: []string{volumes.Results[0].ID},
        		Schedules: []cloud.LifecyclePolicyNewParamsScheduleUnion{
        			{
        				OfCron: &cloud.LifecyclePolicyNewParamsScheduleCron{
        					Hour:        gcore.String("3"),
        					Minute:      gcore.String("30"),
        					MaxQuantity: gcore.Int(7),
        					RetentionTime: cloud.LifecyclePolicyNewParamsScheduleCronRetentionTime{
        						Days: gcore.Int(14),
        					},
        				},
        			},
        		},
        	})
        	if err != nil {
        		panic(err)
        	}
        	fmt.Println(policy.ID, policy.Status)
        }
        ```
      </Tab>

      <Tab title="curl">
        ```bash theme={null}
        VOLUME_ID=$(curl -sS \
          -H "Authorization: APIKey $GCORE_API_KEY" \
          "https://api.gcore.com/cloud/v1/volumes/$GCORE_CLOUD_PROJECT_ID/$GCORE_CLOUD_REGION_ID" \
          | jq -r '.results[0].id')

        curl -X POST \
          "https://api.gcore.com/cloud/v1/lifecycle_policy/$GCORE_CLOUD_PROJECT_ID/$GCORE_CLOUD_REGION_ID" \
          -H "Authorization: APIKey $GCORE_API_KEY" \
          -H "Content-Type: application/json" \
          -d "{
            \"action\": \"volume_snapshot\",
            \"name\": \"daily-boot-snapshots\",
            \"volume_ids\": [\"$VOLUME_ID\"],
            \"schedules\": [
              {
                \"type\": \"cron\",
                \"hour\": \"3\",
                \"minute\": \"30\",
                \"max_quantity\": 7,
                \"retention_time\": {\"days\": 14}
              }
            ]
          }"
        ```

        <p>The API returns:</p>

        ```json theme={null}
        {
          "action": "volume_snapshot",
          "id": 15093,
          "name": "daily-boot-snapshots",
          "project_id": 1,
          "region_id": 1,
          "schedules": [
            {
              "id": "6859087c-a28f-4521-9a09-55a0e4dba9c4",
              "type": "cron",
              "hour": "3",
              "minute": "30",
              "max_quantity": 7,
              "retention_time": {"days": 14},
              "resource_name_template": "Snapshot of volume {volume_id} created by policy {lifecycle_policy_id}",
              "owner": "lifecycle_policy",
              "owner_id": 15093,
              "user_id": 1
            }
          ],
          "status": "active",
          "user_id": 1,
          "volumes": [
            {
              "volume_id": "3ed9e2ce-f906-47fb-ba32-c25a3f63df4f",
              "volume_name": "boot-volume"
            }
          ]
        }
        ```
      </Tab>
    </Tabs>

    <p>Save `id` as the policy ID for later calls. HTTP 400 with `MultipleQuotaLimitExceeded` means `max_quantity` plus existing snapshots exceeds the project snapshot quota.</p>

    <p>Period schedules use `"type": "interval"` with `hours`, `days`, or `weeks` instead of cron fields. Weekly cron adds `day_of_week` (`mon,fri`).</p>

    ## List snapshot schedules

    <p>The collection lists every policy in the project and region, including status, schedules, and attached volumes.</p>

    <Tabs>
      <Tab title="Python SDK">
        ```python theme={null}
        from gcore import Gcore

        client = Gcore()

        policies = client.cloud.lifecycle_policies.list()
        print(policies.count)
        for policy in policies.results:
            print(policy.id, policy.name, policy.status)
        ```
      </Tab>

      <Tab title="Go SDK">
        ```go theme={null}
        package main

        import (
        	"context"
        	"fmt"

        	gcore "github.com/G-Core/gcore-go"
        	"github.com/G-Core/gcore-go/cloud"
        )

        func main() {
        	client := gcore.NewClient()
        	ctx := context.Background()

        	policies, err := client.Cloud.LifecyclePolicies.List(ctx, cloud.LifecyclePolicyListParams{})
        	if err != nil {
        		panic(err)
        	}
        	fmt.Println(policies.Count)
        	for _, policy := range policies.Results {
        		fmt.Println(policy.ID, policy.Name, policy.Status)
        	}
        }
        ```
      </Tab>

      <Tab title="curl">
        ```bash theme={null}
        curl -X GET \
          "https://api.gcore.com/cloud/v1/lifecycle_policy/$GCORE_CLOUD_PROJECT_ID/$GCORE_CLOUD_REGION_ID" \
          -H "Authorization: APIKey $GCORE_API_KEY"
        ```

        <p>The API returns:</p>

        ```json theme={null}
        {
          "count": 1,
          "results": [
            {
              "id": 15093,
              "name": "daily-boot-snapshots",
              "status": "active",
              "action": "volume_snapshot"
            }
          ]
        }
        ```
      </Tab>
    </Tabs>

    ## Disable and enable a schedule

    <p>`paused` stops new snapshots. `active` resumes them. Existing snapshots stay in place.</p>

    <Tabs>
      <Tab title="Python SDK">
        ```python theme={null}
        from gcore import Gcore

        client = Gcore()

        policy = next(
            p
            for p in client.cloud.lifecycle_policies.list().results
            if p.name == "daily-boot-snapshots"
        )

        paused = client.cloud.lifecycle_policies.update(policy.id, status="paused")
        print(paused.status)

        active = client.cloud.lifecycle_policies.update(policy.id, status="active")
        print(active.status)
        ```
      </Tab>

      <Tab title="Go SDK">
        ```go theme={null}
        package main

        import (
        	"context"
        	"fmt"

        	gcore "github.com/G-Core/gcore-go"
        	"github.com/G-Core/gcore-go/cloud"
        )

        func main() {
        	client := gcore.NewClient()
        	ctx := context.Background()

        	listed, err := client.Cloud.LifecyclePolicies.List(ctx, cloud.LifecyclePolicyListParams{})
        	if err != nil {
        		panic(err)
        	}

        	var policyID int64
        	for _, policy := range listed.Results {
        		if policy.Name == "daily-boot-snapshots" {
        			policyID = policy.ID
        			break
        		}
        	}

        	paused, err := client.Cloud.LifecyclePolicies.Update(ctx, policyID, cloud.LifecyclePolicyUpdateParams{
        		Status: cloud.LifecyclePolicyUpdateParamsStatusPaused,
        	})
        	if err != nil {
        		panic(err)
        	}
        	fmt.Println(paused.Status)

        	active, err := client.Cloud.LifecyclePolicies.Update(ctx, policyID, cloud.LifecyclePolicyUpdateParams{
        		Status: cloud.LifecyclePolicyUpdateParamsStatusActive,
        	})
        	if err != nil {
        		panic(err)
        	}
        	fmt.Println(active.Status)
        }
        ```
      </Tab>

      <Tab title="curl">
        ```bash theme={null}
        POLICY_ID=$(curl -sS \
          -H "Authorization: APIKey $GCORE_API_KEY" \
          "https://api.gcore.com/cloud/v1/lifecycle_policy/$GCORE_CLOUD_PROJECT_ID/$GCORE_CLOUD_REGION_ID" \
          | jq -r '.results[] | select(.name=="daily-boot-snapshots") | .id')

        curl -X PATCH \
          "https://api.gcore.com/cloud/v1/lifecycle_policy/$GCORE_CLOUD_PROJECT_ID/$GCORE_CLOUD_REGION_ID/$POLICY_ID" \
          -H "Authorization: APIKey $GCORE_API_KEY" \
          -H "Content-Type: application/json" \
          -d '{"status":"paused"}'

        curl -X PATCH \
          "https://api.gcore.com/cloud/v1/lifecycle_policy/$GCORE_CLOUD_PROJECT_ID/$GCORE_CLOUD_REGION_ID/$POLICY_ID" \
          -H "Authorization: APIKey $GCORE_API_KEY" \
          -H "Content-Type: application/json" \
          -d '{"status":"active"}'
        ```

        <p>The API returns the policy. `status` is `paused` after the first call and `active` after the second.</p>

        ```json theme={null}
        {
          "id": 15093,
          "name": "daily-boot-snapshots",
          "status": "paused"
        }
        ```
      </Tab>
    </Tabs>

    ## Delete a schedule

    <p>Deleting a policy removes the schedule and its attached volume membership. Snapshots already created stay in the project.</p>

    <Tabs>
      <Tab title="Python SDK">
        ```python theme={null}
        from gcore import Gcore

        client = Gcore()

        policy = next(
            p
            for p in client.cloud.lifecycle_policies.list().results
            if p.name == "daily-boot-snapshots"
        )
        client.cloud.lifecycle_policies.delete(policy.id)
        ```
      </Tab>

      <Tab title="Go SDK">
        ```go theme={null}
        package main

        import (
        	"context"

        	gcore "github.com/G-Core/gcore-go"
        	"github.com/G-Core/gcore-go/cloud"
        )

        func main() {
        	client := gcore.NewClient()
        	ctx := context.Background()

        	listed, err := client.Cloud.LifecyclePolicies.List(ctx, cloud.LifecyclePolicyListParams{})
        	if err != nil {
        		panic(err)
        	}

        	var policyID int64
        	for _, policy := range listed.Results {
        		if policy.Name == "daily-boot-snapshots" {
        			policyID = policy.ID
        			break
        		}
        	}

        	err = client.Cloud.LifecyclePolicies.Delete(ctx, policyID, cloud.LifecyclePolicyDeleteParams{})
        	if err != nil {
        		panic(err)
        	}
        }
        ```
      </Tab>

      <Tab title="curl">
        ```bash theme={null}
        POLICY_ID=$(curl -sS \
          -H "Authorization: APIKey $GCORE_API_KEY" \
          "https://api.gcore.com/cloud/v1/lifecycle_policy/$GCORE_CLOUD_PROJECT_ID/$GCORE_CLOUD_REGION_ID" \
          | jq -r '.results[] | select(.name=="daily-boot-snapshots") | .id')

        curl -X DELETE \
          "https://api.gcore.com/cloud/v1/lifecycle_policy/$GCORE_CLOUD_PROJECT_ID/$GCORE_CLOUD_REGION_ID/$POLICY_ID" \
          -H "Authorization: APIKey $GCORE_API_KEY"
        ```

        <p>The API returns an empty 204 response.</p>
      </Tab>
    </Tabs>
  </MethodSection>
</MethodSwitch>
