PUT /api/listings crea o actualiza un listado completo en una sola llamada atómica: la API, sus endpoints, el secreto de origen, los planes, las FAQs y las APIs vinculadas. O se guarda todo, o no se guarda nada. Es lo que usan internamente las herramientas MCP provider_*, y puedes llamarla directamente desde scripts o CI.
Acceso
- Cualquier cuenta con correo verificado. Las cuentas no verificadas o bloqueadas reciben
403. - Autentícate con tu clave de API:
Authorization: Bearer YOUR_API_KEY. - Límites de velocidad por cuenta: 30 upserts y 120 lecturas por minuto.
- Los listados nuevos cuentan contra la cuota de APIs nuevas. Las actualizaciones nunca cuentan.
Endpoints
| Método | Ruta | Propósito |
|---|---|---|
| PUT | /api/listings |
Crea o actualiza un listado (o lo elimina con "delete": true) |
| GET | /api/listings |
Tus listados (status, page, per_page) |
| GET | /api/listings/{product_key} |
Definición completa de un listado (nunca el secreto de origen) |
| GET | /api/listings/me |
Tu cuenta, límites, nombres de plan válidos y tipos de parámetro |
| GET | /api/listings/categories |
Ids de categoría |
Ejemplo
curl -X PUT https://zylalabs.com/api/listings \
-H "Authorization: Bearer $ZYLA_API_KEY" \
-H "Content-Type: application/json" \
-d @listing.json
listing.json:
{
"product_key": "trustpilot-api",
"publish": true,
"api": {
"name": "Trustpilot Reviews API",
"short_description": "Retrieve Trustpilot company reviews, ratings and reviewer details in JSON.",
"trial": false
},
"access": { "in": "header", "key": "X-Origin-Key", "value": "your-origin-secret" },
"endpoints": [{
"name": "Get Company Reviews",
"description": "Returns the latest public reviews for a company domain with pagination.",
"method": "GET",
"base_url": "https://origin.example.com/v1/items/||domain||",
"path_params": { "domain": "example.com" },
"parameters": [
{ "key": "page", "type": "number", "description": "Page number, starting at 1.", "value": "1", "required": false }
],
"headers": [{ "key": "Accept", "value": "application/json" }],
"example_response": { "reviews": [{ "rating": 5 }] }
}],
"plans": [
{ "name": "Basic", "interval": "Monthly", "price": 24.99, "max_requests": 1000 },
{ "name": "Pro", "interval": "Monthly", "price": 49.99, "max_requests": 5000 },
{ "name": "ProPlus", "interval": "Monthly", "price": 99.99, "max_requests": 15000, "rate_limit": 120 }
],
"faqs": [{ "question": "What data does it return?", "answer": "Public reviews with rating and text." }],
"slaves": [{ "name": "Company Reviews Lookup API" }]
}
Reglas
Identidad. product_key es tu propio id estable para el listado. Una clave nueva crea el listado; una clave que ya usaste lo actualiza. Una clave pertenece a la cuenta que la creó (403 para cualquier otra). Los listados eliminados no aceptan ediciones (409).
Publicación. El listado se publica cuando pasa las reglas de calidad y tiene al menos un endpoint con una respuesta de ejemplo y planes activos. Sin eso, "publish": true devuelve 422. Omite publish para publicarlo en cuanto esté listo, o envía "publish": false para mantenerlo como borrador. false nunca despublica un listado que ya está en vivo.
Campos de la API. name sigue las reglas de nombre: hasta 50 caracteres, incluye la palabra "API", único en el hub. short_description de al menos 50 caracteres. Zyla completa el resto de la página del listado por ti: la descripción larga se genera a partir de tu descripción corta, y la categoría y las etiquetas se eligen con IA. Si envías long_description, category_id, tags o website_url, se ignoran y se listan en warnings.
Endpoints. Cuando endpoints está presente, es la lista completa: los endpoints se emparejan por método + base_url (sin el query string), se crean los nuevos y se eliminan los que falten en la lista. Omite endpoints para dejarlos sin cambios.
- Descripción de al menos 40 caracteres. Método GET, POST, PUT, DELETE o PATCH.
base_urldebe ser una URL válida. Los parámetros de ruta van entre||, como en/items/||domain||, con un valor de ejemplo enpath_params.- Los parámetros necesitan
key,type(string, number, email, url, domain, date, datetime) y una descripción de al menos 10 caracteres. example_responsees obligatorio, de hasta 10,000 caracteres.
Secreto de origen (access). Un header o parámetro de consulta que Zyla agrega a cada llamada hacia tu origen, para que tu servidor solo acepte tráfico del hub. Se guarda oculto y nunca se devuelve ni se registra. Omítelo para mantener el actual; envía null para eliminarlo.
Planes. Nombres exactos: Free, Basic, Pro, ProPlus, Premium, Elite, Ultimate, Pay as you go. price en USD; los planes anuales llevan su precio anual final. max_requests por ciclo; un plan más barato debe incluir menos solicitudes que uno más caro en el mismo intervalo. rate_limit de 60 a 240 por minuto. Deben mantenerse activos al menos tres planes mensuales pagos. Si no envías planes en un listado nuevo, se crea un conjunto por defecto.
FAQs. Lista completa cuando está presente, hasta 10. Pregunta de 5 a 100 caracteres, respuesta de 3 a 700.
APIs vinculadas (slaves). Variantes de tu API con su propio nombre y página que reutilizan sus endpoints. Se emparejan por nombre y siguen los cambios en los endpoints de la principal. La principal necesita endpoints, y una API vinculada no puede tener APIs vinculadas propias.
Eliminar. {"product_key": "...", "delete": true} elimina el listado. Se rechaza con 409 mientras tenga suscripciones pagas. Las APIs vinculadas se eliminan solo si las nombras en slaves.
No soportado. Transformaciones de respuesta, cuerpos de solicitud y subida de archivos (422 not_supported). Usa el asistente web para eso.
Respuestas
Éxito: {"success": true, "listing": {...}, "warnings": []}, con 201 al crear y 200 al actualizar. listing.url se establece en cuanto el listado está en vivo.
| Estado | code |
Significado |
|---|---|---|
| 401 | unauthenticated |
Clave ausente o inválida |
| 403 | forbidden |
Cuenta no verificada o bloqueada, o el product_key pertenece a otra cuenta |
| 404 | not_found |
product_key desconocido |
| 409 | name_taken, active_subscriptions, endpoints_required, listing_deleted, slave_of_slave, product_key_conflict |
Conflicto; no se cambió nada |
| 422 | validation_failed, ai_validation_failed, not_supported |
errors indexado por campo, por ejemplo endpoints.2.parameters.0.description |
| 429 | creation_limit_reached |
Se agotó la cuota de APIs nuevas; retry_after en segundos y un header Retry-After |
| 503 | ai_unavailable |
La verificación de contenido no respondió; no se guardó nada; vuelve a intentarlo |
| 500 | server_error |
Falla inesperada; no se guardó nada |