> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sarasfinance.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Signed Storage Upload Flow

> Upload large files directly to process storage using secure pre-signed S3 upload URLs.

The signed storage flow allows you to upload large files (such as videos, zip files, or heavy documents) directly to cloud storage (Amazon S3) securely, without routing the file bytes through the API gateway.

```mermaid theme={null}
sequenceDiagram
    participant Client
    participant Saras as Saras Platform
    participant S3 as AWS S3 Storage

    Client->>Saras: 1. Request Signed Upload URL (POST /knowledges/createSignedStorage)
    Saras-->>Client: Return temporary S3 POST URL, fields & File ID
    Client->>S3: 2. Upload file via Multi-part POST
    S3-->>Client: Confirm Upload (204 No Content)
    Client->>Saras: 3. Finalize Upload (POST /knowledges/closeSignedStorage)
    Saras-->>Client: Return completed File metadata
```

***

### Step 1: Initiate Upload

Call the `createSignedStorage` endpoint to register the file and obtain a temporary pre-signed S3 upload URL.

#### Endpoint

`POST /v1/process/knowledges/createSignedStorage`

#### Body Parameters

<ParamField body="subProjectId" type="string" placeholder="sp_123" required>
  The unique identifier for the sub-project.
</ParamField>

<ParamField body="fileName" type="string" placeholder="contract_archive.zip" required>
  The target name of the file to create.
</ParamField>

<ParamField body="mimeType" type="string" placeholder="application/zip" required>
  Mime-type of the file being uploaded.
</ParamField>

<ParamField body="pluginName" type="string" placeholder="knowledgeRepo" required>
  The target storage plugin.
</ParamField>

#### Response Fields

<ResponseField name="file" type="object">
  <Expandable title="properties">
    <ResponseField name="id" type="string">
      The unique identifier reserved for the file.
    </ResponseField>

    <ResponseField name="fileName" type="string">
      The name of the file.
    </ResponseField>

    <ResponseField name="locked" type="boolean">
      The initial lock state of the file (will remain `true` until closed).
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="aws" type="object">
  <Expandable title="AWS Upload Details">
    <ResponseField name="url" type="string">
      The S3 POST endpoint URL to send the file to.
    </ResponseField>

    <ResponseField name="fields" type="object">
      The required form fields (signature, policy, keys, token) to include in the multi-part form POST request.
    </ResponseField>
  </Expandable>
</ResponseField>

#### Request Example

```bash theme={null}
curl --location 'https://api.sarasfinance.com/v1/process/knowledges/createSignedStorage' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data '{
    "subProjectId": "93d599a6-a396-4ef6-b30e-aff95c56c523",
    "fileName": "evidence.mp4",
    "mimeType": "video/mp4",
    "pluginName": "knowledgeRepo"
}'
```

#### Response Example

```json theme={null}
{
  "file": {
    "id": "file_a781b2e9",
    "fileName": "evidence.mp4",
    "locked": true
  },
  "aws": {
    "url": "https://gf-saras-storage.s3.amazonaws.com/",
    "fields": {
      "key": "uploads/evidence.mp4",
      "AWSAccessKeyId": "AKIAIOSFODNN7EXAMPLE",
      "policy": "eyJleHBpcmF0aW9uIjogIjIwMjY...",
      "signature": "vjbyPxybdZaNmGaEXAMPLE="
    }
  }
}
```

***

### Step 2: Upload File to S3

Perform a standard HTTP multi-part form POST request to the AWS S3 URL returned in Step 1. You **must** include all key-value pairs from the `aws.fields` object as form fields, and append the `file` field last.

#### Request Example

```bash theme={null}
curl --location --request POST 'https://gf-saras-storage.s3.amazonaws.com/' \
--form 'key="uploads/evidence.mp4"' \
--form 'AWSAccessKeyId="AKIAIOSFODNN7EXAMPLE"' \
--form 'policy="eyJleHBpcmF0aW9uIjogIjIwMjY..."' \
--form 'signature="vjbyPxybdZaNmGaEXAMPLE="' \
--form 'file=@"/path/to/evidence.mp4"'
```

***

### Step 3: Finalize Upload

After S3 responds with a successful upload status code (`204 No Content`), call the `closeSignedStorage` endpoint to verify the file's presence, unlock it, and retrieve its complete metadata.

#### Endpoint

`POST /v1/process/knowledges/closeSignedStorage`

#### Body Parameters

<ParamField body="subProjectId" type="string" placeholder="sp_123" required>
  The unique identifier for the sub-project.
</ParamField>

<ParamField body="fileId" type="string" placeholder="file_a781b2e9" required>
  The unique ID of the file record to close.
</ParamField>

#### Response Fields

<ResponseField name="file" type="object">
  <Expandable title="properties">
    <ResponseField name="id" type="string">
      The unique identifier for the file.
    </ResponseField>

    <ResponseField name="fileName" type="string">
      The final filename.
    </ResponseField>

    <ResponseField name="size" type="string">
      Total size of the uploaded file in bytes.
    </ResponseField>

    <ResponseField name="locked" type="boolean">
      The finalized lock state of the file (will be unlocked: `false`).
    </ResponseField>
  </Expandable>
</ResponseField>

#### Request Example

```bash theme={null}
curl --location 'https://api.sarasfinance.com/v1/process/knowledges/closeSignedStorage' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data '{
    "subProjectId": "93d599a6-a396-4ef6-b30e-aff95c56c523",
    "fileId": "file_a781b2e9"
}'
```

#### Response Example

```json theme={null}
{
  "file": {
    "id": "file_a781b2e9",
    "fileName": "evidence.mp4",
    "size": "52428800",
    "locked": false
  }
}
```

***

### Error Codes

| Code                                       | ID   | Description                               |
| :----------------------------------------- | :--- | :---------------------------------------- |
| `ERROR_PROCESS_META_IS_MISSING_IN_REQUEST` | 1200 | Metadata missing in request               |
| `ERROR_SUBPROCESS_META_NOT_FOUND`          | 1202 | Sub-project metadata not found            |
| `ERROR_FILE_ID_NOT_FOUND`                  | 1704 | File ID does not exist                    |
| `ERROR_STORAGE_PRESIGN_FAILED`             | 1709 | S3 URL generation failed                  |
| `ERROR_STORAGE_CLOSE_FAILED`               | 1715 | Verification or closure of storage failed |
