API de procesamiento de imágenes

Sube una imagen, ejecuta hasta cinco operaciones ordenadas y descarga el resultado mediante un único flujo asíncrono.

URL base
https://api.pixmender.com
Documentación interactiva
Swagger UI
1Crear clave
2Request upload
3Upload image
4Create job
5Check status
6Descargar
01

Crear una clave de API

Open Claves de API, create a key with images:write and images:read. Add webhooks:manage solo si vas a usar webhooks; después copia la clave inmediatamente. La clave completa se muestra una sola vez.

Mantenla en el servidorNo expongas nunca una img_live_… clave en código del navegador ni en un repositorio público.
Terminal
export PIXMENDER_API_KEY="img_live_your_key"
02

Solicitar una URL de carga segura

Crea primero un registro del recurso. Usa el tipo MIME exacto: JPEG, PNG, WebP, AVIF, GIF, HEIC o HEIF. Los archivos pueden tener hasta 20 MB.

Request
curl --request POST https://api.pixmender.com/v1/uploads \
  --header "Authorization: Bearer $PIXMENDER_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{"content_type":"image/jpeg","filename":"photo.jpg"}'
Response
{
  "id": "ast_01...",
  "status": "pending_upload",
  "upload_url": "https://storage.pixmender.com/...",
  "upload_method": "POST",
  "upload_fields": {
    "bucket": "pixmender-assets",
    "key": "originals/usr_.../ast_01....jpg",
    "Content-Type": "image/jpeg",
    "Policy": "...",
    "X-Amz-Signature": "..."
  },
  "upload_url_expires_at": "2026-08-25T10:30:00.000Z",
  "asset_expires_at": "2026-08-26T10:15:00.000Z"
}

upload_url_expires_at es el breve plazo de la política de carga. asset_expires_at es el plazo independiente de conservación de la imagen cargada.

03

Subir los bytes de la imagen

Envía mediante POST un cuerpo multipart/form-data directamente a upload_url. Añade primero todos los valores de upload_fields y la imagen como último campo file . La política firmada acepta entre 1 byte y 20 MB. No envíes tu clave de API de PixMender a la URL de almacenamiento.

Request
export UPLOAD_URL="https://storage.pixmender.com/..."

# Add every upload_fields entry returned above before the file field.
curl --request POST "$UPLOAD_URL" \
  --form-string "bucket=$UPLOAD_BUCKET" \
  --form-string "key=$UPLOAD_KEY" \
  --form-string "Content-Type=image/jpeg" \
  --form-string "Policy=$UPLOAD_POLICY" \
  --form-string "X-Amz-Algorithm=$UPLOAD_ALGORITHM" \
  --form-string "X-Amz-Credential=$UPLOAD_CREDENTIAL" \
  --form-string "X-Amz-Date=$UPLOAD_DATE" \
  --form-string "X-Amz-Signature=$UPLOAD_SIGNATURE" \
  --form "[email protected];type=image/jpeg"
04

Crear una tarea de procesamiento

Envía el ID del recurso cargado y una lista ordenada de operaciones. Se reserva el coste exacto y se devuelve automáticamente si falla. Optimizar cuesta 0,1 créditos por separado y es gratis con otra operación. Ampliar cuesta 0,5 créditos; las demás operaciones, 1 crédito. La API exporta PNG, JPEG, WebP y AVIF. El encabezado Idempotency-Key es obligatorio: reutiliza la misma clave solo para solicitudes idénticas, para que un reintento de transporte no cree otra tarea facturable mientras la clave sea válida.

Las claves nuevas son válidas durante la tarea y 24 horas tras finalizar, fallar o cancelarse. Los reintentos no amplían ese plazo. Reutilizar una clave caducada crea una solicitud nueva con cargos normales. Las claves anteriores a esta política mantienen su duración ilimitada. El historial y la conservación de archivos son independientes.

Request
curl --request POST https://api.pixmender.com/v1/images/process \
  --header "Authorization: Bearer $PIXMENDER_API_KEY" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: request-001" \
  --data '{
    "input": { "asset_id": "ast_01..." },
    "operations": [
      { "type": "denoise" },
      {
        "type": "upscale",
        "scale": 4,
        "model": "realesrgan-x4plus"
      },
      { "type": "optimize" }
    ],
    "output_format": "webp",
    "compression_preset": "balanced"
  }'
