# Archivos

Subir entradas y descargar resultados.

Fuente: https://scifig.ai/es/docs/api/files

## Subir

`POST /files` acepta `multipart/form-data` y requiere el ámbito `figures:generate`. Devuelve `201` con `file_id`, `purpose`, `content_type`, `size_bytes`, `expires_at` y `created_at`.

| Campo | Tipo | Obligatorio | Valor predeterminado | Reglas |
| --- | --- | --- | --- | --- |
| file | file | sí | — | Consulta los límites por finalidad más abajo |
| purpose | string | no | `image` | `image`, `mask` o `flowchart_attachment` |

| Finalidad | Aceptado | Se usa en |
| --- | --- | --- |
| image | PNG, JPEG o WebP de hasta 20 MB, comprobado por su contenido y no por el nombre | Edición, detección de texto, ampliación, conversión, imágenes de referencia |
| mask | PNG de hasta 8 MB; el blanco marca la región que se debe redibujar | `POST /images/edits` |
| flowchart_attachment | Formatos del espacio de trabajo FlowChart, hasta 32 MB | `POST /flowcharts/generations` |

Las subidas pueden usarse durante 24 horas; después, el `file_id` es desconocido: `400 INVALID_REQUEST`, `FILE_NOT_FOUND`. Solo son entradas: nunca aparecen en las respuestas de tareas ni se comparten con nadie.

Las subidas cuentan para los mismos límites que en el sitio web. Al superarlos, la respuesta es `429 RATE_LIMITED` con `Retry-After` y `details.reason` igual a `UPLOAD_RATE_LIMITED` por minuto o `UPLOAD_DAILY_LIMIT_REACHED` por día para archivos adjuntos de diagramas de flujo.

Una subida puede enviar una cabecera opcional `Idempotency-Key` de 1 a 255 caracteres ASCII visibles. La misma cuenta, clave y `purpose` siempre corresponden a un único `file_id`: repetirla devuelve el primer archivo con `201`, sin volver a subirlo ni consumir el límite. La misma clave y `purpose` con bytes diferentes devuelve `409 IDEMPOTENCY_CONFLICT`. Sin cabecera, cada subida crea un archivo nuevo. Si esa subida ha caducado, repetirla devuelve `400 INVALID_REQUEST` con `details.reason = FILE_EXPIRED`; súbela de nuevo con una clave nueva.

## Descargar

Cada resultado tiene un `download_url` que funciona sin credenciales durante una hora; consulta la tarea de nuevo para obtener otro enlace. `GET /files/{file_id}` con tus credenciales descarga cualquiera de tus archivos. Los archivos siempre se sirven como adjuntos.

Un `download_url` firmado devuelve `404 NOT_FOUND` cuando caduca o si se modifica; todos los enlaces de una cuenta bloqueada o en proceso de eliminación dejan de funcionar del mismo modo.

| Resultado | Se puede pasar a |
| --- | --- |
| PNG o JPEG | Todos los puntos de acceso de imagen: edición, detección de texto, ampliación, conversión, imágenes de referencia |
| WebP | Edición, detección de texto, ampliación, vectorización SVG e imágenes de referencia; no conversiones PNG, PDF, TIFF o PPTX |
| SVG de diagrama de flujo | `POST /images/conversions` a PNG, PDF, TIFF o PPTX |
| PDF, TIFF, EPS, PPTX y otros SVG | Ninguno: solo descarga |

Una fuente de conversión de más de 20 MB, por ejemplo una ampliación 8K, se rechaza con `400 INVALID_REQUEST` y `FILE_TOO_LARGE`.

## cURL

```bash
curl -X POST https://scifig.ai/api/v1/files \
  -H "Authorization: Bearer $SCIFIG_API_KEY" \
  -F "file=@figure.png" \
  -F "purpose=image"
```

## JavaScript

```javascript
import { readFile } from 'node:fs/promises';

const form = new FormData();
form.set('file', new Blob([await readFile('figure.png')]), 'figure.png');
form.set('purpose', 'image');

const response = await fetch('https://scifig.ai/api/v1/files', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.SCIFIG_API_KEY}`,
  },
  body: form,
});
const result = await response.json();
console.log(response.status, result);
```

## Python

```python
import os

import requests

headers = {
    "Authorization": f"Bearer {os.environ['SCIFIG_API_KEY']}",
}
response = requests.post(
    "https://scifig.ai/api/v1/files",
    headers=headers,
    files={"file": open("figure.png", "rb")},
    data={"purpose": "image"},
    timeout=60,
)
print(response.status_code, response.json())
```
