# Cloud Storage

Cloud Storage is a team-level file space for storing files that need to be reused across MoreLogin automation workflows. Use it to upload files once, organize them with tags, find them later, and delete files that are no longer needed.

It is separate from Cloud Phone file transfer APIs. Cloud Phone file APIs move files into or out of a specific device instance. Cloud Storage APIs manage the shared file library before a file is used by devices, schedules, RPA templates, or other automation logic.

## What You Can Do

| Capability | What it is for | Related APIs |
|  --- | --- | --- |
| Storage overview | Check total capacity, used capacity, expiration date, and capacity status before uploading or cleaning files. | Query cloud storage information |
| File search | List cloud storage files by page and filter by file name, file type, tag, or file ID. | Page cloud storage files |
| File upload | Request presigned upload URLs, upload file content to object storage, then confirm completion in MoreLogin. | Batch request presigned upload URLs, confirm upload completion |
| File cleanup | Delete one or more files from the shared storage library. | Batch delete cloud storage files |
| File tagging | Replace or append tags on files to organize files by project, customer, usage, or workflow. | Set file tags, add file tags, query file tags |
| Tag management | Create, edit, list, and delete reusable file tags. | Query all tags, create tag, edit tag, delete tags |


## Common Use Cases

- Upload APKs, media files, documents, or test assets once and reuse them in automation.
- Keep files organized by customer, campaign, app version, environment, or workflow.
- Build a file picker in your internal tool by calling the file page API with file name and tag filters.
- Clean up expired or unused files in batches after a workflow finishes.
- Sync an external asset system with MoreLogin by creating tags and attaching them to uploaded files.


## API Access

| Method | Base URL | Path Prefix | Use Case |
|  --- | --- | --- | --- |
| **Open API** | `https://api.morelogin.com` | `/cloudstorage` | Server-to-server access, remote tools, CI/CD, backend services |
| **Local API** | `http://127.0.0.1:40000` | `/api/cloudstorage` | Scripts or desktop tools running on the same machine as the MoreLogin client |


For authentication details, see [Authentication](/api-reference/getting-started/authentication).

## Upload Flow

Cloud Storage uploads use a presigned URL flow. Your code does not upload the binary file directly to the MoreLogin API.

1. Call **Batch Request Presigned Upload URLs** with a list of file names (with extensions).
2. For each returned item, upload the binary file to `presignedUrl` with HTTPS `PUT`.
3. Call **Confirm Upload Completion** with the returned file `id`.
4. Use **Page Cloud Storage Files** or **Query File Tags** to verify and display the uploaded file.


```bash
# 1. Request a presigned upload URL
curl -X POST "https://api.morelogin.com/cloudstorage/upload/init" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "fileNames": ["example.jpg"]
  }'

# 2. Upload file content to the returned presignedUrl
curl -X PUT "PRESIGNED_URL_FROM_RESPONSE" \
  -H "Content-Type: image/jpeg" \
  --data-binary "@example.jpg"

# 3. Confirm upload completion (id from step 1 response)
curl -X POST "https://api.morelogin.com/cloudstorage/upload/complete" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "id": 1800000000000001
  }'
```

For Local API, keep the same request body and replace the path with `http://127.0.0.1:40000/api/cloudstorage/...`.

## Use Cloud Storage Files in Cloud Phone RPA

After a file is uploaded and confirmed, Cloud Phone RPA template parameters can reference the file by Cloud Storage file ID. Use the MoreLogin cloud file protocol instead of an external public download URL:

```text
morelogin://cloudfile?ids=1,2
```

`ids` is a comma-separated list of Cloud Storage file IDs. Use English commas only, without spaces. You can get file IDs from the upload completion response or from **Page Cloud Storage Files**.

Single file:

```text
morelogin://cloudfile?ids=1800000000001001
```

Multiple files:

```text
morelogin://cloudfile?ids=1800000000001001,1800000000001002
```

When the RPA parameter is a media or file parameter, keep the required `__Extra__` metadata and set the parameter value to the cloud file protocol URI:

```json
{
  "__Extra__": {
    "videoDownloadUrl": { "name": "video.mp4", "size": 204800000 }
  },
  "videoDownloadUrl": "morelogin://cloudfile?ids=1,2"
}
```

This is useful for scheduled Cloud Phone RPA tasks, marketplace templates, personal templates, and any RPA node parameter that expects a reusable uploaded file. The RPA runtime resolves the file from MoreLogin Cloud Storage, so the file does not need to be exposed as a public HTTPS URL.

## Complete Example: Run Cloud Phone RPA with a Cloud Storage Video

This example uploads `video.mp4` to Cloud Storage, attaches a tag, then creates a one-time Cloud Phone RPA task that uses the uploaded file in the `videoDownloadUrl` template parameter.

The example uses Local API paths. For Open API, keep the same request bodies and replace:

- `http://127.0.0.1:40000/api/cloudstorage/...` with `https://api.morelogin.com/cloudstorage/...`
- `http://127.0.0.1:40000/api/cloudphone/...` with `https://api.morelogin.com/cloudphone/...`


### 1. Create a Tag for RPA Assets

```bash
curl -X POST "http://127.0.0.1:40000/api/cloudstorage/tag/create" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "tagName": "RPA Assets"
  }'
```

Save the returned tag `id`, for example `1800000000000101`.

### 2. Request a Presigned Upload URL

```bash
curl -X POST "http://127.0.0.1:40000/api/cloudstorage/upload/init" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "fileNames": ["video.mp4"]
  }'
```

Save the returned file `id` and `presignedUrl`.

### 3. Upload the File Binary

Upload the file content to `presignedUrl`. This request goes to the object storage URL returned by the previous step, not to the MoreLogin API.

