← Zyplo
Zyplo · Developers

Integrá Zyplo

Para quién no es

Si exportás WebGL multi-archivo de Godot, Unity o GameMaker, Zyplo no lo va a hostear. El formato es un solo archivo HTML autocontenido — un .wasm más un .pck no se pueden subir, ni hoy ni en un roadmap. Mejor que lo sepas ahora y no después de una semana de intentarlo.

Publicar un juego

Zyplo habla MCP. Lo conectás una vez y tu asistente puede crear un juego, validarlo, subirlo como borrador, editarlo y publicarlo — sin que salgas del chat.

La auth es OAuth con registro dinámico de cliente y PKCE. Las keys zyplo_sk_ viejas siguen funcionando si ya tenés una.

Por HTTP

Un POST publica un juego. No hace falta nada más — sin SDK, sin build step, sin script tag adentro de tu juego.

curl -X POST https://zyplo.io/api/upload-game \
  -H "Authorization: Bearer $ZYPLO_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title":"Tap the Comet","description":"One tap. Do not miss.","html_content":"<!doctype html>...","tags":["arcade"],"published":false}'

ZYPLO_KEY es una key personal (zyplo_sk_…) o un access token de OAuth (zyplo_at_…). Subí primero como borrador (published: false) y miralo antes de que salga en vivo. openapi.json

Chequeá antes de subir

Agregá ?dry_run=true y la misma llamada valida sin crear nada. Reporta todos los problemas de una en vez de frenar en el primero, y no escribe nada — ni archivo, ni juego, ni marca de rate limit — así que podés iterar todo lo que quieras.

curl -X POST "https://zyplo.io/api/upload-game?dry_run=true" \
  -H "Authorization: Bearer $ZYPLO_KEY" \
  -H "Content-Type: application/json" \
  -d @game.json

Responde 200 esté el juego bien o mal: el status dice que el chequeo corrió, ok dice el veredicto. Un token inválido sigue respondiendo 401. No chequea ni el rate limit ni la portada, así que ok: true quiere decir que el juego es válido, no que la subida vaya a funcionar.

El formato

Estas son las reglas reales, leídas del mismo módulo que usan el uploader y el prompt del MCP. Si esta página y la API alguna vez no coinciden, eso es un bug — avisanos.

Reglas duras — la subida rechaza si las violás

Reglas de diseño — no se validan, pero si las ignorás el feed te entierra

Un juego que pasa

Un juego mínimo que cumple todas las reglas de arriba. Jugalo y después leelo — es corto a propósito. Jugar el ejemplo

Es un solo archivo, así que el Ver código fuente de tu navegador te muestra el juego entero.

Por qué se rechaza una subida

Todo error responde con un code estable, el campo que falla, y qué hacer al respecto. Ramificá sobre code, nunca sobre el texto del mensaje — los mensajes se pueden reescribir, los códigos no.

{
  "error":    "Zyplo acepta HTML autocontenido: ...",
  "code":     "external_script",
  "field":    "html_content",
  "detail":   "https://cdn.example/phaser.js",
  "fix":      "Inline the library into a <script> block.",
  "docs_url": "https://zyplo.io/en/integrate#error-external_script"
}

El string error no cambió respecto de antes de que existieran los códigos, así que nada de lo que lo lea se rompe. code es internal_error cuando el error es uno que todavía no describimos — eso es un bug nuestro y lo queremos saber.

