Silk Echo offers a powerful solution for creating application-consistent or crash-consistent snapshots of databases.
With silk, you can capture application-consistent state of a database on one host with precision and reliability. These snapshots can then be used to create an identical copy of the database on a different host. The process is flexible, allowing you to perform it manually for specific needs or integrate it into automated workflows to streamline operations. This ensures consistent, efficient, and error-free database replication.
For rapid data capture, crash-consistent snapshots offer a fast and reliable way to preserve system state instantly. These snapshots enable quick recovery from failures or disaster scenarios. However, since they do not ensure application-level consistency, databases and transactional applications may require log replay or application-consistent snapshots for full data integrity.
- Installed Flex.
- Source host running Windows Server with MSSQL and the original database.
- Destination host running Windows Server with MSSQL.
- Hosts must be capable of communicating with the Flex server and the SDP rest API.
- You'l need Silk VSS installed (on both sides) if you're doing app-consistent operations on MSSQL2019 .
- Register the "source" host server in Flex (the server that holds the original MSSQL database).
- Install Silk Agent on the "source" host.
- Register the "destination" host server in Flex (the server where Flex will restore the database).
- Install Silk Agent on the "destination" host.
After preparing the hosts, you can clone a database from the source host to the destination host:
- (Optional) Use the Echo API to discover registered hosts and their existing databases.
- Call Flex to clone a database from the "source" host to the "destination" host.
Most of these actions are long-running operations and can be monitored via the "tasks" API calls.
Flex uses Bearer Token Authentication.
curl -XGET "http://{flex}/{path}" -H "Authorization: Bearer {token}"The authentication token is obtained while registering host in Flex.
A unique header parameter can be set, this will make it easier to track operations.
hs-ref-id(string): Keep it short, 6-8 characters. Format:[a-zA-Z0-9].
curl -XGET "http://{flex}/{path}" -H "hs-ref-id: Hy6f50Ki"| Method | Path | Description |
|---|---|---|
| GET | /api/echo/v1/topology | Retrieve the full "host > db > snapshot" topology |
| Method | Path | Description |
|---|---|---|
| PUT | /api/v1/hosts/{host_id} | Register a host |
| DELETE | /api/v1/hosts/{host_id} | Unregister a host |
| GET | /api/v1/hosts/{host_id} | Retrieve host info |
| GET | /api/v1/hosts | Get all registered hosts info |
| GET | /api/v1/hosts/{host_id}/databases | List host databases |
| GET | /api/v1/hosts/{host_id}/databases/{db_id} | Get database details |
| Method | Path | Description |
|---|---|---|
| POST | /api/echo/v1/hosts/{host_id}/databases/_refresh | replaces host dbs with dbs from a snapshot |
| Method | Path | Description |
|---|---|---|
| POST | /api/echo/v1/echo_dbs | Create a snapshot and clone it to a destination host |
| DELETE | /api/echo/v1/echo_dbs | Delete a clone |
| Method | Path | Description |
|---|---|---|
| GET | /api/echo/v1/db_snapshots | List all snapshots |
| POST | /api/echo/v1/db_snapshots | Create a snapshot |
| DELETE | /api/echo/v1/db_snapshots/{id} | Delete a snapshot |
| POST | /api/echo/v1/db_snapshots/{id}/echo_db | Clone a database from an existing snapshot to a host |
| Method | Path | Description |
|---|---|---|
| GET | /api/echo/v1/tasks/{id} | Retrieve task info |
| GET | /api/echo/v1/tasks | Get all registered tasks info |
PUT /api/v1/hosts/{host_id}
{
"db_vendor": "mssql"
}-
host_id(string): The unique identifier for the host, typically the hostname. Must:- Start with a letter and end with a letter or number.
- Only contain letters, numbers, underscores, and hyphens.
- Be 3-32 characters in length.
Example pattern:
^[a-zA-Z][a-zA-Z0-9_-]+[a-zA-Z0-9]$ -
db_vendor(string): The database vendor for the host. Currently, onlymssqlis supported.
curl -XPUT "http://{flex}/api/v1/hosts/{host_id}" \
-H "Authorization: Bearer {token}" \
-d'{"db_vendor": "mssql"}' \-
201 Created
{ "host_id": "host_id", "db_vendor": "mssql", "token": "vd8iofbhsdohodxhgdx" }Notice: The token is used to authenticate the host, you need to store it securely and use it when installing Silk Agent.
-
409 Conflict
Host already exists.
DELETE /api/v1/hosts/{host_id}
-
204 No Content
The host was successfully unregistered (or did not exist).
curl -XDELETE "http://{flex}/api/v1/hosts/{host_id}" \
-H "Authorization: Bearer {token}"GET /api/v1/hosts/{host_id}
-
200 OK
{ "host_id": "host01", "db_vendor": "mssql", "last_seen_ts": 1722841284, "host_name": "host_wfGIWX4", "host_iqn": "iqn.2009-01.com.kaminario:initiator.host_wfGIWX4", "host_os": "Windows", "host_os_version": "Windows 10", "agent_version": "0.1.0", "cloud_vendor": "AZURE" } -
404 Not Found
Host does not exist.
curl -XGET "http://{flex}/api/v1/hosts/{host_id}" \
-H "Authorization: Bearer {token}"GET /api/v1/hosts
-
200 OK
[ { "host_id": "host01", "db_vendor": "mssql", "last_seen_ts": 1722841284, "host_name": "host_wfGIWX4", "host_iqn": "iqn.2009-01.com.kaminario:initiator.host_wfGIWX4", "host_os": "Windows", "host_os_version": "Windows 10", "agent_version": "0.1.0", "cloud_vendor": "AZURE" } ] -
204 No Content
No hosts are registered.
curl -XGET "http://{flex}/api/v1/hosts" \
-H "Authorization: Bearer {token}"List all databases on a specific host.
GET /api/v1/hosts/{host_id}/databases
host_id(string): The unique identifier for the host.
-
200 OK
[ { "id": "5", "host_id": "host01", "name": "analytics", "vendor": "mssql", "status": "ONLINE", "mssql": { "files": [ { "name": "analytics", "file_id": 1, "kind": "data", "path": "E:\\Data\\analytics.mdf", "size_mb": 1024, "backup_status": "ACTIVE" }, { "name": "analytics_log", "file_id": 2, "kind": "log", "path": "F:\\Logs\\analytics_log.ldf", "size_mb": 256, "backup_status": "ACTIVE" } ] }, "mount_points": [ { "kind": "disk", "path": "E:\\", "serial": "ABC123" }, { "kind": "disk", "path": "F:\\", "serial": "DEF456" } ] } ] -
200 OK (empty array if no databases)
[]
curl -XGET "http://{flex}/api/v1/hosts/host01/databases" \
-H "Authorization: Bearer {token}"Retrieve details of a specific database on a host.
GET /api/v1/hosts/{host_id}/databases/{db_id}
host_id(string): The unique identifier for the host.db_id(string): The unique identifier for the database.
-
200 OK
{ "id": "5", "host_id": "host01", "name": "analytics", "vendor": "mssql", "status": "ONLINE", "mssql": { "files": [ { "name": "analytics", "file_id": 1, "kind": "data", "path": "E:\\Data\\analytics.mdf", "size_mb": 1024, "backup_status": "ACTIVE" }, { "name": "analytics_log", "file_id": 2, "kind": "log", "path": "F:\\Logs\\analytics_log.ldf", "size_mb": 256, "backup_status": "ACTIVE" } ] }, "mount_points": [ { "kind": "disk", "path": "E:\\", "serial": "ABC123" }, { "kind": "disk", "path": "F:\\", "serial": "DEF456" } ] } -
404 Not Found
Database does not exist on the specified host.
curl -XGET "http://{flex}/api/v1/hosts/host01/databases/5" \
-H "Authorization: Bearer {token}"Takes a snapshot of a database located on host A and creates a copy on one or more hosts.
POST /api/echo/v1/echo_dbs
The request can be validated without actually being executed, by calling the same request with "/__validate" at the end of the endpoint
POST /api/echo/v1/echo_dbs/__validate
{
"source_host_id": "host02",
"destinations": [
{
"host_id": "host03",
"db_id": "5",
"db_name": "employees_copy_05"
},
{
"host_id": "host06",
"db_id": "5",
"db_name": "employees_copy_06"
}
],
"name_prefix": "snap_v10",
"consistency_level": "crash",
"target_state": "online"
}source_host_id(string, required): The unique identifier for the source host. Must not be empty.destinations(array of objects, required): A list of objects detailing the destination databases. Must not be empty.host_id(string): The unique identifier for the destination host.db_id(string): The unique identifier of the database to clone.db_name(string): The name of the destination database.
name_prefix(string, optional): The prefix for the snapshot name. Default:"snap".- Must start with a lowercase letter
- Can contain lowercase letters, numbers, underscores, and hyphens
- Length: 4-20 characters
- Pattern:
^[a-z][a-z0-9_-]+$
consistency_level(string, optional): The consistency level for the snapshot. Default:"application".- Possible values:
crash,application
- Possible values:
target_state(string, optional): The target state for the cloned database. Default:"online".- Possible values:
recovery,online
- Possible values:
force_vss_usage(boolean, optional): Force the use of VSS for snapshot creation. Default:false.
-
200 OK
{ "state": "completed", "create_ts": 1735025889, "update_ts": 1735025908, "request_id": "Fj3U7QTsDDWL45ikk0bvk2tsanfC3H", "owner": "ocie-0", "command_type": "CreateCloneCommand", "ref_id": "ADD62kMoLB", "error": "", "result": { "db_snapshot": {"id": "primary__5__1735025906"}, "cloned_dbs": [ { "id": "7", "name": "dev_db_copy_01", "host_id": "host02", "source_host_id": "host01", "source_db_id": 5, "source_db_name": "dev_db" } ] }, "location": "/api/echo/v1/tasks/Fj3U7QTsDDWL45ikk0bvk2tsanfC3H" }state(string): The task state. Possible values:running,completed,failed,aborted.create_ts(integer): The timestamp when the task was created.update_ts(integer): The timestamp of the last task state update.request_id(string): The original request ID.owner(string): The Flex owner of the task.command_type(string): The type of the task.ref_id(string): The reference ID to track the operation.error(string): Any error message.result(object): Information about the created clones.location(string): URL to query the task state.
All validation responses come with the identical format:
{
"valid":true/false,
"issues":[
{
"issue_type": "CODE OF THE ISSUE",
"description": "textual description",
"body": {} // optional. additional data in {key: value} format
}
]
}
-
200 OK
{ "valid":true, "issues":[] }
-
200 OK
{ "valid":false, "issues":[ { "issue_type": "DB_NAME_IS_IN_USE", "description": "host_id='da39-n10li-5'. db names already in use: full_db_3", "body": {} } ] }
# This example uses default values for optional parameters:
# - name_prefix defaults to "snap"
# - consistency_level is explicitly set to "crash" (default is "application")
# - target_state defaults to "online"
# - force_vss_usage defaults to false
curl -XPOST "http://{flex}/api/echo/v1/echo_dbs" \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer {token}" \
-d'{
"source_host_id": "host01",
"destinations": [
{
"host_id": "host02",
"db_id": "5",
"db_name": "employees_copy_05"
}
],
"consistency_level": "crash"
}'Delete a Cloned DB from a host and related thin volumes from the SDP.
The request can be validated without actually being executed, by calling the same request with "/__validate" at the end of the endpoint
DELETE /api/echo/v1/echo_dbs
DELETE /api/echo/v1/echo_dbs/__validate
{
"host_id":"dev-2",
"database_id":"6"
}host_id(string): The unique identifier for the host to delete from.database_id(string): The unique identifier for the database to delete.
- 202 OK
{ "state":"running", "create_ts":1722841284, "update_ts":1722841284, "request_id":"1GUQEnC1fk3sQCc0BHTpFseyB8PfUaS51_lD3iPaRP4", "owner":"ocie-0", "command_type":"DeleteCommand", "ref_id":"592855db", "error":"", "result":null, "location":"/api/echo/v1/tasks/1GUQEnC1fk3sQCc0BHTpFseyB8PfUaS51_lD3iPaRP4" }
curl -XDELETE "http://{flex}/api/echo/v1/echo_dbs" -H 'Content-Type: application/json' -H 'Authorization: Bearer {token}' -d'{"host_id":"dev-2","database_id":"6"}'This api will replace underline volumes of the selected databases with an new volumes. The new volumes are cloned from a desired snapshot.
In case of keep_backup is true. The original database is renamed to a new name
<db_name>_bkp_<timestamp>
db_name: is an original db name timestamp: The time of the refresh. The timestamp is in ISO 8601 format. "20250216T143521Z"
fin-db => fin-db_bkp_20250216T143521Z
POST /api/echo/v1/hosts/{host_id}/databases/_refresh
POST /api/echo/v1/hosts/{host_id}/databases/_refresh/__validate
{
"snapshot_id": "string",
"db_names": [
"string"
],
"keep_backup": true,
"target_state": "online"
}-
host_id(string, required): The unique identifier for the host, typically the hostname. Must:- Start with a letter and end with a letter or number.
- Only contain letters, numbers, underscores, and hyphens.
- Be 3-32 characters in length.
Example pattern:
^[a-zA-Z][a-zA-Z0-9_-]+[a-zA-Z0-9]$ -
snapshot_id(string, required): The unique identifier for the database snapshot. -
db_names(array of strings, required): The names of the databases on the host to be replaced. -
keep_backup(boolean, optional): If set to true, Flex will rename the original db to{name}_bkp_{timestamp}instead of deletion. Default:false.- Note: Requires special permissions on the host.
-
target_state(string, optional): The target state for the refreshed database. Default:"online".- Possible values:
recovery,online
- Possible values:
curl -XPOST "http://{flex}/api/echo/v1/hosts/{host_id}/databases/_refresh" \
-H "Authorization: Bearer {token}" \
-d'{"snapshot_id":"snap_1735025906","db_names": ["dev_db","dev_db2"],"keep_backup":true}'Following response example has a result field. This field will have a value only after operation completion. See: Task State APIs
-
200 OK
{ "state": "completed", "create_ts": 1735025889, "update_ts": 1735025908, "request_id": "Gm9X2VpqAZNY78sjl5cwRbPfKtoQ6B", "owner": "ocie-0", "command_type": "ReplaceDBCommand", "ref_id": "HHudu8s", "error": "", "result": { "cloned_dbs": [{ "id": "dest_db_id", "name": "dest_db_name", "host_id": "host_id", "source_host_id": "source_host_id", "source_db_id": "source_db_id", "source_db_name": "source_db_name" }] }, "location": "/api/echo/v1/tasks/Gm9X2VpqAZNY78sjl5cwRbPfKtoQ6B" }
Retrieve all database snapshots.
GET /api/echo/v1/db_snapshots
-
200 OK
[ { "id": "primary__5__1735025906", "host_id": "primary", "host_name": "primary", "sdp_id": "sdp-001", "vg_snapshot_ids": [101, 102], "databases": [ { "db_id": "5", "db_name": "analytics" }, { "db_id": "6", "db_name": "reporting" } ], "timestamp": 1735025906, "consistency_level": "application", "db_engine_version": "16.0.1000.6", "is_vss_based": true }, { "id": "daily_1735100000", "host_id": "primary", "host_name": "primary", "sdp_id": "sdp-001", "vg_snapshot_ids": [103], "databases": [ { "db_id": "7", "db_name": "inventory" } ], "timestamp": 1735100000, "consistency_level": "crash", "db_engine_version": "16.0.1000.6", "is_vss_based": false } ] -
200 OK (empty array if no snapshots)
[]
id(string): The unique identifier for the snapshot.host_id(string): The identifier of the host where the snapshot was taken.host_name(string): The name of the host.sdp_id(string): The SDP identifier associated with the snapshot.vg_snapshot_ids(array of integers): Volume group snapshot identifiers.databases(array of objects): List of databases included in the snapshot.db_id(string): The database identifier.db_name(string): The database name.
timestamp(integer): Unix timestamp when the snapshot was created.consistency_level(string): The consistency level. Values:crash,application.db_engine_version(string): The database engine version.is_vss_based(boolean): Whether the snapshot was created using VSS.
curl -XGET "http://{flex}/api/echo/v1/db_snapshots" \
-H "Authorization: Bearer {token}"Create a snapshot of a database.
POST /api/echo/v1/db_snapshots
The request can be validated without actually being executed, by calling the same request with "/__validate" at the end of the endpoint
POST /api/echo/v1/db_snapshots/__validate
{
"source_host_id": "host01",
"database_ids": [
"5", "6"
],
"name_prefix": "snap_v10",
"consistency_level" : "crash"
}source_host_id(string, required): The unique identifier for the source host.database_ids(list of strings, required): The unique identifiers for the databases to snapshot. Must not be empty.name_prefix(string, optional): The prefix for the snapshot name. Default:"snap".- Must start with a lowercase letter
- Can contain lowercase letters, numbers, underscores, and hyphens
- Length: 4-20 characters
- Pattern:
^[a-z][a-z0-9_-]+$
consistency_level(string, optional): The consistency level for the snapshot. Default:"application".- Possible values:
crash,application
- Possible values:
force_vss_usage(boolean, optional): Force the use of VSS for snapshot creation. Default:false
-
200 OK
{ "state": "completed", "create_ts": 1735025889, "update_ts": 1735025908, "request_id": "Fj3U7QTsDDWL45ikk0bvk2tsanfC3H", "owner": "ocie-0", "command_type": "CreateDBSnapshotCommand", "ref_id": "ADD62kMoLB", "error": "", "result": {"db_snapshot": {"id": "primary__5__1735025906"}}, "location": "/api/echo/v1/tasks/Fj3U7QTsDDWL45ikk0bvk2tsanfC3H" }
curl -XPOST "http://{flex}/api/echo/v1/db_snapshots" \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer {token}" \
-d'{"source_host_id":"host01","database_ids":["5","6"],"name_prefix":"snap_v10", "consistency_level": "application"}'Clone a database from an existing snapshot to a host.
POST /api/echo/v1/db_snapshots/{db_snapshot_id}/echo_db
The request can be validated without actually being executed, by calling the same request with "/__validate" at the end of the endpoint
POST /api/echo/v1/db_snapshots/{db_snapshot_id}/echo_db/__validate
{
"destinations": [
{
"host_id": "host02",
"db_id": "5",
"db_name": "db_name"
}
],
"target_state": "online"
}db_snapshot_id(string, required): The unique identifier for the database snapshot.destinations(array of objects, required): A list of objects detailing the destination databases:host_id(string): The unique identifier for the destination host.db_id(string): The unique identifier for the database.db_name(string): The name of the destination database.
target_state(string, optional): The target state for the cloned database. Default:"online".- Possible values:
recovery,online
- Possible values:
-
200 OK
{ "state": "running", "create_ts": 1735049892, "update_ts": 1735049892, "request_id": "YUiQ_S3SstXXtBQhCuyYUzDws", "owner": "ocie-0", "command_type": "ImportDBSnapshotCommand", "ref_id": "asdasda", "error": "", "result": null, "location": "/api/echo/v1/tasks/YUiQ_S3SstXXtBQhCuyYUzDws" }{ "state": "completed", "create_ts": 1735049892, "update_ts": 1735049907, "request_id": "YUiQ_S3SstXXtBQhCuyYUzDws", "owner": "ocie-0", "command_type": "ImportDBSnapshotCommand", "ref_id": "asdasda", "error": "", "result": { "cloned_dbs": [ { "source_db_name": "analytics_4", "source_host_id": "primary", "name": "alala", "id": "5", "host_id": "dev-2", "source_db_id": 10 } ] }, "location": "/api/echo/v1/tasks/YUiQ_S3SstXXtBQhCuyYUzDws" }
curl -XPOST "http://{flex}/api/echo/v1/db_snapshots/primary__10__1735028786/echo_db" \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer {token}" \
-d'{"destinations":[{"host_id":"dev-2","db_id":"10","db_name":"alala"}]}'Deletes a DB Snapshot. It is only possible to delete a DB Snapshot if there are no cloned databases that were created from that snapshot.
Note that this endpoint does not create a task. A successful status code indicates that the DB Snapshot has already been deleted.
DELETE /api/echo/v1/db_snapshots/{db_snapshot_id}
The request can be validated without actually being executed, by calling the same request with "/__validate" at the end of the endpoint
DELETE /api/echo/v1/db_snapshots/{db_snapshot_id}/__validate
- 204 OK
curl -XDELETE "http://{flex}/api/echo/v1/db_snapshots/primary__10__1735028786" -H 'Authorization: Bearer {token}'Retrieve the current state of a task by ID.
GET /api/echo/v1/tasks/{request_id}
request_id(string): The unique identifier for the task.
-
200 OK
{ "state": "running", "create_ts": 1723108781, "update_ts": 1723108781, "request_id": "KscTYPMYiMUjCjJleHLauR0y", "owner": "ocie", "command_type": "DeployCommand", "ref_id": "bjGP9ygRMew", "error": "", "result": null, "location": "/api/echo/v1/tasks/KscTYPMYiMUjCjJleHLauR0y" } -
404 Not Found
curl -XGET "http://{flex}/api/echo/v1/tasks/KscTYPMYiMUjCjJleHLauR0y" \
-H "Authorization: Bearer {token}"Retrieve all tasks.
GET /api/echo/v1/tasks
-
200 OK
[ { "state": "completed", "create_ts": 1723108781, "update_ts": 1723108981, "request_id": "KscTYPMYiMUjCjJleHLauR0y", "owner": "ocie", "command_type": "DeployCommand", "ref_id": "bjGP9ygRMew", "error": "", "result": { "cloned_dbs": [ { "source_db_name": "analytics_4", "source_host_id": "primary", "name": "alala", "id": "5", "host_id": "dev-2", "source_db_id": 10 } ] }, "location": "/api/echo/v1/tasks/KscTYPMYiMUjCjJleHLauR0y" } ]
curl -XGET "http://{flex}/api/echo/v1/tasks" \
-H "Authorization: Bearer {token}"