Files API y PDF
Files API de GetVibe API compatible con OpenAI y entrada de PDF: base64, un enlace o un file_id en chat/completions, responses y messages; qué modelos ven las imágenes dentro de un PDF, límites y errores.
Files API compatible con OpenAI para cargar, leer y eliminar archivos. Cada operación requiere una clave de API; solo la misma cuenta cliente que cargó un archivo puede acceder a él.
Subir un archivo
Envía multipart/form-data con los campos obligatorios file y purpose. Propósitos permitidos: assistants, batch, fine-tune, vision y user_data. El tamaño máximo del archivo es de 50 MiB (52 428 800 bytes); superarlo devuelve 413.
curl -X POST https://getvibeapi.com/v1/files \
-H "Authorization: Bearer $GETVIBE_API_KEY" \
-F "purpose=user_data" \
-F "file=@./report.pdf"Obtener metadatos, contenido o eliminar
La carga devuelve un objeto file con un id opaco, name, size, purpose y hora de creación. GET sin /content devuelve estos metadatos; GET /content descarga los bytes sin procesar. Después de un DELETE correcto, ambas solicitudes GET devuelven 404. Un archivo existente de otra cuenta devuelve 403, y un identificador desconocido devuelve 404.
Flujo de trabajo seguro
- Sube el archivo y conserva solo el
file_iddevuelto. - Verifica los metadatos con la misma clave; cuando trabajes con Responses, pasa este id. en
input_file.file_id. - No subas secretos y elimina el archivo después de terminar. Un archivo eliminado no se puede restaurar.
PDF en solicitudes a modelos
Todos los modelos de texto aceptan PDF en los tres formatos de API. En resumen: envía el archivo de cualquiera de las tres formas que se indican a continuación; de forma predeterminada, extraemos el texto gratis y se lo pasamos al modelo. El modelo lee el texto y las tablas, pero no las imágenes dentro del PDF ni los escaneos. Cuando importen las imágenes, el diseño o un escaneo, elige un modelo de la tabla de abajo y desactiva la extracción de texto. Todo lo que aparece en esta página se verificó con solicitudes reales el 2 de noviembre de 2026, usando un PDF de tres páginas con texto, una tabla y una imagen.
Tres formas de enviar un PDF
| Método | Cómo | Cuándo usarlo |
|---|---|---|
| base64 en la solicitud | Chat: {"type":"file","file":{"filename":"report.pdf","file_data":"data:application/pdf;base64,…"}}; Responses: {"type":"input_file","filename":"report.pdf","file_data":"data:…"}; Messages: {"type":"document","source":{"type":"base64","media_type":"application/pdf","data":"…"}} | Un documento para usar una sola vez. Funciona en los tres endpoints. Archivos de hasta 20 MiB. |
| Enlace público | Chat: "file":{"file_url":"https://…"}; Responses: {"type":"input_file","file_url":"https://…"}; Messages: "source":{"type":"url","url":"https://…"} | El archivo ya está en línea. Lo descargamos nosotros: solo HTTPS, sin usuario ni contraseña, el servidor debe responder con application/pdf, hasta 20 MiB, en un plazo de 10 segundos y con un máximo de 3 redirecciones. |
file_id después de subirlo | Sube el archivo con POST /v1/files y purpose=user_data y luego usa: Chat "file":{"file_id":"file-pv-…"}, Responses {"type":"input_file","file_id":"file-pv-…"}, Messages "source":{"type":"file","file_id":"file-pv-…"} | Un documento para varias solicitudes: no hace falta volver a enviar megabytes cada vez y el prefijo idéntico de la solicitud se almacena en caché. El archivo se conserva durante 7 días y solo está visible para tu cuenta. |
Ejemplos listos para ejecutar
La clave se lee de la variable de entorno GETVIBE_API_KEY. Los ejemplos de Python usan los SDK oficiales openai y anthropic sin modificaciones; solo cambia la dirección.
/v1/chat/completions
# PDF inline (base64); jq builds the body so a large file does not hit the command-line length limit
# macOS: replace base64 -w0 report.pdf with base64 -i report.pdf
jq -n --rawfile b64 <(base64 -w0 report.pdf) '{model: "deepseek-v4.1-flash", messages: [{role: "user", content: [
{type: "text", text: "Summarise the document"},
{type: "file", file: {filename: "report.pdf", file_data: ("data:application/pdf;base64," + $b64)}}]}]}' |
curl https://getvibeapi.com/v1/chat/completions \
-H "Authorization: Bearer $GETVIBE_API_KEY" -H "Content-Type: application/json" -d @-/v1/responses
# FILE_ID comes from the upload, see the "curl · file_id" tab above
curl https://getvibeapi.com/v1/responses \
-H "Authorization: Bearer $GETVIBE_API_KEY" -H "Content-Type: application/json" \
-d '{"model":"gpt-6.1-sol","input":[{"role":"user","content":[
{"type":"input_text","text":"What were the sales in Kazan in August?"},
{"type":"input_file","file_id":"'"$FILE_ID"'"}]}]}'
# base64 instead of file_id:
# {"type":"input_file","filename":"report.pdf","file_data":"data:application/pdf;base64,…"}/v1/messages
curl https://getvibeapi.com/v1/messages \
-H "x-api-key: $GETVIBE_API_KEY" -H "anthropic-version: 2023-06-01" -H "Content-Type: application/json" \
-d '{"model":"claude-sonnet-5.5","max_tokens":1024,"messages":[{"role":"user","content":[
{"type":"document","source":{"type":"file","file_id":"'"$FILE_ID"'"}},
{"type":"text","text":"Summarise the document"}]}]}'
# other sources:
# "source":{"type":"base64","media_type":"application/pdf","data":"<base64>"}
# "source":{"type":"url","url":"https://example.com/report.pdf"}Qué ve el modelo: el texto o el archivo en sí
De forma predeterminada, se extrae el texto. Tomamos la capa de texto del PDF y se la pasamos al modelo en lugar del archivo. Es gratis y funciona con cualquier modelo, incluso con uno que no admite PDF. El modelo ve palabras y números, incluidas las tablas (sin bordes, pero con los valores correctos). Lo que no ve: imágenes, gráficos, sellos, firmas, colores y diseño. Se pasan hasta 60,000 caracteres de texto por solicitud (unas 28 páginas densas); el resto se recorta y se le indica al modelo que el documento se truncó. El encabezado de respuesta x-pv-document-shim indica qué ocurrió: applied:text_extracted significa que el modelo recibió el texto; not-needed:lane_reads_pdf, que recibió el archivo.
El archivo en sí. Para que el modelo vea páginas completas, con imágenes y diseño, agrega "plugins":[{"id":"documents","enabled":false}] al cuerpo de la solicitud (el encabezado entonces muestra not-needed:disabled_by_client). Hazlo solo con los modelos marcados como «sí» en la tabla: los demás responden con 400 o indican que no ven ningún archivo, y los tokens de entrada del archivo se siguen facturando.
# curl: add the field to the request body
"plugins": [{"id": "documents", "enabled": false}]
# Python (openai SDK)
r = client.chat.completions.create(
model="gpt-6.1-sol",
messages=[...],
extra_body={"plugins": [{"id": "documents", "enabled": False}]},
)| Modelo | De forma predeterminada | Ve el archivo en sí (extracción desactivada) |
|---|---|---|
gpt-6.1-sol | el archivo en sí | sí — en /chat/completions y /responses |
gpt-6-luna | text | sí — en /chat/completions y /responses |
gpt-5.6-sol | text | no confirmado — mantén el valor predeterminado |
claude-sonnet-5.5, claude-opus-5.5 | text | no — el modelo no puede ver el archivo, así que extraemos el texto incluso con el plugin desactivado (encabezado x-getvibe-warnings: plugin_overridden:documents); para el archivo en sí, usa gpt-6.1-sol |
claude-haiku-5.5 | text | no — el modelo no ve el archivo |
gemini-4-argon, gemini-3.8-flash | text | no — el modelo no ve el archivo, o 400 |
qwen3.8-flash | text | sí — en /chat/completions; 400 en /responses |
deepseek-v4.1-flash, glm-5.3, kimi-k3 | text | no — 400 |
Cómo hicimos las pruebas: se le pidió al modelo una palabra de la página 1, un número de una celda de la tabla y una descripción de una imagen (formas, colores y un número dibujado como imagen). «Texto» significa que identificó correctamente la palabra y el número, y dijo que no podía ver la imagen. «Sí» significa que también describió correctamente la imagen. Envía PDF a los modelos GPT, Gemini y Qwen mediante /v1/chat/completions o /v1/responses: con /v1/messages no pueden ver el archivo en sí.
not-needed:no_text_layer_unmeasured_lane). En ese caso, depende del modelo: gpt-6.1-sol y qwen3.8-flash leen nuestro escaneo; los modelos DeepSeek responden con 400. Si tu modelo no puede leer un escaneo, ejecuta OCR por tu cuenta y envía el texto, o envía las páginas como imágenes PNG/JPEG mediante image_url a un modelo que acepte imágenes.Límites, tokens y tiempo
| Qué | Límite |
|---|---|
| Un PDF en una solicitud al modelo (base64, enlace o file_id) | hasta 20 MiB por archivo; el archivo debe comenzar con %PDF- |
Subir a POST /v1/files | hasta 50 MiB (52,428,800 bytes), pero solo se puede incluir en una solicitud al modelo un PDF de hasta 20 MiB |
file_id lifetime | 7 días (el campo expires_at); después, el archivo se elimina |
| Páginas | sin límite aparte; con extracción de texto, hasta 60,000 caracteres por solicitud; con el archivo en sí, hasta el tamaño de la ventana de contexto del modelo |
| Descargar mediante enlace | hasta 10 segundos y hasta 3 redirecciones |
Cómo se cuentan los tokens. Un PDF se factura como tokens de entrada normales del modelo elegido, según su precio; no hay un cargo aparte por el archivo ni por extraer el texto. Esto es lo que cuesta (medido, incluida una pregunta breve):
- Texto extraído: aproximadamente 700 tokens por página de texto denso (10 páginas: 7,300 tokens; 40 páginas recortadas a 60,000 caracteres: 20,300 tokens). Una página con una tabla breve: 100–200 tokens.
- El archivo en sí, en modelos GPT: unos 600–700 tokens por página (10 páginas — 5,900; 40 — 23,300); en
gemini-4-argon, unos 1,200 por página; en Claude, unos 1,600 por página. Una página escaneada engpt-6.1-sol: unos 5,800 tokens. - Si repites el mismo documento, se aprovecha la caché cuando el inicio de la solicitud no cambia: en una segunda solicitud con el mismo
file_id, se leyeron 7,168 de 7,309 tokens desde la caché.
Tiempo. La extracción de texto tarda una fracción de segundo; una respuesta sobre un documento de 40 páginas llegó en 4–12 segundos. Para documentos grandes y respuestas largas, usa stream: true y configura el tiempo de espera del cliente en al menos 300 segundos.
Errores y cómo solucionarlos
| Respuesta | Causa | Qué hacer |
|---|---|---|
400 invalid_pdf | The PDF must start with the %PDF- signature. | No es un PDF o el base64 está dañado. Asegúrate de codificar el archivo en sí, no su ruta, y de que el tipo sea application/pdf. |
400 invalid_pdf | The PDF size must not exceed 20 MiB. | Divide el documento o comprime las imágenes que contiene. |
413 invalid_request_error | En POST /v1/files: el archivo supera los 52,428,800 bytes | El archivo supera los 50 MiB: divídelo. |
400 invalid_request_error | El file_id no está disponible | El archivo se eliminó, venció (7 días), lo subió otra cuenta o el id pertenece a otro servicio. Vuelve a subir el archivo con la misma clave. |
400 invalid_pdf | The PDF URL must be a public HTTPS URL without credentials. | El enlace usa http://, incluye un usuario y una contraseña, usa un puerto no estándar o apunta a un dominio inexistente. Proporciona un enlace HTTPS público o envía base64. |
400 invalid_pdf | Could not safely fetch the PDF from the URL. | El enlace devuelve 404, una página de inicio de sesión, HTML en vez de un PDF, o el servidor no respondió en 10 segundos. Abre el enlace en una ventana de navegación privada; si el archivo no se descarga de inmediato, envía base64. |
400 unsupported_input | El modelo no puede leer PDFs y el archivo no contiene texto (es un escaneo). | Usa un modelo que pueda leer escaneos (consulta arriba) o ejecuta OCR por tu cuenta. |
400 invalid_request_error | Invalid request… con la extracción de texto desactivada o con un escaneo. | El modelo no acepta archivos PDF. Elimina plugins documents enabled:false para que el modelo reciba el texto, o elige un modelo marcado con "yes" en la tabla. |
| 200, pero «No veo ningún archivo» | La extracción está desactivada y el modelo o canal no puede leer el archivo. | Vuelve a la extracción de texto predeterminada o elige un modelo marcado como «sí» en la tabla. |
Prácticas recomendadas
- ¿Necesitas usar el documento en varias solicitudes? Súbelo una vez y pasa el
file_id: la solicitud es más pequeña y el prefijo repetido se almacena en caché, lo que reduce el costo. - Coloca el PDF y las instrucciones permanentes al principio del mensaje, y la pregunta que cambia al final: así se aprovecha la caché con más frecuencia.
- Divide por capítulos los documentos de más de ~28 páginas densas: con la extracción de texto, todo lo que supere los 60,000 caracteres nunca llega al modelo.
- Para contratos, informes y exportaciones con una capa de texto, basta con extraer el texto: es la opción más económica con cualquier modelo, incluido
deepseek-v4.1-flash. - ¿Necesitas gráficos, sellos o escaneos? Desactiva la extracción y usa un modelo marcado como «sí» en la tabla, por ejemplo
gpt-6.1-sol. - El texto no latino (ruso, chino y otros idiomas) de un PDF se lee sin cambiar ninguna configuración. Quita la contraseña del PDF antes de enviarlo.
- Elimina los archivos subidos con
DELETE /v1/files/{file_id}cuando ya no los necesites.
file_id devuelto con un identificador de terceros.