---
seo_title: API OTS a PDF: convierte plantillas de Calc a PDF | EnConvert
meta_desc: Convierte plantillas de hoja de cálculo OpenDocument (.ots) a PDF con POST /v1/convert/ots-to-pdf. Renderizado con LibreOffice, bytes PDF o URL prefirmada.
keywords: api ots a pdf, convertir ots a pdf api, convertir ots a pdf python, plantilla de calc a pdf api, api rest ots a pdf, plantilla opendocument a pdf api, convertir archivo ots a pdf, ots a pdf libreoffice api
---

# API de OTS a PDF

La API de OTS a PDF convierte archivos de plantilla de hoja de cálculo OpenDocument (`.ots`, el formato de plantilla de hoja de cálculo de LibreOffice y OpenOffice Calc) a PDF a través del endpoint `POST /v1/convert/ots-to-pdf`. Sube un archivo `.ots` como `multipart/form-data` y recibe los bytes del PDF sin procesar, o establece `direct_download=false` para obtener metadatos JSON con una URL de descarga prefirmada. El renderizado lo realiza LibreOffice en el servidor, por lo que el formato, las fuentes y el diseño propios de la plantilla se conservan en el PDF de salida.

---

## Endpoint

```
POST /v1/convert/ots-to-pdf
```

**Content-Type:** `multipart/form-data`

**Entrada aceptada:** archivos `.ots`

**Formato de salida:** `.pdf` (`application/pdf`)

---

## Autenticación

Requiere una clave API privada o un token JWT obtenido de una clave pública.

```
X-API-Key: sk_your_private_key
```

O bien:

```
Authorization: Bearer <jwt_token>
```

---

## Parámetros de la solicitud

| Parámetro | Tipo | Obligatorio | Predeterminado | Descripción |
|-----------|------|----------|---------|-------------|
| `file` | file | Sí | -- | El archivo `.ots` a convertir. |
| `output_filename` | `string` | No | Nombre del archivo de entrada | Nombre de archivo de salida personalizado. La extensión `.pdf` se añade automáticamente. |
| `direct_download` | `boolean` | No | `true` | Con `true`, devuelve los bytes del PDF sin procesar. Con `false`, devuelve metadatos JSON con una URL de descarga prefirmada. |
| `pdf_options` | `string` | No | `null` | Cadena JSON. Este endpoint solo admite la opción `grayscale` (ver más abajo). |

### Opciones de PDF

En los conversores de documentos basados en LibreOffice, el diseño de página (tamaño, márgenes, orientación) lo determina la configuración del propio documento. El único campo de `pdf_options` que aplica es:

| Parámetro | Tipo | Predeterminado | Descripción |
|-----------|------|---------|-------------|
| `grayscale` | `boolean` | `false` | Convierte el PDF de salida a escala de grises mediante posprocesado con Ghostscript. |

<div class="alert alert-info">
<strong>Nota:</strong> El tamaño de página, los márgenes, la orientación, la escala, los encabezados y los pies de página de <code>pdf_options</code> no aplican a este endpoint. El PDF de salida conserva el formato definido en el documento original. Para cambiar el diseño de página, modifica el documento de origen antes de subirlo.
</div>

---

## Detalles de la conversión

- Usa **LibreOffice** (vía unoserver) para renderizar los documentos en el servidor
- Se conservan el formato, las fuentes, el diseño de página y los medios incrustados del propio documento
- Tiempo límite de conversión: 120 segundos
- La salida reproduce fielmente el documento tal como se imprimiría desde LibreOffice

---

## Respuesta

### Descarga directa (`direct_download=true`, predeterminado)

```
HTTP 200 OK
Content-Type: application/pdf
Content-Disposition: inline; filename="document_20260405_123456789.pdf"
```

Devuelve los bytes del PDF sin procesar.

### Respuesta con metadatos (`direct_download=false`)

```json
{
    "presigned_url": "https://spaces.example.com/...",
    "object_key": "env/files/{project_id}/ots-to-pdf/document_20260405_123456789.pdf",
    "filename": "document_20260405_123456789.pdf",
    "file_size": 67890,
    "conversion_time_seconds": 3.5
}
```

---

## Ejemplos de código

### Python

```python
import requests

with open("document.ots", "rb") as f:
    response = requests.post(
        "https://api.enconvert.com/v1/convert/ots-to-pdf",
        headers={"X-API-Key": "sk_your_private_key"},
        files={"file": ("document.ots", f)}
    )

with open("output.pdf", "wb") as out:
    out.write(response.content)
```

