API publica de Picverce AI v1.0.0

Usa Picverce AI desde tu propio servidor

Edita imagenes con las mismas herramientas del sitio web, o crea nuevas desde un prompt con 26 modelos. Los trabajos son asincronos, asi que un modelo lento nunca se convierte en un tiempo de espera agotado de tu lado.

Los trabajos de la API consumen el mismo saldo de creditos de tu cuenta. No hay nada aparte que comprar.

URL base: https://api.picverce.com. Crea una clave en tu cuenta y empieza a llamarla.

Dos formas de usarla

Ambas pasan por el mismo endpoint. Si ya tienes la imagen y quieres cambiarla, eso es una Herramienta. Si quieres una imagen que aun no existe, eso es un Modelo.

API de Herramientas

Ejecuta una herramienta de Picverce AI sobre una imagen que tu envias. Le das una imagen y te devuelve una nueva.

De 2 a 8 creditos. Envia type: "tool".

API de Modelos

Elige un modelo de generacion y un prompt, con imagen de referencia si quieres. Le das palabras y te devuelve una imagen.

De 3 a 14 creditos. Envia type: "generate".

Inicio rapido

  1. 1. Crea una clave

    Ve a Cuenta, Claves de API y pulsa Crear clave. El secreto se muestra una sola vez y no se puede recuperar, asi que copialo antes de cerrar el dialogo.

    Las claves son del tipo pk_live_.... Una clave pk_test_ funciona igual y es para desarrollo.

    El acceso a la API publica viene con un plan de pago o un paquete de creditos. Una suscripcion activa Basic, Standard o Premium lo incluye, y tambien cualquier paquete de creditos que hayas comprado. Ver planes

  2. 2. Consulta tu saldo

    curl
    curl https://api.picverce.com/v1/me \
      -H "Authorization: Bearer pk_live_..."
  3. 3. Crea un trabajo

    curl
    curl -X POST https://api.picverce.com/v1/jobs \
      -H "Authorization: Bearer pk_live_..." \
      -H "Content-Type: application/json" \
      -d '{
        "type": "tool",
        "tool": "background_remover",
        "input": { "image_url": "https://example.com/product.jpg" }
      }'

    Responde en milisegundos con status: "queued" y un id de trabajo.

  4. 4. Consulta hasta que termine

    curl
    curl https://api.picverce.com/v1/jobs/JOB_ID \
      -H "Authorization: Bearer pk_live_..."

    Consulta cada par de segundos hasta que status diga succeeded o failed. Los resultados llegan en output.images.

Lo mismo en JavaScript

Node 18 o superior. Ejecutalo en tu servidor, nunca en un navegador.

Node
const KEY = process.env.PICVERCE_API_KEY;
const BASE = 'https://api.picverce.com';

async function api(path, options = {}) {
  const response = await fetch(BASE + path, {
    ...options,
    headers: {
      Authorization: `Bearer ${KEY}`,
      'Content-Type': 'application/json',
      ...options.headers,
    },
  });

  const body = await response.json();
  if (!response.ok) {
    throw new Error(`${body.error.code}: ${body.error.message}`);
  }
  return body;
}

async function runJob(payload) {
  const job = await api('/v1/jobs', { method: 'POST', body: JSON.stringify(payload) });

  while (true) {
    const current = await api(`/v1/jobs/${job.id}`);
    if (current.status === 'succeeded') return current.output.images;
    if (current.status === 'failed') throw new Error(current.error.message);
    await new Promise((r) => setTimeout(r, 2000));
  }
}

const images = await runJob({
  type: 'generate',
  model: 'flux-schnell',
  input: { prompt: 'a red bicycle against a white wall' },
});

Las claves viven en tu servidor

Esta API no envia cabeceras CORS, a proposito. Una clave pegada en JavaScript del navegador no funcionara desde una pagina web.

Trata una clave como una contrasena. Mantenla fuera de apps moviles y repositorios publicos. Si se filtra, revocala en tu cuenta y dejara de funcionar en la siguiente peticion.

Herramientas que ya puedes ejecutar

Tres herramientas aceptan trabajos en la v1.0.0. El catalogo completo es mayor y se consulta con GET /v1/tools, con precios y esquemas de entrada de todo lo que viene.

HerramientaCreditosQue hace
background_remover2Recorta el sujeto y devuelve un PNG transparente
enhance2Limpieza general, recupera detalle y reduce ruido
upscale2, 3 o 6Aumenta la resolucion 2x, 4x u 8x

Los 26 modelos de generacion aceptan trabajos. Listalos con GET /v1/models y lee capabilities en vez de fijar proporciones y resoluciones en el codigo, porque cambian segun el modelo.

Creditos

Los creditos se reservan al crear el trabajo y solo se cobran cuando termina bien. Un trabajo fallido se reembolsa por completo e informa credits.charged: 0.

