= copy()
:description: Copies a folder, register, or document to a new location (dms.XMLCopy). Returns the new object_id. Supports optional renaming of the copied object.
:keywords: copy, XMLCopy, object_id, folder, register, document, rename
:page-tags: api, dms

Copies a folder, register, or document to a new location using `dms.XMLCopy`.

When copying a register or folder with `copy_cascading=True`, all contained
child objects are also copied recursively. When copying a document with
`link_document=True`, a second location (link) for the same index record is
created instead of a fully independent copy.

== Signature

[tabs]
====
Sync::
+
[source,python]
----
ecm.dms.copy(
    model: ECMFolderModel | ECMRegisterModel | ECMDocumentModel | int,
    object_type: int | str | None = None,
    *,
    folder_id: int | ECMFolderModel | None = None,
    register_id: int | ECMRegisterModel | None = None,
    register_type: int | None = None,
    copy_cascading: bool = False,
    link_document: bool = False,
) -> None
----

Async::
+
[source,python]
----
await ecm.dms.copy(
    model: ECMFolderModel | ECMRegisterModel | ECMDocumentModel | int,
    object_type: int | str | None = None,
    *,
    folder_id: int | ECMFolderModel | None = None,
    register_id: int | ECMRegisterModel | None = None,
    register_type: int | None = None,
    copy_cascading: bool = False,
    link_document: bool = False,
) -> None
----
====

== Parameters

[cols="1,1,1,3"]
|===
|Parameter |Type |Default |Description

|`model`
|`ECMFolderModel \| ECMRegisterModel \| ECMDocumentModel \| int`
|—
|The object to copy. Either a model instance (must have `id` set) or a plain integer object ID (requires `object_type`).

|`object_type`
|`int \| str \| None`
|`None`
|Only required when `model` is a plain `int`. Either a numeric type ID or the internal name of the object type.

|`folder_id`
|`int \| ECMFolderModel \| None`
|`None`
|Target folder — a numeric ID or an `ECMFolderModel` instance whose `id` is used. Required for all copy operations.

|`register_id`
|`int \| ECMRegisterModel \| None`
|`None`
|Target register — a numeric ID or an `ECMRegisterModel` instance whose `id` is used. Pass `-1` to place the copy directly in the folder without a parent register.

|`register_type`
|`int \| None`
|`None`
|Type ID of the target register. Inferred automatically when `register_id` is an `ECMRegisterModel` instance whose class defines `_type_id_`.

|`copy_cascading`
|`bool`
|`False`
|When `True`, all contained child objects are also copied recursively. Only applicable for registers and folders.

|`link_document`
|`bool`
|`False`
|When `True`, a second location (link) for the same index record is created instead of a full copy. Only applicable for documents. Source and target location must differ.
|===

== Exceptions

[cols="1,3"]
|===
|Exception |Condition

|`ValueError`
|`model` is a plain `int` and `object_type` is `None`.

|`ValueError`
|`model` is a model instance with `id` set to `None`.
|===

== Examples

=== Copy a document to a different folder

[tabs]
====
Sync::
+
[source,python]
----
doc = ecm.dms.select(InvoiceDocument).where(InvoiceDocument.Title == "Original").execute()[0]
target_folder = ecm.dms.select(InvoiceFolder).where(InvoiceFolder.Year == 2025).execute()[0]

ecm.dms.copy(doc, folder_id=target_folder, register_id=-1)
----

Async::
+
[source,python]
----
doc = (await ecm.dms.select(InvoiceDocument).where(InvoiceDocument.Title == "Original").execute())[0]
target_folder = (await ecm.dms.select(InvoiceFolder).where(InvoiceFolder.Year == 2025).execute())[0]

await ecm.dms.copy(doc, folder_id=target_folder, register_id=-1)
----
====

=== Copy a folder with all its children

[tabs]
====
Sync::
+
[source,python]
----
folder = ecm.dms.select(InvoiceFolder).where(InvoiceFolder.Year == 2023).execute()[0]

# Copies the folder and all registers and documents inside it
ecm.dms.copy(folder, folder_id=archive_folder_id, register_id=-1, copy_cascading=True)
----

Async::
+
[source,python]
----
folder = (await ecm.dms.select(InvoiceFolder).where(InvoiceFolder.Year == 2023).execute())[0]

await ecm.dms.copy(folder, folder_id=archive_folder_id, register_id=-1, copy_cascading=True)
----
====

=== Create a linked copy (second location)

[tabs]
====
Sync::
+
[source,python]
----
# The document gets a second location — both point to the same index record
ecm.dms.copy(doc, folder_id=secondary_folder_id, register_id=-1, link_document=True)
----

Async::
+
[source,python]
----
await ecm.dms.copy(doc, folder_id=secondary_folder_id, register_id=-1, link_document=True)
----
====

== See also

* xref:api/dms/move.adoc[move()] — Move an object to a new location
* xref:api/dms/delete.adoc[delete()] — Delete an object