not_html 400
Lo que mandaste no arranca como un documento HTML. Campo: html_content Solución: Mandá el documento entero, empezando con <!doctype html>. No un fragmento, no JSON, no un blob en base64.
external_script 400
Un <script src="..."> apunta afuera. Campo: html_content Solución: Inliná la librería dentro de un bloque <script>. Si es muy grande para inlinear, el juego no entra en Zyplo.
relative_asset 400
Un asset usa ruta relativa, y no tiene contra qué resolver una vez que el archivo se sirve solo. Campo: html_content Solución: Embebé el asset como data: URI, o apuntá a una URL https:// absoluta.
forbidden_tag 400
El documento tiene <iframe>, <frame>, <frameset>, <object>, <embed>, <applet>, <form> o <base>. Campo: html_content Solución: Sacalo. Los juegos ya corren dentro de un iframe con sandbox, así que anidar otro o postear un form no puede funcionar.
meta_refresh 400
Un <meta http-equiv="refresh"> sacaría al jugador del feed. Campo: html_content Solución: Sacalo y reiniciá el juego desde JavaScript.
dangerous_url 400
Una URL usa un esquema que no está permitido (javascript:, vbscript:, file:, ftp:, o http: pelado). Campo: html_content Solución: Usá https://, data: o blob:. Para comportamiento al hacer click, poné un listener en vez de una URL javascript:.
network_api 400
El código llama a fetch, XMLHttpRequest, WebSocket, EventSource, importScripts, eval, new Function, navigator.sendBeacon, document.cookie o window.open. Campo: html_content Solución: Sacá la llamada. Los juegos son offline por diseño: guardá el estado en memoria o en localStorage. No hay backend in-game ni SDK in-game.
missing_token 401
No se mandó el header Authorization. Solución: Mandá Authorization: Bearer <token> con una key zyplo_sk_ o un token OAuth zyplo_at_.
invalid_token_format 401
El token Bearer no es ni una key zyplo_sk_ ni un token OAuth zyplo_at_. Solución: Fijate que no estés mandando un JWT de Supabase o un token de sesión. Los tokens de Zyplo empiezan con zyplo_.
invalid_api_key 401
La key zyplo_sk_ no existe o fue revocada. Solución: Generá una key nueva en Perfil de creador → API & Connectors, o conectate por OAuth.
invalid_oauth_token 401
El access token de OAuth expiró o fue revocado. Solución: Refrescá el token. Si tu cliente no puede, sacá y volvé a agregar el conector de Zyplo.
account_suspended 401
La cuenta detrás de este token está suspendida, así que no puede subir ni editar juegos. Solución: No hay nada que reintentar. Escribinos si creés que la suspensión es un error.
game_not_found 401
No hay ningún juego con ese game_id en esta cuenta. Puede haber sido borrado, o el id puede ser de otro. Solución: Llamá a list_my_games (MCP) para ver los ids que esta cuenta realmente tiene. No reintentes con el mismo id.
invalid_body 400
La request llegó sin un objeto JSON como body. Campo: body Solución: Mandá los campos como un objeto JSON con Content-Type: application/json. Una request vacía, un string suelto y un array caen todos acá; detail dice cuál llegó.
missing_field 400
Faltaba un campo requerido, o vino vacío. Solución: Mirá field para saber cuál. Mandalo con un valor no vacío.
conflicting_fields 400
Se mandaron dos campos que no pueden aplicar a la vez. Solución: Mandá cover_url o cover_data_url, nunca los dos.
unsupported_tag 400
Un tag no es de los veinte que Zyplo acepta. Campo: tags Solución: Elegí del enum del spec OpenAPI (arcade, puzzle, skill, casual, humor, meme, snake, breakout, tetris, dodge, memory, logic, reflex, timing, precision, runner, retro, action, platformer, strategy). Los tags después del décimo se descartan en silencio.
no_updates 400
La llamada de update no traía ningún campo con cambios, así que no hay nada que escribir. Solución: Incluí al menos uno de title, description, tags, cover_url o cover_data_url.
unknown_action 400
El campo action no es uno que este endpoint maneje. Campo: action Solución: Usá update, set_visibility o delete.
invalid_dry_run 400
El parámetro de query dry_run traía un valor que no es ni sí ni no. Campo: dry_run Solución: Mandá ?dry_run=true (o 1) para validar, ?dry_run=false (o 0) para subir, o no lo mandes. Un valor no reconocido se rechaza en vez de adivinarse: adivinar mal subiría el juego de verdad.
method_not_allowed 405
Este endpoint sólo responde POST. Solución: Mandá la request como POST con un body JSON.
html_too_large 400
El documento HTML pasa el límite de tamaño. Campo: html_content Solución: Achicá el documento. Lo que suele pasarse son los assets en base64 embebidos — generá el arte con canvas o SVG.
cover_too_large 400
La imagen de portada pasa el límite de tamaño. Campo: cover_url Solución: Mandá una imagen más chica.
plan_limit_reached 400
La cuenta ya tiene el máximo de juegos que permite su plan. Solución: Borrá un juego antes de subir otro. Reintentar no va a servir.
rate_limited 400
Las subidas de esta cuenta vienen demasiado seguidas. Solución: Esperá los segundos que dice el mensaje y reintentá la misma request una vez.
game_under_review 400
El juego está retenido para revisión de moderación, así que no se puede editar ni publicar. Solución: Esperá a que termine la revisión. Reintentar ahora va a fallar igual.
game_file_missing 400
El archivo HTML guardado de este juego no está, así que no se puede leer su código. Solución: Volvé a subir el juego. Esta es nuestra — avisanos que pasó.
cover_invalid_type 400
La portada no es JPG, PNG ni WebP. Campo: cover_url Solución: Convertila a alguno de esos tres.
cover_invalid_data 400
Los bytes de la portada no decodifican como el tipo de imagen que dicen ser. Campo: cover_url Solución: Re-exportá la imagen. Una extensión renombrada o una descarga cortada caen las dos acá.
cover_fetch_failed 400
No se pudo descargar la cover_url. Campo: cover_url Solución: Mandá una URL https pública que devuelva la imagen directo. Zyplo rechaza http, direcciones privadas y de loopback, y sigue como máximo 3 redirects, que también tienen que ser https públicos.
invalid_report 400
El payload del reporte está mal formado. Solución: Mandá un game_id válido (UUID) y una razón conocida.
duplicate_report 409
Este reportante ya reportó este juego. Solución: No hay nada que hacer — vale el primer reporte.
report_rate_limited 429
Demasiados reportes desde este origen. Solución: Esperá antes de reportar de nuevo.
storage_upload_failed 500
Zyplo no pudo escribir el archivo en storage. Solución: Reintentá una vez. Si vuelve a pasar es una falla nuestra — avisanos.
server_misconfigured 500
Falta una credencial del lado del servidor. Solución: No hay nada que puedas hacer. Avisanos.
internal_error 500
Algo falló de nuestro lado que no anticipamos. Solución: Reintentá una vez y después avisanos.

¿Trabado?

Escribime un mail con lo que mandaste y lo que te volvió. Contesta una persona — normalmente el que escribió esta página.