Como los creditos se retienen por adelantado, tu saldo baja en cuanto creas un trabajo. GET /v1/me informa reserved_open para que veas cuanto retiene el trabajo que sigue en curso.

Errores

Todos los fallos tienen la misma forma, asi que un solo manejador los cubre todos.

Cualquier respuesta que no sea 2xx
{
  "error": {
    "code": "insufficient_credits",
    "message": "This job costs 6 credits and your balance is 2.",
    "request_id": "req_4f2a9c1b7e3d5a8c0b6e1f92"
  }
}
HTTPCodigoSignificado
401invalid_api_keyClave ausente, mal formada, desconocida o revocada
402insufficient_creditsClave valida, saldo insuficiente
403plan_upgrade_requiredTu cuenta no incluye acceso a la API publica
404invalid_toolNo existe esa herramienta, o aun no acepta trabajos
404invalid_modelNo existe ese modelo
404job_not_foundNo hay ningun trabajo con ese id en tu cuenta
422validation_errorLa peticion se entendio y fue rechazada
429rate_limitedDemasiadas peticiones en este minuto
500internal_errorAlgo fallo de nuestro lado

La entrada invalida se rechaza, no se corrige

Si pides una proporcion o un numero de variaciones que el modelo no admite, recibes un 422 con los valores admitidos. El sitio web sustituye en silencio por algo valido en esa situacion, lo cual esta bien cuando hay una persona mirando. Para un cliente automatico significaria pagar por una imagen que no pediste, asi que la API la rechaza.

Limites de peticiones

60 peticiones por minuto movil, por clave. Cuenta cada endpoint autenticado. Cada respuesta incluye tu situacion:

Cabeceras de respuesta
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 58
X-RateLimit-Reset: 1787644920

Al pasarte recibes un 429 con Retry-After en segundos. Es una ventana movil, asi que 60 peticiones al inicio del minuto no te dan otras 60 un segundo despues.

Con honestidad sobre el tope: el contador funciona por instancia de borde, asi que el trafico repartido entre regiones puede superar algo las 60 en un minuto real. Disena para 60 en vez de apurarlo. Sera un limite global estricto en una version posterior.

Webhooks

En lugar de consultar en bucle, registra un endpoint y enviaremos un POST firmado cuando termine un trabajo. Anade uno en Cuenta, API, Webhooks. Hoy existen dos eventos: job.succeeded y job.failed.

Lo que llega a tu endpoint
POST https://api.tuempresa.com/picverce/webhook
Content-Type: application/json
User-Agent: Picverce-Webhooks/1.0
X-Picverce-Event: job.succeeded
X-Picverce-Delivery: 0f2b1d94-6a3c-4b1e-9d77-2c9e5a1b3d84
X-Picverce-Timestamp: 1756300000
X-Picverce-Signature: v1=8f3c1a...

{
  "id": "evt_11111111222233334444555555555555s",
  "object": "event",
  "type": "job.succeeded",
  "created_at": "2026-08-27T10:00:09.412Z",
  "data": { "object": { ...el mismo trabajo que devuelve GET /v1/jobs/{id}... } }
}

Verifica la firma antes de confiar en el cuerpo. La cadena firmada es la marca de tiempo, un punto y el cuerpo en crudo tal y como llego.

Verificar en Node
const crypto = require('crypto');

// rawBody tienen que ser los bytes en crudo, no un objeto vuelto a serializar.
function verify(rawBody, headers, secret) {
  const timestamp = headers['x-picverce-timestamp'];
  const received = headers['x-picverce-signature'];
  if (!timestamp || !received) return false;

  // La firma en si nunca caduca, asi que esto es lo que impide un replay.
  if (Math.abs(Math.floor(Date.now() / 1000) - Number(timestamp)) > 300) return false;

  const expected =
    'v1=' +
    crypto.createHmac('sha256', secret).update(timestamp + '.' + rawBody).digest('hex');

  const a = Buffer.from(expected);
  const b = Buffer.from(received);
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

Analiza despues de verificar

Volver a codificar el JSON cambia el orden de las claves y los espacios, y la firma deja de coincidir.

Cuenta con duplicados

La entrega es al menos una vez. El id del evento es estable por trabajo y estado, asi que usalo como clave de idempotencia.

Responde rapido

Encola el trabajo y devuelve 200. Cortamos a los 10 segundos y reintentamos dos veces, sobre los 2 y los 8 segundos.

Los endpoints deben ser https y accesibles desde internet. Las direcciones privadas, de loopback y de metadatos de nube se rechazan al registrarlas y de nuevo antes de cada entrega. No seguimos redirecciones, asi que registra la URL final. Un 404 o un 410 desde tu endpoint detiene los reintentos.

Referencia completa

La descripcion completa en OpenAPI 3.0 cubre cada endpoint, campo y error. Apunta un generador de clientes hacia ella en vez de escribir los tipos a mano.