curl --request POST \
--url https://storage.{region}.basaltic.sh/v1/snapshot-policies \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"volume": "5f8d2c1a-9b3e-4d7a-8c6f-1e2a3b4c5d6e",
"name": "nightly",
"interval_minutes": 1440,
"retention_count": 7,
"description": "Nightly snapshots of the database volume",
"retention_days": 30,
"enabled": true,
"tags": {
"environment": "production",
"team": "backend"
}
}
'import requests
url = "https://storage.{region}.basaltic.sh/v1/snapshot-policies"
payload = {
"volume": "5f8d2c1a-9b3e-4d7a-8c6f-1e2a3b4c5d6e",
"name": "nightly",
"interval_minutes": 1440,
"retention_count": 7,
"description": "Nightly snapshots of the database volume",
"retention_days": 30,
"enabled": True,
"tags": {
"environment": "production",
"team": "backend"
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
volume: '5f8d2c1a-9b3e-4d7a-8c6f-1e2a3b4c5d6e',
name: 'nightly',
interval_minutes: 1440,
retention_count: 7,
description: 'Nightly snapshots of the database volume',
retention_days: 30,
enabled: true,
tags: {environment: 'production', team: 'backend'}
})
};
fetch('https://storage.{region}.basaltic.sh/v1/snapshot-policies', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://storage.{region}.basaltic.sh/v1/snapshot-policies",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'volume' => '5f8d2c1a-9b3e-4d7a-8c6f-1e2a3b4c5d6e',
'name' => 'nightly',
'interval_minutes' => 1440,
'retention_count' => 7,
'description' => 'Nightly snapshots of the database volume',
'retention_days' => 30,
'enabled' => true,
'tags' => [
'environment' => 'production',
'team' => 'backend'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://storage.{region}.basaltic.sh/v1/snapshot-policies"
payload := strings.NewReader("{\n \"volume\": \"5f8d2c1a-9b3e-4d7a-8c6f-1e2a3b4c5d6e\",\n \"name\": \"nightly\",\n \"interval_minutes\": 1440,\n \"retention_count\": 7,\n \"description\": \"Nightly snapshots of the database volume\",\n \"retention_days\": 30,\n \"enabled\": true,\n \"tags\": {\n \"environment\": \"production\",\n \"team\": \"backend\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://storage.{region}.basaltic.sh/v1/snapshot-policies")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"volume\": \"5f8d2c1a-9b3e-4d7a-8c6f-1e2a3b4c5d6e\",\n \"name\": \"nightly\",\n \"interval_minutes\": 1440,\n \"retention_count\": 7,\n \"description\": \"Nightly snapshots of the database volume\",\n \"retention_days\": 30,\n \"enabled\": true,\n \"tags\": {\n \"environment\": \"production\",\n \"team\": \"backend\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://storage.{region}.basaltic.sh/v1/snapshot-policies")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"volume\": \"5f8d2c1a-9b3e-4d7a-8c6f-1e2a3b4c5d6e\",\n \"name\": \"nightly\",\n \"interval_minutes\": 1440,\n \"retention_count\": 7,\n \"description\": \"Nightly snapshots of the database volume\",\n \"retention_days\": 30,\n \"enabled\": true,\n \"tags\": {\n \"environment\": \"production\",\n \"team\": \"backend\"\n }\n}"
response = http.request(request)
puts response.read_body{
"snapshot_policy": {
"faults": [
{
"code": "BACKUP_FAILED",
"severity": "error",
"message": "Backup upload failed.",
"details": {},
"first_at": "2023-11-07T05:31:56Z",
"last_at": "2023-11-07T05:31:56Z",
"occurrences": 1
}
],
"id": "3c9f1b2e-6d4a-4e8b-9f1c-2a3b4c5d6e7f",
"crn": "crn:storage:sa-saopaulo-1:my-account:snapshot-policy/nightly",
"volume_id": "5f8d2c1a-9b3e-4d7a-8c6f-1e2a3b4c5d6e",
"name": "nightly",
"description": "Nightly snapshots of the database volume",
"enabled": true,
"interval_minutes": 1440,
"retention_count": 7,
"retention_days": 30,
"next_run_at": "2026-01-16T00:00:00Z",
"last_run_at": "2026-01-15T00:00:00Z",
"tags": {
"environment": "production",
"team": "backend"
},
"created_at": "2026-01-15T09:30:00Z",
"updated_at": "2026-01-15T09:30:00Z"
}
}{
"error": {
"code": "INVALID_INPUT",
"message": "Invalid request parameters",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "Authentication required",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}{
"error": {
"code": "ACCESS_DENIED",
"message": "You don't have permission to perform this action",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}{
"error": {
"code": "NOT_FOUND",
"message": "Resource not found",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}{
"error": {
"code": "INVALID_INPUT",
"message": "Invalid request parameters",
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"params": {
"instances": 2,
"pools": 0
}
}
}{
"error": {
"code": "IDEMPOTENCY_KEY_REUSED",
"message": "This Idempotency-Key was already used with a different request payload",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}{
"error": {
"code": "INTERNAL_ERROR",
"message": "An internal error occurred",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}Criar política de snapshot
Anexar uma programação de instantâneo a um volume. Um volume suporta até 16 políticas independentes, cada uma com seu próprio intervalo e retenção. As execuções sobrepostas criam instantâneos separados e cada um conta contra a cota.
O primeiro snapshot chega um interval_minutes depois — anexar uma programação não é em si uma solicitação de um snapshot. Use POST /v1/snapshots para um agora.
O que a retenção pode excluir, uma vez que uma programação também é um excluidor automático: apenas os instantâneos que essa política em si tirou. Um instantâneo feito manualmente nunca é colhido, e também não é algo de que algo depende — um instantâneo do qual um volume foi criado, incluindo uma restauração ainda em execução, é ignorado e olhado novamente mais tarde. Pausar a política interrompe a exclusão, bem como a tomada, e excluir a política mantém seus instantâneos existentes. O trabalho já reivindicado antes de uma pausa ou exclusão pode ser concluída; nenhuma nova exclusão de retenção é reivindicada após essa alteração. Outras políticas continuam independentemente.
curl --request POST \
--url https://storage.{region}.basaltic.sh/v1/snapshot-policies \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"volume": "5f8d2c1a-9b3e-4d7a-8c6f-1e2a3b4c5d6e",
"name": "nightly",
"interval_minutes": 1440,
"retention_count": 7,
"description": "Nightly snapshots of the database volume",
"retention_days": 30,
"enabled": true,
"tags": {
"environment": "production",
"team": "backend"
}
}
'import requests
url = "https://storage.{region}.basaltic.sh/v1/snapshot-policies"
payload = {
"volume": "5f8d2c1a-9b3e-4d7a-8c6f-1e2a3b4c5d6e",
"name": "nightly",
"interval_minutes": 1440,
"retention_count": 7,
"description": "Nightly snapshots of the database volume",
"retention_days": 30,
"enabled": True,
"tags": {
"environment": "production",
"team": "backend"
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
volume: '5f8d2c1a-9b3e-4d7a-8c6f-1e2a3b4c5d6e',
name: 'nightly',
interval_minutes: 1440,
retention_count: 7,
description: 'Nightly snapshots of the database volume',
retention_days: 30,
enabled: true,
tags: {environment: 'production', team: 'backend'}
})
};
fetch('https://storage.{region}.basaltic.sh/v1/snapshot-policies', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://storage.{region}.basaltic.sh/v1/snapshot-policies",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'volume' => '5f8d2c1a-9b3e-4d7a-8c6f-1e2a3b4c5d6e',
'name' => 'nightly',
'interval_minutes' => 1440,
'retention_count' => 7,
'description' => 'Nightly snapshots of the database volume',
'retention_days' => 30,
'enabled' => true,
'tags' => [
'environment' => 'production',
'team' => 'backend'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://storage.{region}.basaltic.sh/v1/snapshot-policies"
payload := strings.NewReader("{\n \"volume\": \"5f8d2c1a-9b3e-4d7a-8c6f-1e2a3b4c5d6e\",\n \"name\": \"nightly\",\n \"interval_minutes\": 1440,\n \"retention_count\": 7,\n \"description\": \"Nightly snapshots of the database volume\",\n \"retention_days\": 30,\n \"enabled\": true,\n \"tags\": {\n \"environment\": \"production\",\n \"team\": \"backend\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://storage.{region}.basaltic.sh/v1/snapshot-policies")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"volume\": \"5f8d2c1a-9b3e-4d7a-8c6f-1e2a3b4c5d6e\",\n \"name\": \"nightly\",\n \"interval_minutes\": 1440,\n \"retention_count\": 7,\n \"description\": \"Nightly snapshots of the database volume\",\n \"retention_days\": 30,\n \"enabled\": true,\n \"tags\": {\n \"environment\": \"production\",\n \"team\": \"backend\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://storage.{region}.basaltic.sh/v1/snapshot-policies")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"volume\": \"5f8d2c1a-9b3e-4d7a-8c6f-1e2a3b4c5d6e\",\n \"name\": \"nightly\",\n \"interval_minutes\": 1440,\n \"retention_count\": 7,\n \"description\": \"Nightly snapshots of the database volume\",\n \"retention_days\": 30,\n \"enabled\": true,\n \"tags\": {\n \"environment\": \"production\",\n \"team\": \"backend\"\n }\n}"
response = http.request(request)
puts response.read_body{
"snapshot_policy": {
"faults": [
{
"code": "BACKUP_FAILED",
"severity": "error",
"message": "Backup upload failed.",
"details": {},
"first_at": "2023-11-07T05:31:56Z",
"last_at": "2023-11-07T05:31:56Z",
"occurrences": 1
}
],
"id": "3c9f1b2e-6d4a-4e8b-9f1c-2a3b4c5d6e7f",
"crn": "crn:storage:sa-saopaulo-1:my-account:snapshot-policy/nightly",
"volume_id": "5f8d2c1a-9b3e-4d7a-8c6f-1e2a3b4c5d6e",
"name": "nightly",
"description": "Nightly snapshots of the database volume",
"enabled": true,
"interval_minutes": 1440,
"retention_count": 7,
"retention_days": 30,
"next_run_at": "2026-01-16T00:00:00Z",
"last_run_at": "2026-01-15T00:00:00Z",
"tags": {
"environment": "production",
"team": "backend"
},
"created_at": "2026-01-15T09:30:00Z",
"updated_at": "2026-01-15T09:30:00Z"
}
}{
"error": {
"code": "INVALID_INPUT",
"message": "Invalid request parameters",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "Authentication required",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}{
"error": {
"code": "ACCESS_DENIED",
"message": "You don't have permission to perform this action",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}{
"error": {
"code": "NOT_FOUND",
"message": "Resource not found",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}{
"error": {
"code": "INVALID_INPUT",
"message": "Invalid request parameters",
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"params": {
"instances": 2,
"pools": 0
}
}
}{
"error": {
"code": "IDEMPOTENCY_KEY_REUSED",
"message": "This Idempotency-Key was already used with a different request payload",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}{
"error": {
"code": "INTERNAL_ERROR",
"message": "An internal error occurred",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}storage:CreateSnapshotPolicy. Consulte permissões de armazenamento para obter a lista completa, o que cada uma abrange e um exemplo de política.Autorizações
Um token bearer OAuth 2.0, enviado como Authorization: Bearer <token>. Esta é a forma recomendada de autenticação.
Obtenha o token trocando o par de chaves de acesso de uma conta de serviço em POST /v1/oauth/token com grant_type=client_credentials. Esse é o fluxo padrão de credenciais de cliente; bibliotecas compatíveis com OAuth podem obter e renovar o token para você.
curl -s -u "$KEY_ID:$SECRET" -d grant_type=client_credentials \
https://iam.basaltic.sh/v1/oauth/token
Os tokens duram uma hora por padrão. O mesmo par de chaves de acesso também serve como credencial AWS SigV4 para o endpoint de objetos compatível com S3, que aceita somente esse método de autenticação.
Cabeçalhos
Chave opcional gerada pelo cliente que torna uma criação segura para reprodução. A reintentar uma solicitação com a mesma chave retorna o resultado original literalmente em vez de criar um recurso duplicado. A reutilização de uma chave com um corpo de solicitação diferente é rejeitada (422); uma solicitação cuja chave ainda está sendo processada retorna 409. Os registros são honrados por 24 horas. Use um UUID ou token exclusivo semelhante.
255Corpo
UUID, CRN ou nome exato do volume de propriedade da conta.
"5f8d2c1a-9b3e-4d7a-8c6f-1e2a3b4c5d6e"
Único na conta: ele nomeia a política em seu CRN. Os snapshots agendados são nomeados <policy>-<UTC timestamp>. Os nomes de recursos não devem começar com o prefixo literal crn: ou ser UUIDs (formas canônicas, compactas, entre colchetes ou urn:uuid:, em qualquer caso).
1 - 128"nightly"
Minutos entre instantâneos — um intervalo mínimo, não uma cadência exata. Uma passagem periódica leva o que foi devido e re-baseia a próxima execução de cada política no momento em que foi executada, então um snapshot aterrissa em ou após interval_minutes e nunca antes, e pode aterrissar um minuto ou dois depois quando a passagem está ocupada. Uma janela que o passe perde custa um instantâneo em vez de produzir uma explosão de recuperação depois.
O limite mínimo é de um minuto, porque é esse tempo que avalia o calendário e nada mais fino pode ser honrado; o limite máximo é de 30 dias. Intervalos sub-horais multiplicam o churn de snapshots e contam contra a cota de snapshots, então escolha o maior intervalo que atenda ao seu objetivo de ponto de recuperação.
1 <= x <= 432001440
Quantos instantâneos dessa política devem ser mantidos. Quando um incêndio leva a contagem além disso, o mais velho vai primeiro.
1 <= x <= 2567
"Nightly snapshots of the database volume"
Limite de idade opcional, aplicado em cima de retention_count: um instantâneo fora da janela EITHER é colhido. 0 significa sem idade limitada. O único snapshot mais recente está isento do limite de idade, portanto, um volume que não pode ser capturado por mais tempo do que a janela nunca perde todo o seu histórico.
0 <= x <= 365030
Padrões para true. Defina false para anexar uma programação pausada. A pausa interrompe toda a política — nenhum instantâneo é tirado e nenhum é excluído, porque uma programação pausada que continuava colhendo excluiria o histórico enquanto você estava olhando para ele.
true
Show child attributes
Show child attributes
{
"environment": "production",
"team": "backend"
}
Resposta
Política de snapshot criada
Um cronograma anexado a um volume: tirar um instantâneo a cada interval_minutes, em seguida, manter no máximo retention_count dos instantâneos criados por essa política.
A retenção só apaga instantâneos criados pela própria política (aqueles que carregam seu snapshot_policy_id) — um instantâneo feito manualmente nunca é removido. Ele também nunca exclui um instantâneo do qual algo depende: um instantâneo do qual um volume foi criado, incluindo uma restauração ainda em andamento, é ignorado e reexaminado mais tarde.
Show child attributes
Show child attributes

