# `POST /v1/workspace/copy` — Copy or move to another repository

Part of the [Bkper Managed Agent API](https://bkper.com/docs/api/managed-agent.md). Read its guide for authentication, conventions, and examples.

Copy one file or folder, as its working copy has it, from one context repository the user can view into the working copy of another they can change (cloned when the sandbox does not have it), and with `move` remove it from the source, which they must also be able to change: two repositories to save. At most 100 files, each up to 256 KiB (422 file_invalid, reason count or size), each as a write would take it at its new path. 409 file_exists when the destination exists (never overwritten), 404 not_found when the source is not there, 403 workspace_forbidden without those permissions. Context repositories only, never App source; a repository to itself is 400. Nothing is published until Save; the agent sees it at once. 409 workspace_busy while Git works in the repository (the agent's, or a sync): nothing changed, try again.

## Operation contract

```json
{
  "operationId": "copyWorkspaceEntry",
  "tags": [
    "Workspace"
  ],
  "summary": "Copy or move to another repository",
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "parameters": [],
  "description": "Copy one file or folder, as its working copy has it, from one context repository the user can view into the working copy of another they can change (cloned when the sandbox does not have it), and with `move` remove it from the source, which they must also be able to change: two repositories to save. At most 100 files, each up to 256 KiB (422 file_invalid, reason count or size), each as a write would take it at its new path. 409 file_exists when the destination exists (never overwritten), 404 not_found when the source is not there, 403 workspace_forbidden without those permissions. Context repositories only, never App source; a repository to itself is 400. Nothing is published until Save; the agent sees it at once. 409 workspace_busy while Git works in the repository (the agent's, or a sync): nothing changed, try again.",
  "requestBody": {
    "required": true,
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/CopyWorkspace"
        }
      }
    }
  },
  "responses": {
    "200": {
      "description": "Success",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/WorkspaceCopied"
          }
        }
      }
    },
    "400": {
      "description": "Rejected; never contains credentials or upstream payloads.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "401": {
      "description": "Rejected; never contains credentials or upstream payloads.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "403": {
      "description": "Rejected; never contains credentials or upstream payloads.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "404": {
      "description": "Rejected; never contains credentials or upstream payloads.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "409": {
      "description": "Rejected; never contains credentials or upstream payloads.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "410": {
      "description": "Rejected; never contains credentials or upstream payloads.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "411": {
      "description": "Rejected; never contains credentials or upstream payloads.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "413": {
      "description": "Rejected; never contains credentials or upstream payloads.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "422": {
      "description": "Rejected; never contains credentials or upstream payloads.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "503": {
      "description": "Rejected; never contains credentials or upstream payloads.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    }
  }
}
```

## Schemas

### CopyWorkspace

```json
{
  "type": "object",
  "properties": {
    "from": {
      "type": "object",
      "properties": {
        "repository": {
          "type": "string",
          "pattern": "^(user|domain|books\\/[A-Za-z0-9_-]{1,128})$",
          "description": "A context repository: user, domain or books/{bookId}. Never App source."
        },
        "path": {
          "type": "string",
          "minLength": 1,
          "maxLength": 512,
          "description": "A file or folder (one tree entry)."
        }
      },
      "required": [
        "repository",
        "path"
      ],
      "additionalProperties": false
    },
    "to": {
      "type": "object",
      "properties": {
        "repository": {
          "type": "string",
          "pattern": "^(user|domain|books\\/[A-Za-z0-9_-]{1,128})$",
          "description": "Another context repository than `from`'s."
        },
        "path": {
          "type": "string",
          "minLength": 1,
          "maxLength": 512,
          "description": "Where it goes, which must not exist (409 file_exists)."
        }
      },
      "required": [
        "repository",
        "path"
      ],
      "additionalProperties": false
    },
    "move": {
      "type": "boolean",
      "description": "Also remove it from `from`."
    }
  },
  "required": [
    "from",
    "to",
    "move"
  ],
  "additionalProperties": false
}
```

### WorkspaceCopied

```json
{
  "type": "object",
  "properties": {
    "paths": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "The files written in the destination's working copy, by path."
    },
    "moved": {
      "type": "boolean",
      "description": "Whether it left the source: with `move`, always."
    }
  },
  "required": [
    "paths",
    "moved"
  ],
  "description": "A copy (or move) between two working copies: not published until each is saved."
}
```

### Error

```json
{
  "type": "object",
  "properties": {
    "error": {
      "type": "object",
      "properties": {
        "code": {
          "type": "string",
          "description": "Stable code, e.g. not_found, idempotency_conflict, session_working, usage_limit_exceeded. Open."
        },
        "type": {
          "description": "Category, e.g. invalid_request_error, authentication_error, usage_limit_error. Open.",
          "type": "string"
        },
        "message": {
          "type": "string"
        },
        "host": {
          "description": "host_in_use: the host another service holds.",
          "type": "string"
        },
        "service": {
          "description": "host_in_use: the id of the service that holds the host.",
          "type": "string"
        },
        "reason": {
          "description": "file_invalid: why the change, or a picture, was refused. Open: path | text | size | skill | skills | count | type.",
          "type": "string"
        },
        "paths": {
          "description": "file_exists from an add: every path of the request where a file is and `replace` was not set, all at once, so the person can be asked once. publish_conflict: the files someone published changes to the same lines of.",
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "publishers": {
          "description": "publish_conflict: who published those changes, by name.",
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "required": [
        "code"
      ]
    }
  },
  "required": [
    "error"
  ]
}
```

## Authentication

```json
{
  "bearerAuth": {
    "type": "http",
    "scheme": "bearer"
  }
}
```
