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.
img_live_… clave en código del navegador ni en un repositorio público.export PIXMENDER_API_KEY="img_live_your_key"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.
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"}'{
"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.
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.
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"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.
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"
}'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.
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.
{
"id": "job_01...",
"status": "queued",
"credits_reserved": 1.5,
"input_asset_id": "ast_01...",
"result_asset_id": null
}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_requestedcanceledexpiredcurl https://api.pixmender.com/v1/jobs/job_01... \
--header "Authorization: Bearer $PIXMENDER_API_KEY"{
"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
}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.
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.webpDelete 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.
curl -X DELETE "https://api.pixmender.com/v1/assets/ast_example" -H "Authorization: Bearer $PIXMENDER_API_KEY"{"id":"ast_example","deleted":true}await client.deleteAsset(assetId); // TypeScript
client.delete_asset(asset_id) # Python
$client->deleteAsset($assetId); // PHPReferencia 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.
remove_watermarkEliminar marcas de agua visiblesTarea: rights_attested: trueremove_textEliminar pies de foto y letras—remove_logoEliminar marcas de marca—remove_objectEliminar un objeto descritose requiere promptrestoreReparar 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 procesamientooptimizeCompresión perceptual según el contenido; AUTO elige la mejor opcióndebe ir al finalsource conserva el formato de entrada verificadoRecibir 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.
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"]}'webhook-id.webhook-timestamp.raw-body. Guarda el secreto whsec_… mostrado al crearlo; solo aparece una vez.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.
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.
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");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")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');# 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.1Conectar 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.
# Run in the custom-nodes directory of a self-hosted n8n instance
npm install https://pixmender.com/downloads/n8n-nodes-pixmender-0.1.0.tgzMigrar 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.
curl https://api.pixmender.com/shrink \
--user "api:$PIXMENDER_API_KEY" \
--data-binary "@photo.png" \
--dump-header /dev/stdoutUna 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.
{
"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_..."
}
}curl https://api.pixmender.com/output/job_... \
--output "photo-optimized.png"curl https://api.pixmender.com/shrink \
--user "api:$PIXMENDER_API_KEY" \
--header "Content-Type: application/json" \
--data '{"source":{"url":"https://example.com/photo.jpg"}}'/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.