NAS Cloud Direct (NCD)
NAS Cloud Direct (NCD) protects unstructured file data on Network Attached Storage using Rubrik Cloud Direct clusters. Unlike traditional NAS Unstructured Data protection — which uses CDM-managed filesets — NCD captures RSC-native snapshots and exposes a fully API-driven granular recovery flow: search and browse individual files across snapshots, then restore one file or many in a single request.
NCD vs. NAS
Both products protect file shares, but they are distinct. NAS Unstructured Data is backed by a Rubrik cluster and CDM filesets. NCD is backed by a Cloud Direct cluster, and its shares, snapshots, and recovery operations use the cloudDirect* family of GraphQL operations documented on this page.
This guide walks the full NCD lifecycle: discover your environment, assign protection, take on-demand backups, and recover individual files. System registration and other one-time setup tasks are covered in Set Up at the end.
Prerequisites
Before using the NCD API:
- Obtain an access token — See Authentication for the token exchange flow.
- Locate your SLA Domain — See SLA Domains to retrieve the UUID of the policy you will assign to your shares.
- Register the NCD system — A NAS appliance must be registered as a Cloud Direct system before its shares appear in discovery queries. If your shares are not yet visible, see Set Up.
Object Model
NCD organizes unstructured data into a three-level hierarchy:
System → Namespace → Share
| Object | Description |
|---|---|
| System | The NAS appliance registered with Rubrik — NetApp, Isilon, Qumulo, FlashBlade, VAST, Azure Files, FSxN, generic NFS/SMB/S3, and others. |
| Namespace | A logical grouping within a system, such as an SVM on NetApp. |
| Share | The snappable: an NFS export, SMB share, or S3 bucket. This is the object that gets backed up, assigned an SLA, and recovered from. |
Protection operations — SLA assignment, on-demand snapshots, and recovery — all act on the share. Capture the share FID (id) from discovery; it is the handle for everything that follows.
Discover Your NCD Environment
Shares
Use cloudDirectNasShares to list and filter shares, or cloudDirectNasShare if you already have the share FID. Either way, capture the share id and name — both are needed in the recovery flow (name is required as srcShareName).
List and filter
query {
cloudDirectNasShares(
sortBy: NAME
sortOrder: ASC
filter: [
{ field: IS_RELIC, texts: "false" }
{ field: IS_REPLICATED, texts: "false" }
]
) {
nodes {
id
name
protocol
ncdPolicyName
cloudDirectId
isStale
totalSnapshots
cloudDirectNasSystem {
id
name
vendorType
}
cloudDirectNasNamespace {
id
name
}
effectiveSlaDomain {
id
name
}
}
pageInfo {
endCursor
hasNextPage
}
}
}
$query = New-RscQuery -GqlQuery cloudDirectNasShares
$query.Var.filter = @((Get-RscType -Name Filter),(Get-RscType -Name Filter))
$query.Var.filter[0].field = [RubrikSecurityCloud.Types.HierarchyFilterField]::IS_RELIC
$query.Var.filter[0].texts = "false"
$query.Var.filter[1].field = [RubrikSecurityCloud.Types.HierarchyFilterField]::IS_REPLICATED
$query.Var.filter[1].texts = "false"
$query.field.nodes = @(Get-RscType -Name CloudDirectNasShare -InitialProperties `
id,`
name,`
protocol,`
ncdPolicyName,`
cloudDirectId,`
isRelic,`
isStale,`
totalSnapshots,`
cloudDirectNasSystem.id,cloudDirectNasSystem.name,cloudDirectNasSystem.vendorType,`
cloudDirectNasNamespace.id,cloudDirectNasNamespace.name,`
effectiveSlaDomain.id,effectiveSlaDomain.name
)
$query.Invoke().nodes
#!/bin/bash
# RSC_TOKEN="YOUR_RSC_ACCESS_TOKEN"
query="query { cloudDirectNasShares(sortBy: NAME sortOrder: ASC filter: [ {field: IS_RELIC texts: \\\"false\\\"} {field: IS_REPLICATED texts: \\\"false\\\"} ]) { nodes { id name protocol ncdPolicyName cloudDirectId isRelic isStale totalSnapshots cloudDirectNasSystem { id name vendorType } cloudDirectNasNamespace { id name } effectiveSlaDomain { id name } } pageInfo { endCursor hasNextPage } } }"
# Execute the GraphQL query with curl
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $RSC_TOKEN" \
-d "{\"query\": \"$query\"}" \
https://example.my.rubrik.com/api/graphql
See Pagination for how to page through large result sets.
By ID
query {
cloudDirectNasShare(fid: "11111111-2222-3333-4444-555555555555") {
id
name
protocol
ncdPolicyName
cloudDirectId
isRelic
isStale
totalSnapshots
newestSnapshot {
id
date
}
oldestSnapshot {
id
date
}
effectiveSlaDomain {
id
name
}
cloudDirectNasSystem {
id
name
vendorType
}
cloudDirectNasNamespace {
id
name
}
}
}
# Replace with the share FID captured from cloudDirectNasShares.
$query = New-RscQuery -GqlQuery cloudDirectNasShare
$query.Var.fid = "11111111-2222-3333-4444-555555555555"
$query.field = Get-RscType -Name CloudDirectNasShare -InitialProperties `
id,`
name,`
protocol,`
ncdPolicyName,`
cloudDirectId,`
isRelic,`
isStale,`
totalSnapshots,`
newestSnapshot.id,newestSnapshot.date,`
oldestSnapshot.id,oldestSnapshot.date,`
effectiveSlaDomain.id,effectiveSlaDomain.name,`
cloudDirectNasSystem.id,cloudDirectNasSystem.name,cloudDirectNasSystem.vendorType,`
cloudDirectNasNamespace.id,cloudDirectNasNamespace.name
$query.Invoke()
#!/bin/bash
# RSC_TOKEN="YOUR_RSC_ACCESS_TOKEN"
# Replace the fid with a share FID captured from cloudDirectNasShares.
query="query { cloudDirectNasShare(fid: \\\"11111111-2222-3333-4444-555555555555\\\") { id name protocol ncdPolicyName cloudDirectId isRelic isStale totalSnapshots newestSnapshot { id date } oldestSnapshot { id date } effectiveSlaDomain { id name } cloudDirectNasSystem { id name vendorType } cloudDirectNasNamespace { id name } } }"
# Execute the GraphQL query with curl
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $RSC_TOKEN" \
-d "{\"query\": \"$query\"}" \
https://example.my.rubrik.com/api/graphql
Systems
List the NAS appliances registered as Cloud Direct systems. The vendorType field identifies the NAS vendor (NetApp, Isilon, Qumulo, and others).
query {
cloudDirectNasSystems(filter: [
{field: NAME_EXACT_MATCH texts: "example"}
{field: IS_RELIC texts: "false"}
{field: IS_REPLICATED texts: "false"}
]) {
nodes {
name
id
cloudDirectId
vendorType
lastStatus
lastRefreshTime
osVersion
apiVersion
cluster {
name
id
}
effectiveSlaDomain {
name
id
}
}
}
}
$query = New-RscQuery -GqlQuery cloudDirectNasSystems
$query.Var.filter = @((Get-RscType -Name Filter),(Get-RscType -Name Filter))
$query.Var.filter[0].field = [RubrikSecurityCloud.Types.HierarchyFilterField]::IS_RELIC
$query.Var.filter[0].texts = "false"
$query.Var.filter[1].field = [RubrikSecurityCloud.Types.HierarchyFilterField]::IS_REPLICATED
$query.Var.filter[1].texts = "false"
$query.field.nodes = @(Get-RscType -Name CloudDirectNasSystem -InitialProperties `
name,`
id,`
vendorType,`
lastStatus,`
lastRefreshTime,`
cloudDirectId,`
cloudDirectNasSystem.name,cloudDirectNasSystem.id,`
cloudDirectNasNamespace.name,cloudDirectNasNamespace.id,`
excludes.path,excludes.pattern,`
shareCount,`
cluster.name,cluster.id
)
$query.Invoke().nodes
#!/bin/bash
# RSC_TOKEN="YOUR_RSC_ACCESS_TOKEN"
query="query { cloudDirectNasSystems(filter: [ {field: NAME_EXACT_MATCH texts: \\\"example\\\"} {field: IS_RELIC texts: \\\"false\\\"} {field: IS_REPLICATED texts: \\\"false\\\"} ]) { nodes { name id cloudDirectId vendorType lastStatus lastRefreshTime osVersion apiVersion cluster { name id } effectiveSlaDomain { name id } } } }"
# Execute the GraphQL query with curl
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $RSC_TOKEN" \
-d "{\"query\": \"$query\"}" \
https://example.my.rubrik.com/api/graphql
Namespaces
List namespaces within your Cloud Direct systems.
$query = New-RscQuery -GqlQuery cloudDirectNasNamespaces
$query.Var.filter = @((Get-RscType -Name Filter),(Get-RscType -Name Filter))
$query.Var.filter[0].field = [RubrikSecurityCloud.Types.HierarchyFilterField]::IS_RELIC
$query.Var.filter[0].texts = "false"
$query.Var.filter[1].field = [RubrikSecurityCloud.Types.HierarchyFilterField]::IS_REPLICATED
$query.Var.filter[1].texts = "false"
$query.field.nodes = @(Get-RscType -Name CloudDirectNasNamespace -InitialProperties `
name,`
id,`
cloudDirectId,`
cloudDirectNasSystem.name,cloudDirectNasSystem.id,`
shareCount,`
cluster.name,cluster.id,`
effectiveSlaDomain.name,effectiveSlaDomain.id
)
$query.Invoke().nodes
#!/bin/bash
# RSC_TOKEN="YOUR_RSC_ACCESS_TOKEN"
query="query { cloudDirectNasNamespaces(filter: [ {field: NAME_EXACT_MATCH texts: \\\"example\\\"} {field: IS_RELIC texts: \\\"false\\\"} {field: IS_REPLICATED texts: \\\"false\\\"} ]) { nodes { name id cloudDirectId cloudDirectNasSystem { name id } shareCount cluster { name id } effectiveSlaDomain { name id } } } }"
# Execute the GraphQL query with curl
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $RSC_TOKEN" \
-d "{\"query\": \"$query\"}" \
https://example.my.rubrik.com/api/graphql
Configure Protection
Protect a share by assigning it an SLA Domain. NCD uses the generic assignSla mutation — pass the share FID as the object ID. See Assigning an SLA to a workload for the assignment flow and code samples.
NCD SLA Domains specify backup targets per frequency
An NCD SLA Domain must declare which backup target each retention frequency writes to — minutelyBackupLocations, hourlyBackupLocations, dailyBackupLocations, and so on are set in the SLA definition. This is configured when you create or update the SLA Domain, not at assignment time. See Creating an SLA Domain for the full SLA definition.
On-Demand Backup
Trigger an immediate snapshot of a share with takeCloudDirectSnapshot, outside the SLA schedule.
| Field | Description |
|---|---|
objectFid |
Required. The FID of the share to snapshot. |
slaId |
Optional. Omit to use the share's assigned SLA, or provide a different SLA ID to override retention for this snapshot. |
exclusions |
Optional. A list of { path, pattern } entries to skip during this backup. |
Returns a list of statuses, not one
takeCloudDirectSnapshot returns a BatchAsyncRequestStatus — a responses list of AsyncRequestStatus, not a single status. A single share can fan out to multiple snapshot jobs, one per backup target defined in its SLA. Iterate responses and poll each id to track every job to completion.
# Take an on-demand snapshot of a share.
# Omit slaId to use the share's assigned SLA, or set it to override for this snapshot.
# exclusions is optional — each entry has a path and/or pattern to skip.
mutation {
takeCloudDirectSnapshot(input: {
objectFid: "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
slaId: "11111111-2222-3333-4444-555555555555"
exclusions: [
{ path: "/finance/tmp" }
{ pattern: "*.bak" }
]
}) {
responses {
id
status
}
}
}
# Take an on-demand snapshot of a share.
# Omit slaId to use the share's assigned SLA, or set it to override for this snapshot.
$query = New-RscMutation -GqlMutation takeCloudDirectSnapshot
$exclusion = Get-RscType -Name CloudDirectExclusionInput
$exclusion.pattern = "*.bak"
$query.Var.input = Get-RscType -Name TakeCloudDirectSnapshotInput
$query.Var.input.objectFid = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
$query.Var.input.slaId = "11111111-2222-3333-4444-555555555555"
$query.Var.input.exclusions = @($exclusion)
# takeCloudDirectSnapshot returns a BatchAsyncRequestStatus — a list of
# AsyncRequestStatus, one per backup target a share fans out to.
$query.field.responses = @(Get-RscType -Name AsyncRequestStatus -InitialProperties id,status)
$query.Invoke().responses
#!/bin/bash
# RSC_TOKEN="YOUR_RSC_ACCESS_TOKEN"
# Take an on-demand snapshot of a share. Omit slaId to use the share's assigned SLA.
query="mutation TakeCloudDirectSnapshot(\$input: TakeCloudDirectSnapshotInput!) { takeCloudDirectSnapshot(input: \$input) { responses { id status } } }"
read -r -d '' variables <<'JSON'
{
"input": {
"objectFid": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"slaId": "11111111-2222-3333-4444-555555555555",
"exclusions": [
{ "path": "/finance/tmp" },
{ "pattern": "*.bak" }
]
}
}
JSON
# Execute the GraphQL mutation with curl
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $RSC_TOKEN" \
-d "$(jq -n --arg q "$query" --argjson v "$variables" '{query: $q, variables: $v}')" \
https://example.my.rubrik.com/api/graphql
Granular Recovery
List Snapshots
List the snapshots of a share to choose the point in time to recover from. Sort by CREATION_TIME descending to get the most recent snapshot first.
workloadId is a String, not a UUID
snapshotsOfCloudDirectShare takes workloadId: String!. The share FID must be passed as a quoted string literal — the field does not accept the UUID scalar type.
# workloadId is the share FID passed as a String (not a UUID scalar).
query {
snapshotsOfCloudDirectShare(
workloadId: "11111111-2222-3333-4444-555555555555"
sortBy: CREATION_TIME
sortOrder: DESC
) {
nodes {
id
date
expirationDate
protocol
isIndexed
isQuarantined
isExpired
isOnDemandSnapshot
}
pageInfo {
endCursor
hasNextPage
}
}
}
# workloadId is the share FID passed as a String (not a UUID type).
$query = New-RscQuery -GqlQuery snapshotsOfCloudDirectShare
$query.Var.workloadId = "11111111-2222-3333-4444-555555555555"
$query.Var.sortOrder = [RubrikSecurityCloud.Types.SortOrder]::DESC
$query.Var.sortBy = [RubrikSecurityCloud.Types.SnapshotQuerySortByField]::CREATION_TIME
$query.field.nodes = @(Get-RscType -Name CloudDirectSnapshot -InitialProperties `
id,`
date,`
expirationDate,`
protocol,`
isIndexed,`
isQuarantined,`
isExpired,`
isOnDemandSnapshot
)
$query.Invoke().nodes
#!/bin/bash
# RSC_TOKEN="YOUR_RSC_ACCESS_TOKEN"
# workloadId is the share FID passed as a String. Replace before running.
query="query { snapshotsOfCloudDirectShare(workloadId: \\\"11111111-2222-3333-4444-555555555555\\\" sortBy: CREATION_TIME sortOrder: DESC) { nodes { id date expirationDate protocol isIndexed isQuarantined isExpired isOnDemandSnapshot } pageInfo { endCursor hasNextPage } } }"
# Execute the GraphQL query with curl
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $RSC_TOKEN" \
-d "{\"query\": \"$query\"}" \
https://example.my.rubrik.com/api/graphql
Capture the id of the target snapshot — this is the snapshotFid used in recovery.
Search Files
When you know a filename or path prefix but not which snapshot contains it, search the entire share at once. searchSnappableVersionedFiles returns each matching file with its fileVersions — one entry per snapshot that contains a version of the file.
# snappableFid is the share FID. searchQuery is a filename or path prefix.
$query = New-RscQuery -GqlQuery searchSnappableVersionedFiles
$query.Var.snappableFid = "11111111-2222-3333-4444-555555555555"
$query.Var.searchQuery = "quarterly-report"
$query.Var.usePrefixSearch = $true
$query.field.nodes = @(Get-RscType -Name VersionedFile -InitialProperties `
filename,`
absolutePath,`
displayPath,`
fileVersions.snapshotId,fileVersions.size,fileVersions.lastModified,fileVersions.fileMode
)
$query.Invoke().nodes
#!/bin/bash
# RSC_TOKEN="YOUR_RSC_ACCESS_TOKEN"
# snappableFid is the share FID. searchQuery is a filename or path prefix.
query="query { searchSnappableVersionedFiles(snappableFid: \\\"11111111-2222-3333-4444-555555555555\\\" searchQuery: \\\"quarterly-report\\\" usePrefixSearch: true) { nodes { filename absolutePath displayPath fileVersions { snapshotId size lastModified fileMode } } pageInfo { endCursor hasNextPage } } }"
# Execute the GraphQL query with curl
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $RSC_TOKEN" \
-d "{\"query\": \"$query\"}" \
https://example.my.rubrik.com/api/graphql
searchQuery matches against filenames and paths. Set usePrefixSearch: true to match on a leading path or name fragment. Capture the file's absolutePath (use it as srcPath) and the fileVersions.snapshotId of the version you want.
Browse a Snapshot
To explore a snapshot directory-by-directory, use browseSnapshotFileConnection. Start at the root path and re-issue the query with a directory's displayPath to descend into it. The fileMode field distinguishes files from directories.
# snapshotFid is captured from snapshotsOfCloudDirectShare.
# Use "/" to browse the snapshot root, then drill into a directory's displayPath.
$query = New-RscQuery -GqlQuery browseSnapshotFileConnection
$query.Var.snapshotFid = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
$query.Var.path = "/"
$query.field.nodes = @(Get-RscType -Name SnapshotFile -InitialProperties `
filename,`
absolutePath,`
displayPath,`
fileMode,`
size,`
lastModified
)
$query.Invoke().nodes
#!/bin/bash
# RSC_TOKEN="YOUR_RSC_ACCESS_TOKEN"
# snapshotFid is captured from snapshotsOfCloudDirectShare.
# Use "/" to browse the root, then drill into a directory's displayPath.
query="query { browseSnapshotFileConnection(snapshotFid: \\\"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\\\" path: \\\"/\\\") { nodes { filename absolutePath displayPath fileMode size lastModified } pageInfo { endCursor hasNextPage } } }"
# Execute the GraphQL query with curl
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $RSC_TOKEN" \
-d "{\"query\": \"$query\"}" \
https://example.my.rubrik.com/api/graphql
Recover Files
recoverCloudDirectNasShare restores one or more files from a snapshot in a single request. Recovery targets are described by restorePathPairList — a list of { srcPath, dstPath } pairs.
| Field | Description |
|---|---|
snapshotFid |
Snapshot to restore from. |
srcShareName |
name of the source share (from the share details query). |
srcPath |
Absolute path of the file or directory to restore. |
dstPath |
Where to restore it. Empty string overwrites the source path in place. |
Two optional fields are also available: destShareFid to restore to a different NCD share, and aclOnly: true to restore only file permissions without content.
Single file
# An empty dstPath overwrites the source path in place.
# Provide a non-empty dstPath to restore to an alternate location.
mutation {
recoverCloudDirectNasShare(input: {
snapshotFid: "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
srcShareName: "/finance"
restorePathPairList: [
{ srcPath: "/finance/quarterly-report.xlsx", dstPath: "" }
]
}) {
id
status
}
}
# Restore a single file from a snapshot.
# An empty dstPath overwrites the source path in place.
$query = New-RscQuery -GqlQuery recoverCloudDirectNasShare
$pathPair = Get-RscType -Name NascdRestorePathPairInput
$pathPair.srcPath = "/finance/quarterly-report.xlsx"
$pathPair.dstPath = ""
$query.Var.input = Get-RscType -Name RecoverCloudDirectNasShareInput
$query.Var.input.snapshotFid = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
$query.Var.input.srcShareName = "finance-share"
$query.Var.input.restorePathPairList = @($pathPair)
$query.field = Get-RscType -Name AsyncRequestStatus -InitialProperties id,status
$query.Invoke()
#!/bin/bash
# RSC_TOKEN="YOUR_RSC_ACCESS_TOKEN"
# Restore a single file. An empty dstPath overwrites the source path in place.
query="mutation RecoverCloudDirectNasShare(\$input: RecoverCloudDirectNasShareInput!) { recoverCloudDirectNasShare(input: \$input) { id status } }"
read -r -d '' variables <<'JSON'
{
"input": {
"snapshotFid": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"srcShareName": "finance-share",
"restorePathPairList": [
{ "srcPath": "/finance/quarterly-report.xlsx", "dstPath": "" }
]
}
}
JSON
# Execute the GraphQL mutation with curl
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $RSC_TOKEN" \
-d "$(jq -n --arg q "$query" --argjson v "$variables" '{query: $q, variables: $v}')" \
https://example.my.rubrik.com/api/graphql
Multiple files
Add an entry to restorePathPairList for each file. This is the "shopping cart" pattern: collect files from search or browse, then restore them in a single request.
restorePathPairList constraints
- All
srcPathvalues must come from the same snapshot (snapshotFid). srcPathvalues must not overlap — you cannot restore both a directory and a file nested inside it in the same request.- All
dstPathvalues must be identical — a single destination directory — or all empty to overwrite each file in place. Mixing distinct destinations is not allowed.
# All dstPath values must be identical (same destination directory).
# All srcPaths must come from the same snapshot and must not overlap.
mutation {
recoverCloudDirectNasShare(input: {
snapshotFid: "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
srcShareName: "/finance"
restorePathPairList: [
{ srcPath: "/finance/quarterly-report.xlsx", dstPath: "/restored/2026-06-15" }
{ srcPath: "/finance/budget.csv", dstPath: "/restored/2026-06-15" }
]
}) {
id
status
}
}
# Shopping-cart restore: multiple files in one request.
# All srcPaths must come from the same snapshot and must not overlap.
# All dstPaths must be identical (one destination directory) or all empty.
$query = New-RscQuery -GqlQuery recoverCloudDirectNasShare
$pair1 = Get-RscType -Name NascdRestorePathPairInput
$pair1.srcPath = "/finance/quarterly-report.xlsx"
$pair1.dstPath = "/restored/2026-06-15"
$pair2 = Get-RscType -Name NascdRestorePathPairInput
$pair2.srcPath = "/finance/budget.csv"
$pair2.dstPath = "/restored/2026-06-15"
$query.Var.input = Get-RscType -Name RecoverCloudDirectNasShareInput
$query.Var.input.snapshotFid = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
$query.Var.input.srcShareName = "finance-share"
$query.Var.input.restorePathPairList = @($pair1, $pair2)
$query.field = Get-RscType -Name AsyncRequestStatus -InitialProperties id,status
$query.Invoke()
#!/bin/bash
# RSC_TOKEN="YOUR_RSC_ACCESS_TOKEN"
# Shopping-cart restore. All srcPaths must come from the same snapshot and not
# overlap. All dstPaths must be identical (one destination) or all empty.
query="mutation RecoverCloudDirectNasShare(\$input: RecoverCloudDirectNasShareInput!) { recoverCloudDirectNasShare(input: \$input) { id status } }"
read -r -d '' variables <<'JSON'
{
"input": {
"snapshotFid": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"srcShareName": "finance-share",
"restorePathPairList": [
{ "srcPath": "/finance/quarterly-report.xlsx", "dstPath": "/restored/2026-06-15" },
{ "srcPath": "/finance/budget.csv", "dstPath": "/restored/2026-06-15" }
]
}
}
JSON
# Execute the GraphQL mutation with curl
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $RSC_TOKEN" \
-d "$(jq -n --arg q "$query" --argjson v "$variables" '{query: $q, variables: $v}')" \
https://example.my.rubrik.com/api/graphql
Monitor Recovery
recoverCloudDirectNasShare returns an AsyncRequestStatus immediately — the restore runs in the background. Use the returned id to poll the task to completion using the standard async task-monitoring pattern, checking status until it reaches a terminal state.
Set Up
The operations below are one-time or infrequent administrative tasks: registering a NAS appliance so its shares can be discovered, adding shares on generic systems, registering Kerberos credentials, and removing a system. Most environments perform these once, then work entirely within the discovery, protection, and recovery flows above.
Register a NAS System
Register a NAS appliance as a Cloud Direct system with addCloudDirectSystem. Once the import completes, the system's shares become discoverable and can be protected.
| Field | Description |
|---|---|
clusterId |
Required. The Rubrik CDM cluster that will manage this system. |
host |
Required. Management IP or hostname of the NAS appliance. |
systemType |
Required. Vendor type — for example NETAPP_CLUSTER_MODE, ISILON, QUMULO, FLASHBLADE, VAST_DATA, FSXN, AZURE_FILES, GENERIC_NFS, GENERIC_SMB, GENERIC_S3. |
skipServiceAccountCreation |
Required. Set true to skip automatic service account creation on the array and use the credentials you provide as-is. |
verifySsl |
Required. Whether to verify the appliance's TLS certificate. |
Authenticate with either a username/password pair (username, password) or a client certificate (certificateData, certificateType, certificateKeyPassword). For FSxN, also set managementInfo.fileSystemId; for Azure Files, set managementInfo.privateEndpoint.
Registration is asynchronous
addCloudDirectSystem returns { jobId } — an import job ID, not an AsyncRequestStatus. The system and its shares do not appear in discovery queries until the background import finishes, which can take up to two hours for large environments. There is no dedicated status query for this job — monitor progress in the Rubrik UI or the activity events feed.
# Register a NAS appliance as a Cloud Direct system.
# Returns a jobId — registration runs asynchronously and shares appear once
# the background import completes (up to ~2 hours for large environments).
mutation {
addCloudDirectSystem(input: {
clusterId: "11111111-2222-3333-4444-555555555555"
host: "netapp01.example.com"
systemType: NETAPP_CLUSTER_MODE
username: "svc-rubrik"
password: "REPLACE_WITH_PASSWORD"
skipServiceAccountCreation: false
verifySsl: true
}) {
jobId
}
}
# Register a NAS appliance as a Cloud Direct system.
# Returns a jobId — registration runs asynchronously and shares appear once
# the background import completes (up to ~2 hours for large environments).
$query = New-RscMutation -GqlMutation addCloudDirectSystem
$query.Var.input = Get-RscType -Name AddCloudDirectSystemInput
$query.Var.input.clusterId = "11111111-2222-3333-4444-555555555555"
$query.Var.input.host = "netapp01.example.com"
$query.Var.input.systemType = [RubrikSecurityCloud.Types.CloudDirectNasVendorType]::NETAPP_CLUSTER_MODE
$query.Var.input.username = "svc-rubrik"
$query.Var.input.password = "REPLACE_WITH_PASSWORD"
$query.Var.input.skipServiceAccountCreation = $false
$query.Var.input.verifySsl = $true
$query.field = Get-RscType -Name AddCloudDirectSystemReply -InitialProperties jobId
$query.Invoke()
#!/bin/bash
# RSC_TOKEN="YOUR_RSC_ACCESS_TOKEN"
# Register a NAS appliance as a Cloud Direct system. Returns a jobId;
# registration is asynchronous and shares appear once the import completes.
query="mutation AddCloudDirectSystem(\$input: AddCloudDirectSystemInput!) { addCloudDirectSystem(input: \$input) { jobId } }"
read -r -d '' variables <<'JSON'
{
"input": {
"clusterId": "11111111-2222-3333-4444-555555555555",
"host": "netapp01.example.com",
"systemType": "NETAPP_CLUSTER_MODE",
"username": "svc-rubrik",
"password": "REPLACE_WITH_PASSWORD",
"skipServiceAccountCreation": false,
"verifySsl": true
}
}
JSON
# Execute the GraphQL mutation with curl
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $RSC_TOKEN" \
-d "$(jq -n --arg q "$query" --argjson v "$variables" '{query: $q, variables: $v}')" \
https://example.my.rubrik.com/api/graphql
Add Shares (Generic NAS Only)
addCloudDirectSharesToSystem is needed only for generic NAS systems (GENERIC_NFS, GENERIC_SMB, GENERIC_S3), where shares are not auto-discovered. For branded arrays — NetApp, Isilon, Qumulo, and the rest — shares are discovered automatically after the system is registered, so you do not call this.
Provide clusterUuid, systemId (the system FID), and shares — a list of share paths to add.
Kerberos Credentials (Kerberos-Secured NFS Only)
addCloudDirectKerberosCredential is needed only for NFS shares secured with Kerberos (krb5/krb5i/krb5p). Plain NFS (AUTH_SYS) and SMB do not require it.
Kerberos credentials are registered at the cluster level, not per system — register them before or independently of system import. Provide clusterUuid, username, password, and a kdcConfig object with kdc1, realm, and an optional kdc2. Rotate credentials by removing them with deleteCloudDirectKerberosCredential and registering new ones.
Remove a System
Remove a Cloud Direct system with cloudDirectSystemDelete, passing clusterUuid and systemFid.
Operation name
The mutation is cloudDirectSystemDelete — the noun precedes the verb, unlike the addCloudDirect* operations. It returns Void, so the request has no selection set.
# Remove a Cloud Direct system. Note the operation name: cloudDirectSystemDelete.
$query = New-RscMutation -GqlMutation cloudDirectSystemDelete
$query.Var.input = Get-RscType -Name CloudDirectSystemDeleteInput
$query.Var.input.clusterUuid = "11111111-2222-3333-4444-555555555555"
$query.Var.input.systemFid = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
$query.Invoke()
#!/bin/bash
# RSC_TOKEN="YOUR_RSC_ACCESS_TOKEN"
# Remove a Cloud Direct system. Note the operation name: cloudDirectSystemDelete.
# Returns Void — there is no selection set.
query="mutation CloudDirectSystemDelete(\$input: CloudDirectSystemDeleteInput!) { cloudDirectSystemDelete(input: \$input) }"
read -r -d '' variables <<'JSON'
{
"input": {
"clusterUuid": "11111111-2222-3333-4444-555555555555",
"systemFid": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
}
}
JSON
# Execute the GraphQL mutation with curl
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $RSC_TOKEN" \
-d "$(jq -n --arg q "$query" --argjson v "$variables" '{query: $q, variables: $v}')" \
https://example.my.rubrik.com/api/graphql