Optional output sizeSet output_size: { width: 2560, height: 2560 } para obtener ese tamaño exacto con un recorte centrado. Las dimensiones son enteros de 1 a 10000. Con ambas dimensiones, el valor predeterminado es cover. Con una sola dimensión, el valor predeterminado es inside y el otro lado se calcula proporcionalmente. Un valor explícito de output_size.fit: "inside" ajusta toda la imagen a los límites sin recortar. Ambos modos amplían imágenes pequeñas cuando es necesario y mantienen las proporciones. Se redimensiona después de la IA y antes de codificar y optimizar. Solo imágenes estáticas.

Redimensionar por separado cuesta 0,1 créditos: envía un operations array with output_size. Con otra operación, redimensionar es gratis: optimizar y redimensionar cuesta 0,1 créditos; ampliar, optimizar y redimensionar cuesta 0,5. El precio se mantiene si la imagen ya encaja. Las tareas fallidas o canceladas devuelven la reserva completa. Cada tamaño o modo nuevo requiere una clave de idempotencia nueva; los reintentos reutilizan la misma.

Preajuste de compresiónThe production API retains compression_preset:lossless, balanced, or small. Si se omite, se mantienen el modo equilibrado predeterminado y el control de calidad.

Without encoder_version, la API usa el codificador de producción localmente o en workers compatibles. Para activar la beta, envía en el nivel superior encoder_version: "v8" con una clave API. La optimización beta solo se ejecuta localmente; las operaciones de IA anteriores mantienen sus proveedores. Los umbrales SSIMULACRA2 son 60 / 75 / 90 para Compact / Balanced / Visual Lossless, con un límite de 120 segundos. Producción mantiene su control de calidad y sus límites.

202 Accepted
{
  "id": "job_01...",
  "status": "queued",
  "credits_reserved": 1.5,
  "input_asset_id": "ast_01...",
  "result_asset_id": null
}
05

Consultar el estado de la tarea

Consulta cada 1–3 segundos hasta que el estado sea succeeded,failed, canceled, or expired. Si se completa, utiliza result_asset_id para descargar. Las tareas optimizadas también devuelven tamaños, ahorro, formato elegido, clase de contenido, resultado de control perceptual, esfuerzo de búsqueda y motivo final en optimization.

queuedvalidatingprocessingsucceededfailedcancel_requestedcanceledexpired
Request
curl https://api.pixmender.com/v1/jobs/job_01... \
  --header "Authorization: Bearer $PIXMENDER_API_KEY"
Respuesta completada
{
  "id": "job_01...",
  "status": "succeeded",
  "credits_charged": 1.5,
  "credits_refunded": 0,
  "input_byte_size": 2471936,
  "input_content_type": "image/jpeg",
  "result_asset_id": "ast_result_01...",
  "result_filename": "photo.avif",
  "result_byte_size": 812640,
  "result_content_type": "image/avif",
  "optimization": {
    "source_bytes": 2471936,
    "result_bytes": 812640,
    "savings_percent": 67.125,
    "format": "avif",
    "quality": 57,
    "similarity": 0.99124,
    "guard_passed": true,
    "attempts": 12,
    "candidate_formats": [
      "avif",
      "webp",
      "jpeg"
    ],
    "content_class": "photo",
    "deadline_reached": false,
    "original_preserved": false,
    "reason": "optimized",
    "encode_ms": 2840
  },
  "error": null
}
06

Descargar el resultado

La API devuelve una URL firmada temporal válida durante 10 minutos. El archivo procesado permanece disponible 24 horas, salvo eliminación anterior.

Request
curl 'https://api.pixmender.com/v1/assets/ast_result_01.../download?disposition=attachment' \
  --header "Authorization: Bearer $PIXMENDER_API_KEY"

# Response: { "url": "https://storage.pixmender.com/...", "expires_in": 600 }
curl --location "https://storage.pixmender.com/..." --output photo.webp

Delete originals and results

Después de descargar todos los archivos necesarios, llama a DELETE /v1/assets/{assetId}para cada original y resultado. La eliminación es gratuita y requiere images:write. Elimina esa imagen y sus vistas previas en caché. Conserva otros resultados y el historial. Repetir la solicitud devuelve la misma respuesta correcta.

