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. 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 clavepk_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. Consulta tu saldo
curl curl https://api.picverce.com/v1/me \ -H "Authorization: Bearer pk_live_..."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. 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
statusdigasucceededofailed. Los resultados llegan enoutput.images.
Lo mismo en JavaScript
Node 18 o superior. Ejecutalo en tu servidor, nunca en un navegador.
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.
| Herramienta | Creditos | Que hace |
|---|---|---|
| background_remover | 2 | Recorta el sujeto y devuelve un PNG transparente |
| enhance | 2 | Limpieza general, recupera detalle y reduce ruido |
| upscale | 2, 3 o 6 | Aumenta 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.
{
"error": {
"code": "insufficient_credits",
"message": "This job costs 6 credits and your balance is 2.",
"request_id": "req_4f2a9c1b7e3d5a8c0b6e1f92"
}
}| HTTP | Codigo | Significado |
|---|---|---|
| 401 | invalid_api_key | Clave ausente, mal formada, desconocida o revocada |
| 402 | insufficient_credits | Clave valida, saldo insuficiente |
| 403 | plan_upgrade_required | Tu cuenta no incluye acceso a la API publica |
| 404 | invalid_tool | No existe esa herramienta, o aun no acepta trabajos |
| 404 | invalid_model | No existe ese modelo |
| 404 | job_not_found | No hay ningun trabajo con ese id en tu cuenta |
| 422 | validation_error | La peticion se entendio y fue rechazada |
| 429 | rate_limited | Demasiadas peticiones en este minuto |
| 500 | internal_error | Algo 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:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 58
X-RateLimit-Reset: 1787644920Al 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.
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.
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.