> For the complete documentation index, see [llms.txt](https://cleyrop.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://cleyrop.gitbook.io/docs/documentation-fr-en/support-and-resources/references-techniques-api-sdk/sdk-cleyrop-sdk.md).

# SDK cleyrop-sdk

The SDK `cleyrop-sdk` is the official Python library for interacting with the Cleyrop platform from code. It lets you manipulate a project's Work Data resources programmatically to automate uploads, integrate file management into a processing pipeline, or access data from an App.

It exposes a Python client (synchronous and asynchronous) as well as a command-line interface (CLI) usable from a DevSpace terminal.

## Installation & Usage

The SDK is pre-installed in the environment of the **Codelab** and in the Python / PySpark transformations of Dataflows. Authentication is automatic thanks to the token injected by the platform.

Only the **DevSpace** requires a manual installation (see below).

### DevSpace Installation - Getting Started

{% stepper %}
{% step %}

#### Installation

Once your DevSpace is connected to your IDE (VS Code, Cursor…), create a working directory and install the SDK:

<pre class="language-shell" data-overflow="wrap"><code class="lang-shell"><strong>mkdir -p /home/cleyrop/projects/mon-projet &#x26;&#x26; cd /home/cleyrop/projects/mon-projet
</strong>uv venv
source .venv/bin/activate

uv pip install "cleyrop-sdk" --extra-index-url "https://gitlab.com/api/v4/projects/79823225/packages/pypi/simple"
</code></pre>

{% endstep %}

{% step %}

#### Authentication

Once the `cleyrop-sdk` is installed, authenticate on the platform with the following command:

```shell
cleyrop login
```

The SDK opens your browser and asks you to authorize access. Click **Yes** to validate.

<figure><img src="/files/01a45813c9cd2d7446112cbf6bff79308f5b14b8" alt="" width="322"><figcaption></figcaption></figure>
{% endstep %}
{% endstepper %}

## Usage - Code Example

List the files present and upload a file into a project's Work Data.

{% tabs %}
{% tab title="Codelab" %}
{% code title="Codelab : Cleyrop sdk - folder content / upload file" expandable="true" %}

```python
import os, io
from cleyrop import CleyropClient, ClientConfig
from cleyrop.models import FileResponse, FolderResponse

sdk = CleyropClient(ClientConfig.from_env())

# The project associated with the notebook
project = sdk.get_project_by_slug(os.environ["PROJECT_SLUG"])
print(f"Project: {project.slug} (id={project.id})")

# Project content (direct, non-recursive)
for item in sdk.iter_project_contents(project.id):
    kind = "📁" if isinstance(item, FolderResponse) else "📄"
    size = f" ({item.size}B)" if isinstance(item, FileResponse) else ""
    print(f"  {kind} {item.name}{size}")

# Upload a file
buf = io.BytesIO(b"Hello from Codelab\n")
resp = sdk.upload_file(buf, project_id=project.id, filename="from-codelab.txt")
print(f"Uploaded: {resp.name} (id={resp.id}, scan={resp.virus_scan_status})")
```

{% endcode %}
{% endtab %}

{% tab title="Dataflow " %}
{% code title="Dataflow - Cleyrop SDK - folder content / upload file" expandable="true" %}

```python

import os, io
from cleyrop import CleyropClient, ClientConfig
from cleyrop.models import FileResponse, FolderResponse

sdk = CleyropClient(ClientConfig.from_env())
sdk.login_client_credentials()   # mandatory in Dataflow

# The current project
project = sdk.get_project_by_slug(os.environ["PROJECT_SLUG"])
print(f"Project: {project.slug} (id={project.id})")

# List files at the root
for item in sdk.iter_project_contents(project.id):
    kind = "📁" if isinstance(item, FolderResponse) else "📄"
    size = f" ({item.size}B)" if isinstance(item, FileResponse) else ""
    print(f"  {kind} {item.name}{size}")

# Upload a file
buf = io.BytesIO(b"Hello from the Dataflow\n")
resp = sdk.upload_file(buf, project_id=project.id, filename="from-dataflow.txt")
print(f"Uploaded: {resp.name} (id={resp.id}, scan={resp.virus_scan_status})")
```

{% endcode %}

{% hint style="info" %}
In a Dataflow, the code above can be integrated into a Python or PySpark transformation to manipulate Work Data in addition to data processing.
{% endhint %}

{% hint style="danger" %}

<pre><code><strong>sdk.login_client_credentials()   # mandatory in Dataflow
</strong></code></pre>

{% endhint %}
{% endtab %}

{% tab title="DevSpace" %}
{% code title="DevSpace : Cleyrop sdk - folder content / upload file" overflow="wrap" %}

```py
import io
from cleyrop import CleyropClient, ClientConfig
from cleyrop.models import FileResponse, FolderResponse

with CleyropClient(ClientConfig.from_env()) as client:
    # List projects
    for p in client.iter_projects():
        print(f"  {p.slug:20s} {p.id}")

    # Navigate in a project's content
    project = client.get_project_by_slug("mon-projet")
    for item in client.iter_project_contents(project.id):
        kind = "📁" if isinstance(item, FolderResponse) else "📄"
        size = f" ({item.size}B)" if isinstance(item, FileResponse) else ""
        print(f"  {kind} {item.name}{size}")
    
    # Upload a file present in the DevSpace
    resp = client.upload_file("chemin/vers/mon-fichier.csv", project_id=project.id)
    print(f"Uploaded: {resp.name} (id={resp.id})")
```

{% endcode %}
{% endtab %}

{% tab title="App" %}
{% code title="App : Cleyrop SDK - folder content / upload file" overflow="wrap" %}

```py
import os
from cleyrop import CleyropClient, ClientConfig


def get_client() -> CleyropClient:
    """Client Configuration & Authentication"""
    cfg = ClientConfig.internal(
            client_id=os.environ.get("CLEYROP_CLIENT_ID", "cleyrop-cli"),
            client_secret=os.environ.get("CLEYROP_CLIENT_SECRET"),
        )
    client = CleyropClient(cfg)
    client.login_client_credentials()
    return client


# Usage
with get_client() as client:
    project = client.get_project_by_slug("mon-projet")
    for item in client.iter_project_contents(project.id):
        print(item.name)
    # … all the other SDK methods work here
    # (upload_file, download_file_bytes, create_folder, search, etc.)
```

{% endcode %}
{% endtab %}
{% endtabs %}

## Deploy an App with the SDK

To use the `cleyrop-sdk` in an App deployed via The Factory, add the following elements to your Dockerfile.

{% hint style="success" %}
To **use the SDK from an App** to access a project's Work Data files, you must first generate a **service account** for the instance and grant the necessary access rights (read, edit) to the desired projects
{% endhint %}

```dockerfile
FROM python:3.13-slim
WORKDIR /app

# Install the SDK (add here the dependencies specific to your app)
RUN pip install --no-cache-dir cleyrop-sdk \
    --extra-index-url "https://gitlab.com/api/v4/projects/79823225/packages/pypi/simple"

COPY app.py .

EXPOSE <port>
CMD ["python", "app.py"]
```

**Script example**

*Web application that connects and returns the list of accessible projects:*

{% code title="Python script" overflow="wrap" %}

```py
import os
from fastapi import FastAPI
from cleyrop import CleyropClient, ClientConfig

app = FastAPI()

# Connection (the attached service account provides the credentials)
client = CleyropClient(ClientConfig.internal(
    client_id=os.environ.get("CLEYROP_CLIENT_ID"),
    client_secret=os.environ.get("CLEYROP_CLIENT_SECRET"),
))
client.login_client_credentials()

@app.get("/")
def home():
    return {"projects": [p.slug for p in client.iter_projects()]}
```

{% endcode %}

{% code title="" overflow="wrap" %}

```dockerfile
FROM python:3.13-slim
WORKDIR /app

RUN pip install --no-cache-dir cleyrop-sdk fastapi "uvicorn[standard]" \
    --extra-index-url "https://gitlab.com/api/v4/projects/79823225/packages/pypi/simple"

COPY app.py .

EXPOSE 8080
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8080"]
```

{% endcode %}

{% hint style="info" %}
The port configured in The Factory must be the same as the one exposed by the app.
{% endhint %}

## Methods available in the Cleyrop SDK

<table data-header-hidden="false" data-header-sticky><thead><tr><th width="262.1015625">Method</th><th>Description</th><th>Main parameters</th><th>Output</th></tr></thead><tbody><tr><td><code>list_projects()</code></td><td>List all projects</td><td>—</td><td>Project list</td></tr><tr><td><code>get_project(id)</code></td><td>Retrieve a project by ID</td><td><code>id</code> : project UUID</td><td>Project ID</td></tr><tr><td><code>get_project_by_slug(slug)</code></td><td>Retrieve a project by slug</td><td><code>slug</code> : text identifier</td><td>Project slug</td></tr><tr><td><code>iter_projects()</code></td><td>Browse all projects (automatic pagination)</td><td>—</td><td>Project by project</td></tr><tr><td><code>iter_project_contents(project_id)</code></td><td>List the direct contents of a project or folder (non-recursive)</td><td><code>project_id</code>, <code>folder_id</code>(optional)</td><td>File or folder per item</td></tr><tr><td><code>resolve_path(project_id, path)</code></td><td>Find a file or folder from its path</td><td><code>project_id</code>, <code>path</code></td><td>Found file or folder</td></tr><tr><td><code>upload_file(source, project_id)</code></td><td>Upload a file (local path or buffer)</td><td><code>source</code>, <code>project_id</code>, <code>folder_id</code>(opt.), <code>filename</code>(opt.)</td><td>File created with its ID and scan status</td></tr><tr><td><code>download_file(file_id, dest)</code></td><td>Download a file to disk</td><td><code>file_id</code>, <code>dest</code></td><td>Path of the saved file</td></tr><tr><td><code>download_file_bytes(file_id)</code></td><td>Download a file into memory</td><td><code>file_id</code></td><td>Bytes content</td></tr><tr><td><code>get_file(file_id)</code></td><td>Retrieve a file's metadata</td><td><code>file_id</code></td><td>Name, size, scan status</td></tr><tr><td><code>rename_file(file_id, name)</code></td><td>Rename a file</td><td><code>file_id</code>, <code>name</code></td><td>File renamed</td></tr><tr><td><code>move_file(file_id, folder_id)</code></td><td>Move a file</td><td><code>file_id</code>, <code>folder_id</code></td><td>File moved</td></tr><tr><td><code>copy_file(file_id, name)</code></td><td>Copy a file</td><td><code>file_id</code>, <code>name</code> (opt.)</td><td>Copy created with new ID</td></tr><tr><td><code>update_file(file_id, file_metadata)</code></td><td>Update metadata</td><td><code>file_id</code>, <code>file_metadata</code>(dict)</td><td>File updated</td></tr><tr><td><code>delete_file(file_id)</code></td><td>Send a file to the trash</td><td><code>file_id</code></td><td>—</td></tr><tr><td><code>restore_file(file_id)</code></td><td>Restore a file from the trash</td><td><code>file_id</code></td><td>File restored</td></tr><tr><td><code>delete_file_permanent(file_id)</code></td><td>Delete permanently (irreversible)</td><td><code>file_id</code></td><td>—</td></tr><tr><td><code>create_folder(name, project_id)</code></td><td>Create a folder</td><td><code>name</code>, <code>project_id</code>, <code>parent_id</code> (opt.)</td><td>Folder created with its ID</td></tr><tr><td><code>get_folder(folder_id)</code></td><td>Retrieve a folder's metadata</td><td><code>folder_id</code></td><td>Name, path</td></tr><tr><td><code>get_folder_contents(folder_id)</code></td><td>List a folder's contents</td><td><code>folder_id</code></td><td>List of files and folders</td></tr><tr><td><code>rename_folder(folder_id, name)</code></td><td>Rename a folder</td><td><code>folder_id</code>, <code>name</code></td><td>Folder renamed</td></tr><tr><td><code>move_folder(folder_id, parent_id)</code></td><td>Move a folder</td><td><code>folder_id</code>, <code>parent_id</code></td><td>Folder moved</td></tr><tr><td><code>delete_folder(folder_id, recursive)</code></td><td>Send a folder to the trash</td><td><code>folder_id</code>, <code>recursive</code>(bool)</td><td>—</td></tr><tr><td><code>restore_folder(folder_id, recursive)</code></td><td>Restore a folder from the trash</td><td><code>folder_id</code>, <code>recursive</code>(bool)</td><td>Folder restored</td></tr><tr><td><code>search(query, project_id)</code></td><td>Search files and folders</td><td><code>query</code>, <code>project_id</code>, <code>search_mode</code>("name" or "fulltext")</td><td>Number of results + list</td></tr><tr><td><code>list_trash(project_id)</code></td><td>List items in the trash</td><td><code>project_id</code></td><td>Number of files and folders in the trash</td></tr></tbody></table>

***

## CLI

The SDK installs a command `cleyrop` usable in the DevSpace terminal.

**Authentication**

| Command          | Description             |
| ---------------- | ----------------------- |
| `cleyrop login`  | Interactive login       |
| `cleyrop logout` | Logout                  |
| `cleyrop me`     | Show the connected user |

**Projects**

| Command                                                     | Description                              |
| ----------------------------------------------------------- | ---------------------------------------- |
| `cleyrop projects list`                                     | List all projects                        |
| `cleyrop projects get <PROJECT_ID>`                         | Project details                          |
| `cleyrop projects contents <PROJECT_ID> [--folder-id UUID]` | List the contents of a project or folder |

**Files**

| Command                                                            | Description        |
| ------------------------------------------------------------------ | ------------------ |
| `cleyrop files upload <FILE> --project-id UUID [--folder-id UUID]` | Upload a file      |
| `cleyrop files download <FILE_ID> -o OUTPUT_PATH`                  | Download a file    |
| `cleyrop files get <FILE_ID>`                                      | File metadata      |
| `cleyrop files rename <FILE_ID> <NAME>`                            | Rename a file      |
| `cleyrop files copy <FILE_ID> [--folder-id UUID]`                  | Copy a file        |
| `cleyrop files move <FILE_ID> --folder-id UUID`                    | Move a file        |
| `cleyrop files delete <FILE_ID>`                                   | Send to trash      |
| `cleyrop files delete <FILE_ID> --permanent`                       | Delete permanently |
| `cleyrop files restore <FILE_ID>`                                  | Restore from trash |

**Folders**

| Command                                             | Description              |
| --------------------------------------------------- | ------------------------ |
| `cleyrop folders create <NAME> --project-id UUID`   | Create a folder          |
| `cleyrop folders list <FOLDER_ID>`                  | List a folder's contents |
| `cleyrop folders rename <FOLDER_ID> <NAME>`         | Rename a folder          |
| `cleyrop folders move <FOLDER_ID> --parent-id UUID` | Move a folder            |
| `cleyrop folders delete <FOLDER_ID>`                | Send to trash            |
| `cleyrop folders restore <FOLDER_ID>`               | Restore from trash       |

**File search and trash**

| `cleyrop search <QUERY> --project-id UUID [--mode fulltext\|name]` | Search files or folders |
| ------------------------------------------------------------------ | ----------------------- |
| `cleyrop trash list <PROJECT_ID>`                                  | List items in the trash |