Un recurso usado por una tarea en cola o en curso devuelve 409; espera a que termine o se cancele. Un 503 indica que el acceso está bloqueado pero la limpieza del almacenamiento sigue pendiente; reintenta la solicitud. Los recursos desconocidos o de otro usuario devuelven 404.

Request
curl -X DELETE "https://api.pixmender.com/v1/assets/ast_example" -H "Authorization: Bearer $PIXMENDER_API_KEY"
Response
{"id":"ast_example","deleted":true}
SDK methods
await client.deleteAsset(assetId); // TypeScript
client.delete_asset(asset_id)       # Python
$client->deleteAsset($assetId);     // PHP
07

Referencia de operaciones

Un flujo contiene entre 1 y 5 operaciones. Si se usa, optimizemust be last. upscale debe ser la última operación de procesamiento y solo puede ir seguida de optimize.

Para redimensionar sin otras operaciones, envía un operations array and specify output_size.

TypePurposeCampos adicionales
remove_watermarkEliminar marcas de agua visiblesTarea: rights_attested: true
remove_textEliminar pies de foto y letras—
remove_logoEliminar marcas de marca—
remove_objectEliminar un objeto descritose requiere prompt
restoreReparar daños y degradación—
denoiseReducir ruido y artefactos de compresión—
deblurMejorar detalles desenfocados—
face_enhanceMejorar detalles del retrato—
upscaleAumentar la resoluciónscale: 2 | 4; paso final de procesamiento
optimizeCompresión perceptual según el contenido; AUTO elige la mejor opcióndebe ir al final
Formatos de salidasource · png · jpeg · webp · avif; source conserva el formato de entrada verificado
Modelos de ampliaciónrealesrgan-x4plus · realesrgan-x4plus-anime · realesr-animevideov3
08

Recibir webhooks firmados

Crea un endpoint con el permiso webhooks:manage o gestiónalo desde Webhooks. PixMender envía job.succeeded, job.failed, and job.canceled. Devuelve una respuesta 2xx en 10 segundos; las entregas fallidas se reintentan con espera exponencial.

Crear endpoint
curl --request POST https://api.pixmender.com/v1/webhooks \
  --header "Authorization: Bearer $PIXMENDER_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{"url":"https://example.com/pixmender","events":["job.succeeded","job.failed"]}'
Verificar el cuerpo sin procesarLas firmas usan HMAC-SHA256 sobre webhook-id.webhook-timestamp.raw-body. Guarda el secreto whsec_… mostrado al crearlo; solo aparece una vez.
Verificación de firma con Node.js
import { createHmac, timingSafeEqual } from "node:crypto";

const eventId = request.headers.get('webhook-id');
const timestamp = request.headers.get('webhook-timestamp');
const signatureHeader = request.headers.get('webhook-signature');
if (!eventId || !timestamp || !signatureHeader?.startsWith('v1=')) {
  throw new Error('Missing webhook signature headers');
}
const received = signatureHeader.slice(3);
if (!/^[a-f0-9]{64}$/i.test(received)) {
  throw new Error('Invalid webhook signature format');
}
const rawBody = await request.text();

const timestampNumber = Number(timestamp);
const age = Math.abs(Date.now() / 1000 - timestampNumber);
if (!Number.isFinite(timestampNumber) || age > 300) {
  throw new Error('Stale webhook');
}

const secret = process.env.PIXMENDER_WEBHOOK_SECRET;
if (!secret) throw new Error('Webhook secret is not configured');
const expected = createHmac('sha256', secret)
  .update(`${eventId}.${timestamp}.${rawBody}`)
  .digest('hex');
const receivedBytes = Buffer.from(received, 'hex');
const expectedBytes = Buffer.from(expected, 'hex');
if (receivedBytes.length !== expectedBytes.length ||
    !timingSafeEqual(receivedBytes, expectedBytes)) {
  throw new Error('Invalid webhook signature');
}

Las cabeceras de entrega son webhook-id, webhook-timestamp, and webhook-signature: v1=…. Elimina duplicados mediante el ID del webhook.

09

Usar un SDK del servidor

Los SDK del servidor combinan carga firmada, creación y consulta de tareas y descarga en un método. No incluyas la clave de API en el navegador.

TypeScript · @pixmender/sdk
import { PixMender } from "@pixmender/sdk";