### Node.js

```javascript
const form = new FormData();
form.append("file", fs.createReadStream("document.ots"));

const response = await fetch("https://api.enconvert.com/v1/convert/ots-to-pdf", {
    method: "POST",
    headers: { "X-API-Key": "sk_your_private_key" },
    body: form
});

fs.writeFileSync("output.pdf", Buffer.from(await response.arrayBuffer()));
```

### PHP

```php
$ch = curl_init("https://api.enconvert.com/v1/convert/ots-to-pdf");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ["X-API-Key: sk_your_private_key"],
    CURLOPT_POSTFIELDS => ["file" => new CURLFile("document.ots")]
]);
$pdf = curl_exec($ch);
curl_close($ch);
file_put_contents("output.pdf", $pdf);
```

### Go

```go
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
part, _ := writer.CreateFormFile("file", "document.ots")
file, _ := os.Open("document.ots")
io.Copy(part, file)
writer.Close()

req, _ := http.NewRequest("POST", "https://api.enconvert.com/v1/convert/ots-to-pdf", body)
req.Header.Set("Content-Type", writer.FormDataContentType())
req.Header.Set("X-API-Key", "sk_your_private_key")
resp, _ := http.DefaultClient.Do(req)
```

### Con salida en escala de grises

```python
import requests
import json

with open("document.ots", "rb") as f:
    response = requests.post(
        "https://api.enconvert.com/v1/convert/ots-to-pdf",
        headers={"X-API-Key": "sk_your_private_key"},
        files={"file": ("document.ots", f)},
        data={"pdf_options": json.dumps({"grayscale": True})}
    )
```

---

## Respuestas de error

| Estado | Condición |
|--------|-----------|
| `400 Bad Request` | El archivo no es un archivo `.ots` |
| `400 Bad Request` | La conversión del documento falló (archivo dañado o no compatible) |
| `400 Bad Request` | JSON de `pdf_options` no válido |
| `401 Unauthorized` | Clave API o token JWT ausente o no válido |
| `402 Payment Required` | Cuota mensual de ops agotada |
| `402 Payment Required` | Límite de almacenamiento alcanzado |
| `413 Payload Too Large` | El archivo supera el tamaño máximo del plan |
| `500 Internal Server Error` | La conversión superó el tiempo límite (120 segundos) |

---

## Límites

| Límite | Valor |
|-------|-------|
| Tamaño máximo de archivo | Según el plan (Founding: 5 MB) |
| Tiempo límite de conversión | 120 segundos |
| Conversiones mensuales | Según el plan |

## Preguntas frecuentes

### ¿Cómo convierto una plantilla de hoja de cálculo OTS a PDF con una API REST?

Envía una solicitud `POST` a `/v1/convert/ots-to-pdf` con el archivo `.ots` en un cuerpo `multipart/form-data`, autenticada con un encabezado `X-API-Key` o un JWT `Authorization: Bearer`. De forma predeterminada, la respuesta contiene los bytes del PDF convertido.

### ¿Puedo convertir archivos de plantilla de LibreOffice u OpenOffice Calc a PDF con esta API?

Sí. El endpoint acepta archivos `.ots`, el formato de plantilla de hoja de cálculo OpenDocument que usan LibreOffice y OpenOffice Calc, y los renderiza en el servidor con LibreOffice, de modo que la salida coincide con cómo se imprimiría el documento desde LibreOffice.

### ¿Puedo obtener una URL de descarga en lugar de los bytes del PDF?

Sí. Establece `direct_download=false` y la API devuelve metadatos JSON que incluyen una `presigned_url`, el `filename` de salida, `file_size` y `conversion_time_seconds`.

### ¿Puedo cambiar el tamaño de página, los márgenes o la orientación del PDF de salida?

No. El diseño de página se toma de la configuración del propio documento OTS; el único campo de `pdf_options` admitido es `grayscale`. Para cambiar el diseño, modifica el documento de origen antes de subirlo.

### ¿Por qué el endpoint ots-to-pdf devuelve 400 Bad Request?

Se devuelve un `400 Bad Request` cuando lo subido no es un archivo `.ots`, cuando el documento está dañado o no es compatible, o cuando el valor de `pdf_options` no es JSON válido.
