> For the complete documentation index, see [llms.txt](https://docs.rememberizer.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.rememberizer.ai/es/recursos-para-desarrolladores/api-docs/vector-store/upload-files-to-a-vector-store.md).

# Subir archivos a un Almacén de Vectores

{% openapi src="/files/5V7ybptH1vsfKadO6dio" path="/vector-stores/{vector-store-id}/documents/upload" method="post" %}
[rememberizer\_openapi.yml](https://983989491-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeFTiuIsKOMpUEE73g7bP%2Fuploads%2Fgit-blob-77b6137eeb641262ec8e531c78123c02b825b865%2Frememberizer_openapi.yml?alt=media\&token=03079f98-60fe-4914-9e1b-443e008fd108)
{% endopenapi %}

## Ejemplos de Solicitudes

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST \
  https://api.rememberizer.ai/api/v1/vector-stores/vs_abc123/documents/upload \
  -H "x-api-key: YOUR_API_KEY" \
  -F "files=@/path/to/document1.pdf" \
  -F "files=@/path/to/document2.docx"
```

{% hint style="info" %}
Reemplace `YOUR_API_KEY` con su clave API real de Vector Store, `vs_abc123` con su ID de Vector Store, y proporcione las rutas a sus archivos locales.
{% endhint %}
{% endtab %}

{% tab title="JavaScript" %}

```javascript
const uploadFiles = async (vectorStoreId, files) => {
  const formData = new FormData();
  
  // Agregar múltiples archivos a los datos del formulario
  for (const file of files) {
    formData.append('files', file);
  }
  
  const response = await fetch(`https://api.rememberizer.ai/api/v1/vector-stores/${vectorStoreId}/documents/upload`, {
    method: 'POST',
    headers: {
      'x-api-key': 'YOUR_API_KEY'
      // Nota: No establezca el encabezado Content-Type, se establecerá automáticamente con el límite correcto
    },
    body: formData
  });
  
  const data = await response.json();
  console.log(data);
};

// Ejemplo de uso con el elemento de entrada de archivo
const fileInput = document.getElementById('fileInput');
uploadFiles('vs_abc123', fileInput.files);
```

{% hint style="info" %}
Reemplace `YOUR_API_KEY` con su clave API real de Vector Store y `vs_abc123` con su ID de Vector Store.
{% endhint %}
{% endtab %}

{% tab title="Python" %}

```python
import requests

def upload_files(vector_store_id, file_paths):
    headers = {
        "x-api-key": "YOUR_API_KEY"
    }
    
    files = [('files', (file_path.split('/')[-1], open(file_path, 'rb'))) for file_path in file_paths]
    
    response = requests.post(
        f"https://api.rememberizer.ai/api/v1/vector-stores/{vector_store_id}/documents/upload",
        headers=headers,
        files=files
    )
    
    data = response.json()
    print(data)

upload_files('vs_abc123', ['/path/to/document1.pdf', '/path/to/document2.docx'])
```

{% hint style="info" %}
Reemplace `YOUR_API_KEY` con su clave API real de Vector Store, `vs_abc123` con su ID de Vector Store, y proporcione las rutas a sus archivos locales.
{% endhint %}
{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'net/http'
require 'uri'
require 'json'

def upload_files(vector_store_id, file_paths)
  uri = URI("https://api.rememberizer.ai/api/v1/vector-stores/#{vector_store_id}/documents/upload")
  
  # Crear un nuevo objeto HTTP
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  
  # Crear una solicitud de formulario multipart
  request = Net::HTTP::Post.new(uri)
  request['x-api-key'] = 'YOUR_API_KEY'
  
  # Crear un límite multipart
  boundary = "RubyFormBoundary#{rand(1000000)}"
  request['Content-Type'] = "multipart/form-data; boundary=#{boundary}"
  
  # Construir el cuerpo de la solicitud
  body = []
  file_paths.each do |file_path|
    file_name = File.basename(file_path)
    file_content = File.read(file_path, mode: 'rb')
    
    body << "--#{boundary}\r\n"
    body << "Content-Disposition: form-data; name=\"files\"; filename=\"#{file_name}\"\r\n"
    body << "Content-Type: #{get_content_type(file_name)}\r\n\r\n"
    body << file_content
    body << "\r\n"
  end
  body << "--#{boundary}--\r\n"
  
  request.body = body.join
  
  # Enviar la solicitud
  response = http.request(request)
  
  # Analizar y devolver la respuesta
  JSON.parse(response.body)
end
```

## Método auxiliar para determinar el tipo de contenido

def get\_content\_type(filename) ext = File.extname(filename).downcase case ext when '.pdf' then 'application/pdf' when '.doc' then 'application/msword' when '.docx' then 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' when '.txt' then 'text/plain' when '.md' then 'text/markdown' when '.json' then 'application/json' else 'application/octet-stream' end end

## Ejemplo de uso

result = upload\_files('vs\_abc123', \['/path/to/document1.pdf', '/path/to/document2.docx']) puts result

````

{% hint style="info" %}
Reemplace `YOUR_API_KEY` con su clave API real de Vector Store, `vs_abc123` con su ID de Vector Store, y proporcione las rutas a sus archivos locales.
{% endhint %}
{% endtab %}
{% endtabs %}

## Parámetros de Ruta

| Parámetro          | Tipo   | Descripción                                                       |
|--------------------|--------|------------------------------------------------------------------|
| vector-store-id    | string | **Requerido.** El ID de la tienda de vectores a la que subir archivos. |

## Cuerpo de la Solicitud

Este endpoint acepta una solicitud `multipart/form-data` con uno o más archivos en el campo `files`.

## Formato de Respuesta

```json
{
  "documents": [
    {
      "id": 1234,
      "name": "document1.pdf",
      "type": "application/pdf",
      "size": 250000,
      "status": "processing",
      "created": "2023-06-15T10:15:00Z",
      "vector_store": "vs_abc123"
    },
    {
      "id": 1235,
      "name": "document2.docx",
      "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
      "size": 180000,
      "status": "processing",
      "created": "2023-06-15T10:15:00Z",
      "vector_store": "vs_abc123"
    }
  ],
  "errors": []
}
````

Si algunos archivos no se pueden cargar, se enumerarán en el array `errors`:

```json
{
  "documents": [
    {
      "id": 1234,
      "name": "document1.pdf",
      "type": "application/pdf",
      "size": 250000,
      "status": "processing",
      "created": "2023-06-15T10:15:00Z",
      "vector_store": "vs_abc123"
    }
  ],
  "errors": [
    {
      "file": "document2.docx",
      "error": "Formato de archivo no soportado"
    }
  ]
}
```

### Autenticación

Este endpoint requiere autenticación utilizando una clave API en el encabezado `x-api-key`.

### Formatos de Archivo Soportados

* PDF (`.pdf`)
* Microsoft Word (`.doc`, `.docx`)
* Microsoft Excel (`.xls`, `.xlsx`)
* Microsoft PowerPoint (`.ppt`, `.pptx`)
* Archivos de texto (`.txt`)
* Markdown (`.md`)
* JSON (`.json`)
* HTML (`.html`, `.htm`)

### Límites de Tamaño de Archivo

* Límite de tamaño de archivo individual: 50MB
* Límite de tamaño total de solicitud: 100MB
* Número máximo de archivos por solicitud: 20

### Respuestas de Error

| Código de Estado | Descripción                                                                          |
| ---------------- | ------------------------------------------------------------------------------------ |
| 400              | Solicitud Incorrecta - No se proporcionaron archivos o formato de solicitud inválido |
| 401              | No Autorizado - Clave API inválida o faltante                                        |
| 404              | No Encontrado - Almacén de Vectores no encontrado                                    |
| 413              | Carga Útil Demasiado Grande - Los archivos exceden el límite de tamaño               |
| 415              | Tipo de Medio No Compatible - Formato de archivo no soportado                        |
| 500              | Error Interno del Servidor                                                           |
| 207              | Multi-Estado - Algunos archivos se subieron con éxito, pero otros fallaron           |

### Estado del Procesamiento

Los archivos son aceptados inicialmente con un estado de `processing`. Puedes verificar el estado de procesamiento de los documentos utilizando el endpoint [Get a List of Documents in a Vector Store](/es/recursos-para-desarrolladores/api-docs/vector-store/get-a-list-of-documents-in-a-vector-store.md). El estado final será uno de:

* `done`: El documento fue procesado con éxito
* `error`: Ocurrió un error durante el procesamiento
* `processing`: El documento aún se está procesando

El tiempo de procesamiento depende del tamaño y la complejidad del archivo. El tiempo de procesamiento típico es de entre 30 segundos a 5 minutos por documento.

### Operaciones por Lotes

Para cargar eficientemente múltiples archivos en su Almacén de Vectores, Rememberizer admite operaciones por lotes. Este enfoque ayuda a optimizar el rendimiento al tratar con grandes cantidades de documentos.

#### Implementación de Carga por Lotes

{% tabs %} {% tab title="Python" %}

```python
import os
import requests
import time
import concurrent.futures
from pathlib import Path

def batch_upload_to_vector_store(vector_store_id, folder_path, batch_size=5, file_types=None):
    """
    Cargar todos los archivos de un directorio a un Almacén de Vectores en lotes
    
    Args:
        vector_store_id: ID del almacén de vectores
        folder_path: Ruta a la carpeta que contiene los archivos a cargar
        batch_size: Número de archivos a cargar en cada lote
        file_types: Lista opcional de extensiones de archivo para filtrar (por ejemplo, ['.pdf', '.docx'])
        
    Returns:
        Lista de resultados de carga
    """
    api_key = "YOUR_API_KEY"
    headers = {"x-api-key": api_key}
    
    # Obtener lista de archivos en el directorio
    files = []
    for entry in os.scandir(folder_path):
        if entry.is_file():
            file_path = Path(entry.path)
            # Filtrar por extensión de archivo si se especifica
            if file_types is None or file_path.suffix.lower() in file_types:
                files.append(file_path)
    
    print(f"Se encontraron {len(files)} archivos para cargar")
    results = []
    
    # Procesar archivos en lotes
    for i in range(0, len(files), batch_size):
        batch = files[i:i+batch_size]
        print(f"Procesando lote {i//batch_size + 1}/{(len(files) + batch_size - 1)//batch_size}: {len(batch)} archivos")
        
        # Cargar lote
        upload_files = []
        for file_path in batch:
            upload_files.append(('files', (file_path.name, open(file_path, 'rb'))))
        
        try:
            response = requests.post(
                f"https://api.rememberizer.ai/api/v1/vector-stores/{vector_store_id}/documents/upload",
                headers=headers,
                files=upload_files
            )
            
            # Cerrar todos los manejadores de archivos
            for _, (_, file_obj) in upload_files:
                file_obj.close()
            
            if response.status_code in (200, 201, 207):
                batch_result = response.json()
                results.append(batch_result)
                print(f"Carga de lote exitosa - {len(batch_result.get('documents', []))} documentos procesados")
                
                # Verificar errores
                if batch_result.get('errors') and len(batch_result['errors']) > 0:
                    print(f"Errores encontrados: {len(batch_result['errors'])}")
                    for error in batch_result['errors']:
                        print(f"- {error['file']}: {error['error']}")
            else:
                print(f"La carga del lote falló con el código de estado {response.status_code}: {response.text}")
                results.append({"error": f"La carga del lote falló: {response.text}"})
                
        except Exception as e:
            print(f"Excepción durante la carga por lotes: {str(e)}")
            results.append({"error": str(e)})
            
            # Cerrar cualquier manejador de archivo restante en caso de excepción
            for _, (_, file_obj) in upload_files:
                try:
                    file_obj.close()
                except:
                    pass
        
        # Limitación de tasa - pausa entre lotes
        if i + batch_size < len(files):
            print("Pausando antes del siguiente lote...")
            time.sleep(2)
    
    return results

# Ejemplo de uso
results = batch_upload_to_vector_store(
    'vs_abc123',
    '/ruta/a/la/carpeta/de/documentos',
    batch_size=5,
    file_types=['.pdf', '.docx', '.txt']
)
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
/**
 * Subir archivos a un Vector Store en lotes
 * 
 * @param {string} vectorStoreId - ID del Vector Store
 * @param {FileList|File[]} files - Archivos a subir
 * @param {Object} options - Opciones de configuración
 * @returns {Promise<Array>} - Lista de resultados de la subida
 */
async function batchUploadToVectorStore(vectorStoreId, files, options = {}) {
  const {
    batchSize = 5,
    delayBetweenBatches = 2000,
    onProgress = null
  } = options;
  
  const apiKey = 'YOUR_API_KEY';
  const results = [];
  const fileList = Array.from(files);
  const totalBatches = Math.ceil(fileList.length / batchSize);
  
  console.log(`Preparándose para subir ${fileList.length} archivos en ${totalBatches} lotes`);
  
  // Procesar archivos en lotes
  for (let i = 0; i < fileList.length; i += batchSize) {
    const batch = fileList.slice(i, i + batchSize);
    const batchNumber = Math.floor(i / batchSize) + 1;
    
    console.log(`Procesando lote ${batchNumber}/${totalBatches}: ${batch.length} archivos`);
    
    if (onProgress) {
      onProgress({
        currentBatch: batchNumber,
        totalBatches: totalBatches,
        filesInBatch: batch.length,
        totalFiles: fileList.length,
        completedFiles: i
      });
    }
    
    // Crear FormData para este lote
    const formData = new FormData();
    batch.forEach(file => {
      formData.append('files', file);
    });
    
    try {
      const response = await fetch(
        `https://api.rememberizer.ai/api/v1/vector-stores/${vectorStoreId}/documents/upload`,
        {
          method: 'POST',
          headers: {
            'x-api-key': apiKey
          },
          body: formData
        }
      );
      
      if (response.ok) {
        const batchResult = await response.json();
        results.push(batchResult);
        
        console.log(`Lote subido con éxito - ${batchResult.documents?.length || 0} documentos procesados`);
        
        // Verificar errores
        if (batchResult.errors && batchResult.errors.length > 0) {
          console.warn(`Errores encontrados: ${batchResult.errors.length}`);
          batchResult.errors.forEach(error => {
            console.warn(`- ${error.file}: ${error.error}`);
          });
        }
      } else {
        console.error(`La subida del lote falló con estado ${response.status}: ${await response.text()}`);
        results.push({ error: `Lote fallido con estado: ${response.status}` });
      }
    } catch (error) {
      console.error(`Excepción durante la subida del lote: ${error.message}`);
      results.push({ error: error.message });
    }
    
    // Agregar retraso entre lotes para evitar limitaciones de tasa
    if (i + batchSize < fileList.length) {
      console.log(`Pausando por ${delayBetweenBatches}ms antes del siguiente lote...`);
      await new Promise(resolve => setTimeout(resolve, delayBetweenBatches));
    }
  }
  
  console.log(`Subida completa. Se procesaron ${fileList.length} archivos.`);
  return results;
}

// Ejemplo de uso con elemento de entrada de archivo
document.getElementById('upload-button').addEventListener('click', async () => {
  const fileInput = document.getElementById('file-input');
  const vectorStoreId = 'vs_abc123';
  
  const progressBar = document.getElementById('progress-bar');
  
  try {
    const results = await batchUploadToVectorStore(vectorStoreId, fileInput.files, {
      batchSize: 5,
      onProgress: (progress) => {
        // Actualizar la interfaz de progreso
        const percentage = Math.round((progress.completedFiles / progress.totalFiles) * 100);
        progressBar.style.width = `${percentage}%`;
        progressBar.textContent = `${percentage}% (Lote ${progress.currentBatch}/${progress.totalBatches})`;
      }
    });
    
    console.log('Resultados de la subida completa:', results);
  } catch (error) {
    console.error('La subida falló:', error);
  }
});
```

{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'net/http'
require 'uri'
require 'json'
require 'mime/types'

# Subir archivos a un Almacén de Vectores en lotes
#
# @param vector_store_id [String] ID de la tienda de vectores
# @param folder_path [String] Ruta a la carpeta que contiene los archivos a subir
# @param batch_size [Integer] Número de archivos a subir en cada lote
# @param file_types [Array<String>] Array opcional de extensiones de archivo para filtrar
# @param delay_between_batches [Float] Segundos a esperar entre lotes
# @return [Array] Lista de resultados de carga
def batch_upload_to_vector_store(vector_store_id, folder_path, batch_size: 5, file_types: nil, delay_between_batches: 2.0)
  api_key = 'YOUR_API_KEY'
  results = []
  
  # Obtener lista de archivos en el directorio
  files = Dir.entries(folder_path)
    .select { |f| File.file?(File.join(folder_path, f)) }
    .select { |f| file_types.nil? || file_types.include?(File.extname(f).downcase) }
    .map { |f| File.join(folder_path, f) }
  
  puts "Encontrados #{files.count} archivos para cargar"
  total_batches = (files.count.to_f / batch_size).ceil
  
  # Procesar archivos en lotes
  files.each_slice(batch_size).with_index do |batch, batch_index|
    puts "Procesando lote #{batch_index + 1}/#{total_batches}: #{batch.count} archivos"
    
    # Preparar la solicitud HTTP
    uri = URI("https://api.rememberizer.ai/api/v1/vector-stores/#{vector_store_id}/documents/upload")
    request = Net::HTTP::Post.new(uri)
    request['x-api-key'] = api_key
    
    # Crear un límite de formulario multipart
    boundary = "RubyBoundary#{rand(1000000)}"
    request['Content-Type'] = "multipart/form-data; boundary=#{boundary}"
    
    # Construir el cuerpo de la solicitud
    body = []
    batch.each do |file_path|
      file_name = File.basename(file_path)
      mime_type = MIME::Types.type_for(file_path).first&.content_type || 'application/octet-stream'
      
      begin
        file_content = File.binread(file_path)
        
        body << "--#{boundary}\r\n"
        body << "Content-Disposition: form-data; name=\"files\"; filename=\"#{file_name}\"\r\n"
        body << "Content-Type: #{mime_type}\r\n\r\n"
        body << file_content
        body << "\r\n"
      rescue => e
        puts "Error al leer el archivo #{file_path}: #{e.message}"
      end
    end
    body << "--#{boundary}--\r\n"
    
    request.body = body.join
    
    # Enviar la solicitud
    begin
      http = Net::HTTP.new(uri.host, uri.port)
      http.use_ssl = true
      response = http.request(request)
      
      if response.code.to_i == 200 || response.code.to_i == 201 || response.code.to_i == 207
        batch_result = JSON.parse(response.body)
        results << batch_result
        
        puts "Carga del lote exitosa - #{batch_result['documents']&.count || 0} documentos procesados"
        
        # Verificar errores
        if batch_result['errors'] && !batch_result['errors'].empty?
          puts "Errores encontrados: #{batch_result['errors'].count}"
          batch_result['errors'].each do |error|
            puts "- #{error['file']}: #{error['error']}"
          end
        end
      else
        puts "La carga del lote falló con el código de estado #{response.code}: #{response.body}"
        results << { "error" => "Lote fallido: #{response.body}" }
      end
    rescue => e
      puts "Excepción durante la carga del lote: #{e.message}"
      results << { "error" => e.message }
    end
    
    # Limitación de tasa - pausa entre lotes
    if batch_index < total_batches - 1
      puts "Pausando durante #{delay_between_batches} segundos antes del siguiente lote..."
      sleep(delay_between_batches)
    end
  end
  
  puts "Carga completa. Procesados #{files.count} archivos."
  results
end

# Ejemplo de uso
results = batch_upload_to_vector_store(
  'vs_abc123',
  '/path/to/documents/folder',
  batch_size: 5,
  file_types: ['.pdf', '.docx', '.txt'],
  delay_between_batches: 2.0
)
```

{% endtab %}
{% endtabs %}

### Mejores Prácticas para Cargas por Lotes

Para optimizar el rendimiento y la fiabilidad al cargar grandes volúmenes de archivos:

1. **Gestionar el Tamaño del Lote**: Mantenga los tamaños de lote entre 5-10 archivos para un rendimiento óptimo. Demasiados archivos en una sola solicitud aumentan el riesgo de tiempos de espera.
2. **Implementar Limitación de Tasa**: Agregue retrasos entre lotes (se recomiendan 2-3 segundos) para evitar alcanzar los límites de tasa de la API.
3. **Agregar Lógica de Reintento de Errores**: Para sistemas de producción, implemente lógica de reintento para cargas fallidas con retroceso exponencial.
4. **Validar Tipos de Archivos**: Pre-filtre los archivos para asegurarse de que sean tipos compatibles antes de intentar la carga.
5. **Monitorear el Progreso del Lote**: Para aplicaciones orientadas al usuario, proporcione retroalimentación sobre el progreso de las operaciones por lotes.
6. **Manejar Éxitos Parciales**: La API puede devolver un código de estado 207 para éxito parcial. Siempre verifique los estados de documentos individuales.
7. **Limpiar Recursos**: Asegúrese de que todos los manejadores de archivos estén cerrados correctamente, especialmente cuando ocurren errores.
8. **Paralelizar con Sabiduría**: Para cargas muy grandes (miles de archivos), considere múltiples procesos de lotes concurrentes que apunten a diferentes almacenes de vectores, luego combine los resultados más tarde si es necesario.
9. **Implementar Sumas de Comprobación**: Para datos críticos, verifique la integridad del archivo antes y después de la carga con sumas de comprobación.
10. **Registrar Resultados Completos**: Mantenga registros detallados de todas las operaciones de carga para la solución de problemas.

Siguiendo estas mejores prácticas, puede gestionar de manera eficiente la ingestión de documentos a gran escala en sus almacenes de vectores.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.rememberizer.ai/es/recursos-para-desarrolladores/api-docs/vector-store/upload-files-to-a-vector-store.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