```bash
curl -X PUT "PRESIGNED_URL_FROM_RESPONSE" \
  -H "Content-Type: video/mp4" \
  --data-binary "@video.mp4"
```

### 4. Confirm Upload Completion

```bash
curl -X POST "http://127.0.0.1:40000/api/cloudstorage/upload/complete" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "id": 1800000000000001
  }'
```

Save the returned Cloud Storage file ID, for example `1800000000001001`.

### 4.1 Attach the Tag to the File

```bash
curl -X POST "http://127.0.0.1:40000/api/cloudstorage/file/tag/add" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "fileId": 1800000000001001,
    "tagIds": [1800000000000101]
  }'
```

If your upload completion response does not include the file ID directly, query files by page:

```bash
curl -X POST "http://127.0.0.1:40000/api/cloudstorage/file/page" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "pageNo": 1,
    "pageSize": 20,
    "fileName": "video",
    "tagIds": [1800000000000101]
  }'
```

### 5. Build the RPA Template Parameter

Use the Cloud Storage file ID in the MoreLogin cloud file protocol:

```text
morelogin://cloudfile?ids=1800000000001001
```

For an RPA template parameter named `videoDownloadUrl`, build the JSON object like this:

```json
{
  "__Extra__": {
    "videoDownloadUrl": {
      "name": "video.mp4",
      "size": 204800000
    }
  },
  "videoDownloadUrl": "morelogin://cloudfile?ids=1800000000001001"
}
```

Then escape it as a JSON string for `templateParameter`:

```json
"{\"__Extra__\":{\"videoDownloadUrl\":{\"name\":\"video.mp4\",\"size\":204800000}},\"videoDownloadUrl\":\"morelogin://cloudfile?ids=1800000000001001\"}"
```

### 6. Create a One-Time Cloud Phone RPA Task

Before creating the task, get `cloudPhoneId` from the Cloud Phone list API and `templateId` from the marketplace or personal template list API.

```bash
curl -X POST "http://127.0.0.1:40000/api/cloudphone/rpa/onceTask/save" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "cloudPhoneId": 1678331966138097,
    "scheduleName": "Upload video from Cloud Storage",
    "templateId": 1678347487160256,
    "templateParameter": "{\"__Extra__\":{\"videoDownloadUrl\":{\"name\":\"video.mp4\",\"size\":204800000}},\"videoDownloadUrl\":\"morelogin://cloudfile?ids=1800000000001001\"}",
    "description": "Use a Cloud Storage video file in a one-time Cloud Phone RPA task"
  }'
```

### 7. Verify the Task

Query the Cloud Phone RPA task list or subtask list to verify execution status:

```bash
curl -X POST "http://127.0.0.1:40000/api/cloudphone/rpa/task/page" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "pageNo": 1,
    "pageSize": 20,
    "taskName": "Upload video from Cloud Storage"
  }'
```

The key point is that the RPA task receives `videoDownloadUrl` as `morelogin://cloudfile?ids=...`. MoreLogin resolves the file from Cloud Storage at runtime, so your integration does not need to host the file on a public URL.

## Tag Workflow

Tags are reusable metadata for cloud storage files. A file can have multiple tags.

- Use **Create Cloud Storage File Tag** to create tags such as `Invoices`, `APK`, `Customer A`, or `RPA Assets`.
- Use **Set File Tags** when you want to overwrite all tags on a file.
- Use **Add File Tags** when you want to append tags without removing existing tags.
- Use **Query All Cloud Storage File Tags** to build tag filters in your UI.
- Use **Query File Tags** to show which tags are attached to selected files.


Example: append a tag to a file without removing its existing tags.

```bash
curl -X POST "https://api.morelogin.com/cloudstorage/file/tag/add" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "fileId": 1800000000001001,
    "tagIds": [1800000000000103]
  }'
```

## API Map

| Task | Open API path | Local API path |
|  --- | --- | --- |
| Query storage information | `GET /cloudstorage/info` | `GET /api/cloudstorage/info` |
| Page files | `POST /cloudstorage/file/page` | `POST /api/cloudstorage/file/page` |
| Request presigned upload URLs | `POST /cloudstorage/upload/init` | `POST /api/cloudstorage/upload/init` |
| Confirm upload completion | `POST /cloudstorage/upload/complete` | `POST /api/cloudstorage/upload/complete` |
| Batch delete files | `POST /cloudstorage/file/delete/batch` | `POST /api/cloudstorage/file/delete/batch` |
| Set file tags | `POST /cloudstorage/file/tag/set` | `POST /api/cloudstorage/file/tag/set` |
| Add file tags | `POST /cloudstorage/file/tag/add` | `POST /api/cloudstorage/file/tag/add` |
| Query tags on files | `POST /cloudstorage/file/tag/query` | `POST /api/cloudstorage/file/tag/query` |
| Query all tags | `GET /cloudstorage/tag/all` | `GET /api/cloudstorage/tag/all` |
| Create tag | `POST /cloudstorage/tag/create` | `POST /api/cloudstorage/tag/create` |
| Edit tag | `POST /cloudstorage/tag/edit` | `POST /api/cloudstorage/tag/edit` |
| Delete tags | `POST /cloudstorage/tag/delete/batch` | `POST /api/cloudstorage/tag/delete/batch` |


## API Reference

| API | Description |
|  --- | --- |
| [Cloud Storage Open API](/api-reference/cloud-storage/open-api) | Remote access via `https://api.morelogin.com`, OAuth2 authentication |
| [Cloud Storage Local API](/api-reference/cloud-storage/local-api) | Local access via `http://127.0.0.1:40000` |


> **Note**: Local API paths use the `/api/` prefix. Open API paths omit it.