const client = new PixMender({
  apiKey: process.env.PIXMENDER_API_KEY!,
});
const result = await client.processImage({
  file: "./photo.jpg",
  // Optimize must be the final operation.
  operations: [{ type: "denoise" }, { type: "upscale", scale: 4 }, { type: "optimize" }],
  idempotencyKey: "workflow-run-123",
  outputFormat: "webp",
  compressionPreset: "balanced",
});
await result.downloadTo("./photo-enhanced.webp");
Python · pixmender
import os
from pixmender import PixMender

client = PixMender(api_key=os.environ["PIXMENDER_API_KEY"])
result = client.process_image(
    file="photo.jpg",
    operations=[{"type": "restore"}, {"type": "optimize"}],
    idempotency_key="workflow-run-123",
    output_format="webp",
    compression_preset="balanced",
)
result.download_to("photo-enhanced.webp")
PHP · pixmender/pixmender-php
use PixMender\PixMender;

$client = new PixMender($_ENV['PIXMENDER_API_KEY']);
$result = $client->processImage(
    __DIR__ . '/photo.jpg',
    [['type' => 'restore'], ['type' => 'optimize']],
    'workflow-run-123',
    outputFormat: 'webp',
    compressionPreset: 'balanced',
);
$result->downloadTo(__DIR__ . '/photo-enhanced.webp');
Descargas directasVersion 0.1.0 · alojado por PixMender
Sumas SHA-256
TypeScriptNode.js 18+
@pixmender/sdk
PythonPython 3.10+
pixmender
PHPPHP 8.1+
pixmender/pixmender-php
Instalar directamente desde pixmender.com
# TypeScript
npm install https://pixmender.com/downloads/pixmender-sdk-0.1.0.tgz

# Python
pip install https://pixmender.com/downloads/pixmender-0.1.0-py3-none-any.whl

# PHP / Composer
composer config repositories.pixmender composer https://pixmender.com/downloads/composer
composer require pixmender/pixmender-php:^0.1
10

Conectar herramientas de automatización

Las integraciones de n8n y Make aceptan una imagen binaria, ejecutan el flujo asíncrono completo y devuelven la imagen procesada como salida binaria para el siguiente paso.

Descargas directasVersion 0.1.0 · paquetes de código fuente directos
n8nSelf-hosted installation
n8n-nodes-pixmender
MakeDeveloper app components
PixMender Custom App
Instalar en n8n autogestionado
# Run in the custom-nodes directory of a self-hosted n8n instance
npm install https://pixmender.com/downloads/n8n-nodes-pixmender-0.1.0.tgz
11

Migrar desde Tinify

Las integraciones HTTP existentes de Tinify pueden conservar el formato de optimización. Apúntalas a https://api.pixmender.com, keep Basic Auth, use api como usuario y tu clave de API de PixMender como contraseña.

Optimizar una imagen local
curl https://api.pixmender.com/shrink \
  --user "api:$PIXMENDER_API_KEY" \
  --data-binary "@photo.png" \
  --dump-header /dev/stdout

Una solicitud correcta devuelve 201 Created. El cuerpo JSON incluye size, type, dimensions, compression ratio y la dirección pública de descarga enoutput.url. La misma URL se devuelve en la cabecera Location y funciona sin clave de API hasta que caduca el resultado.

201 Created
{
  "input": {
    "size": 98868,
    "type": "image/jpeg"
  },
  "output": {
    "size": 88373,
    "type": "image/jpeg",
    "width": 1280,
    "height": 853,
    "ratio": 0.8938,
    "url": "https://api.pixmender.com/output/job_..."
  }
}
Descargar sin autorización
curl https://api.pixmender.com/output/job_... \
  --output "photo-optimized.png"
Optimizar la URL de una imagen
curl https://api.pixmender.com/shrink \
  --user "api:$PIXMENDER_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{"source":{"url":"https://example.com/photo.jpg"}}'
Ámbito de compatibilidadAdmite optimización de PNG, JPEG, WebP y AVIF de hasta 5 MB y 60 megapíxeles. Este endpoint no permite redimensionar, convertir, conservar metadatos ni almacenar. /shrink usa el optimizador de producción en el mismo formato y su control de calidad; no ofrece todos los modos y formatos de la API principal. Cada optimización completada cuesta 0,1 créditos.