---
title: "Copy a file/dir from this node to another node"
method: POST
path: "/preview/nodes/{name}/copies"
tags: ["nodes"]
---

# Copy a file/dir from this node to another node

`POST /preview/nodes/{name}/copies`

## Request

- Base URL: `https://autoresearch.sfcompute.com`
- URL: `https://autoresearch.sfcompute.com/preview/nodes/{name}/copies`
- Auth: HTTP bearer

Copy a file or directory from one of your nodes to another - the one-verb node-to-node move (docs: no mesh or shared network required; it works between any two RUNNING nodes of your workspace, across hosts and regions). The bytes ride one storage hop, exercised entirely by the platform's hosts: the source side is an export (a directory tars its contents; the artifact receipt - id, size, sha256 - shows on the mission page, ~30 days), the destination side an import - the bytes appear at dst_path owned by dev, and no URL or credential ever enters either container, nothing rides through this chat. A FILE lands at dst_path exactly (parents created; a trailing "/" means "into this directory under the source's name"). A DIRECTORY's CONTENTS land extracted under dst_path, merged file-by-file over what's already there - a re-copy after edits overwrites per file instead of failing on an existing tree. The call waits up to 5 minutes for the export leg (returning artifact_id, size_bytes, sha256; past that it refuses with error code TIMEOUT and the artifact id, and the export can still land. A client whose own call deadline is shorter gives up first; list_artifacts(src_node) then shows the export) and starts the import leg: poll get_import(dst_node, import_id) until "complete". Both nodes must be RUNNING. A stopped end is a refusal and never a wake. A run_command wakes a node, and the wake bills. A same-node copy is refused. Use run_command with a plain cp there, because the file never leaves the disk. Copy time is node time on both ends, and the import leg holds the destination out of grace while it streams. Bounded by the artifact export rate and size caps and the import caps (refusals name the numbers). Every call is recorded to your org's audit log (both nodes, both paths, the artifact id - never bytes).

## Path parameters

- `name` string, required: Source node name (from `list_nodes`).

## Query parameters

- `workspace` string

## Request body

- object
  - `dst_node` string, required: Destination node name (must differ from src_node).
  - `dst_path` string, required: Where it lands on dst_node, absolute or ~-relative. Copying a FILE: this is the destination file path (parents created; a trailing "/" means "into this directory under the source's name", the cp convention). Copying a DIRECTORY: this is the destination directory; the source directory's CONTENTS land under it.
  - `mission` string, nullable: Attribute the copy (and its artifact receipt) to a mission (from open_mission). Omit and it joins the source node's own mission, which is usually what you want.
  - `src_path` string, required: The path to copy FROM, absolute or ~-relative (e.g. "~/prep/app"). A regular file or a directory.

## Response `200`

The capability's JSON result.

- Result: The capability's result: the same object the MCP tool returns as structuredContent. Resources carry an `object` type discriminator and an immutable id; money is integer micro-dollars in `*_usd_micros` fields.
  - `object` string: The resource type, when the result is one resource.

## Other responses

- `400`: Malformed request: bad JSON, a parameter that does not parse, or a value outside its range. Code `invalid`.
- `401`: No bearer token, or one this API cannot verify. Code `unauthenticated`.
- `403`: Authenticated, but the token's scopes or the account's role do not reach this operation. The message names the scope word to request. Code `forbidden`.
- `404`: No such route. Code `not_found`; the body names the OpenAPI document.
- `409`: The node is not in a state this export can read: stopped, still coming up, lost, or changing state mid-call. Code `NODE_NOT_RUNNING`.
- `413`: The path is over the export size cap. `export_file` stops at the object store's single-PUT bound and no raise exceeds it; send a larger path with `export_data`. Code `TOO_LARGE`.
- `422`: A well-formed request the platform declined: no such node, a cap reached, a state that forbids the move. The message says which, and what to do instead. Code `refused`.
- `429`: Over this door's per-customer budget. Wait `Retry-After` seconds. Code `rate_limited`.
- `500`: Our fault. Retry; if it persists, quote the request-id. Code `internal`.
- `503`: The node's host did not answer, went away mid-export, or export is not configured here. Ours, not yours: retry. Codes `HOST_UNAVAILABLE`, `NOT_ENABLED`.
- `504`: copy_file's export leg did not finish inside the call's wait. It is still running and may land: read the artifact by id before copying again. Code `TIMEOUT`. (export_file answers a wait that ends with 200 and `state: pending` instead.)

---

[API](https://skmtc.dev/givemeanode/apis/autoresearch-customer-api.md) · [All operations](https://skmtc.dev/givemeanode/apis/autoresearch-customer-api/llms.txt) · [OpenAPI document](https://skmtc.dev/givemeanode/apis/autoresearch-customer-api/revisions/f88dcb70ac6c?raw)
