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

# Subir Documento

> Sube un documento y opcionalmente asócialo con una entidad y categoría — en la plataforma gu1 para KYC, KYB y evidencia de compliance.

Sube archivos asociados a entidades usando multipart/form-data.

## Autenticación

Este endpoint requiere autenticación mediante token Bearer y contexto de organización.

**Headers Requeridos:**

* `Authorization: Bearer <jwt-token>`
* `X-Organization-ID: <organization-id>`

## Parámetros del Form Data

<ParamField body="file" type="File" required>
  El archivo a subir (cualquier tipo soportado)
</ParamField>

<ParamField body="entityId" type="UUID">
  ID de la entidad a la que asociar el documento
</ParamField>

<ParamField body="categoryId" type="UUID">
  ID de la categoría del documento (UBO, Representante Legal, Corporativo, etc.)
</ParamField>

## Ejemplo de Request

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.gu1.ai/documents/upload \
    -H "Authorization: Bearer TU_JWT_TOKEN" \
    -H "X-Organization-ID: TU_ORG_ID" \
    -F "file=@/ruta/al/documento.pdf" \
    -F "entityId=bb0c2d24-b519-40ec-b765-86de831ca0af" \
    -F "categoryId=c5e9a3f2-1234-5678-9abc-def012345678"
  ```

  ```javascript JavaScript theme={null}
  const formData = new FormData();
  formData.append('file', fileInput.files[0]);
  formData.append('entityId', 'bb0c2d24-b519-40ec-b765-86de831ca0af');
  formData.append('categoryId', 'c5e9a3f2-1234-5678-9abc-def012345678');

  const response = await fetch('https://api.gu1.ai/documents/upload', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,
      'X-Organization-ID': organizationId
    },
    body: formData
  });

  const document = await response.json();
  ```

  ```python Python theme={null}
  import requests

  files = {'file': open('/ruta/al/documento.pdf', 'rb')}
  data = {
      'entityId': 'bb0c2d24-b519-40ec-b765-86de831ca0af',
      'categoryId': 'c5e9a3f2-1234-5678-9abc-def012345678'
  }

  response = requests.post(
      'https://api.gu1.ai/documents/upload',
      headers={
          'Authorization': f'Bearer {token}',
          'X-Organization-ID': org_id
      },
      files=files,
      data=data
  )

  document = response.json()
  ```
</CodeGroup>

## Respuesta

<ResponseField name="id" type="UUID">
  Identificador único del documento
</ResponseField>

<ResponseField name="name" type="string">
  Nombre del documento
</ResponseField>

<ResponseField name="originalFileName" type="string">
  Nombre original del archivo subido
</ResponseField>

<ResponseField name="fileSize" type="number">
  Tamaño del archivo en bytes
</ResponseField>

<ResponseField name="mimeType" type="string">
  Tipo MIME del archivo
</ResponseField>

<ResponseField name="storagePath" type="string">
  Ruta donde se almacena el archivo (clave S3 o ruta local)
</ResponseField>

<ResponseField name="storageProvider" type="string">
  Proveedor de almacenamiento usado ('s3' o 'local')
</ResponseField>

<ResponseField name="categoryId" type="UUID">
  ID de la categoría del documento (si se asignó)
</ResponseField>

<ResponseField name="organizationId" type="UUID">
  ID de la organización propietaria del documento
</ResponseField>

<ResponseField name="createdAt" type="timestamp">
  Fecha de creación del documento
</ResponseField>

## Ejemplo de Respuesta

```json theme={null}
{
  "id": "d7f8e9c0-1234-5678-9abc-def012345678",
  "name": "document.pdf",
  "description": "Documento subido: document.pdf",
  "type": "other",
  "fileName": "1730649606123_document.pdf",
  "originalFileName": "document.pdf",
  "fileSize": 245678,
  "mimeType": "application/pdf",
  "fileExtension": "pdf",
  "storagePath": "/uploads/1730649606123_document.pdf",
  "storageProvider": "local",
  "securityLevel": "internal",
  "categoryId": "c5e9a3f2-1234-5678-9abc-def012345678",
  "organizationId": "24236b0a-e34d-4218-b3d2-76b101ce8aa9",
  "createdBy": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
  "createdAt": "2025-11-03T15:30:45.123Z",
  "updatedAt": "2025-11-03T15:30:45.123Z"
}
```

## Qué Sucede Después de la Subida

1. **Almacenamiento**: El archivo se sube a S3 (si está habilitado) o almacenamiento local
2. **Registro en Base de Datos**: Se crea el registro del documento en la base de datos
3. **Versionamiento**: Se crea automáticamente la versión inicial (v1)
4. **Relación con Entidad**: Si se proporciona `entityId`, se crea la relación automáticamente
5. **Análisis de Riesgo**: Se activa el análisis automático de riesgo si hay reglas configuradas

## Tipos de Archivo Soportados

* **Documentos**: PDF, DOC, DOCX, TXT
* **Imágenes**: PNG, JPG, JPEG, GIF
* **Hojas de Cálculo**: XLS, XLSX, CSV
* **Otros**: Cualquier tipo de archivo

## Categorías de Documentos

Para obtener las categorías disponibles, usa:

```bash theme={null}
GET /documents/categories
```

Categorías comunes incluyen:

* **UBO (Beneficiario Final)**
* **Representante Legal**
* **Documentos Corporativos**
* **Debida Diligencia Reforzada**

## Respuestas de Error

<ResponseField name="400" type="error">
  Bad Request - Falta archivo o autenticación

  ```json theme={null}
  {
    "error": "No file provided"
  }
  ```
</ResponseField>

<ResponseField name="401" type="error">
  No Autorizado - Token inválido

  ```json theme={null}
  {
    "error": "Unauthorized - No token provided"
  }
  ```
</ResponseField>

<ResponseField name="500" type="error">
  Error Interno del Servidor

  ```json theme={null}
  {
    "error": "Error interno del servidor",
    "details": "Mensaje de error aquí"
  }
  ```
</ResponseField>

## Notas

<Note>
  El sistema detecta automáticamente si el almacenamiento S3 está configurado y lo usa, de lo contrario usa almacenamiento local.
</Note>

<Warning>
  El tamaño máximo del archivo depende de la configuración del servidor (típicamente 50MB).
</Warning>

<Tip>
  Incluso si `entityId` o `categoryId` no existen, el documento se creará de todos modos. La relación o asignación de categoría simplemente se omitirá.
</Tip>
