¿Cómo publicar su plugin?

Contenido
Los plugins de GameAP se publican en plugins.gameap.dev — desde ahí los usuarios los instalan directamente desde el panel. Esta guía recorre todo el camino: desde la creación de la ficha del plugin hasta la publicación automática de nuevas versiones desde CI.
Se presupone que su plugin ya está escrito y se compila en un .wasm. También necesitará una
cuenta en plugins.gameap.dev: un registro normal con confirmación del correo electrónico, o inicio
de sesión a través de GitHub, GitLab o Google.
Hay dos formas de subir una versión: manualmente a través del dashboard y a través de la API desde CI. Es más fácil empezar con el dashboard y, cuando la compilación se estabilice, pasar a CI.
Paso 1. Cuenta de desarrollador #
Publicar plugins requiere una cuenta con estado de desarrollador. Se concede gratis e inmediatamente — basta con aceptar las reglas de publicación.
En el catálogo de plugins pulse Publish your plugin — el botón de la esquina superior derecha.

Se abrirá la página con las reglas de publicación. En resumen, lo que usted acepta:
- Plugins funcionales y de calidad — solo plugins operativos y probados, que hagan lo que promete su descripción.
- Nada de código malicioso — sin puertas traseras, mineros ocultos ni lógica ofuscada; cualquier recopilación de datos de los usuarios debe describirse explícitamente.
- Derechos y licencias — usted es propietario del código o está autorizado a distribuirlo, las licencias de terceros se respetan y la licencia del plugin está indicada.
- Compatibilidad con GameAP — el plugin funciona con las versiones actuales del panel y cumple los requisitos del formato.
- Actualizaciones y soporte — los errores críticos y las vulnerabilidades se corrigen en plazos razonables, y los reportes de los usuarios reciben respuesta.
- Moderación — cada plugin y cada versión pasan una revisión, y un plugin que infrinja las reglas puede ser retirado en cualquier momento.
- Sin spam ni duplicados — sin nombres engañosos ni relleno de palabras clave.
El texto completo está en la propia página, y vale la pena leerlo entero.
Pulse Agree al final de la página. El rol se concede al instante, sin revisión ni espera: en la barra lateral aparecerá la sección Developer con los apartados Dashboard, My Plugins, New Plugin y Support, y llegará un correo informándole de que ya es desarrollador.
Importante. Las reglas solo pueden aceptarse con un correo electrónico verificado: de lo contrario, el botón Agree permanece inactivo y la página muestra un recordatorio para confirmar la dirección. Las cuentas creadas a través de GitHub, GitLab o Google se consideran verificadas de inmediato.
El botón Publish your plugin es visible para todos, incluidos los visitantes que no han iniciado sesión. Sin sesión, la página de reglas muestra Log in to agree — al identificarse volverá a las reglas.
Paso 2. Creación del plugin #
Seleccione New Plugin en el menú de la izquierda — se abrirá el formulario de creación.

| Campo | Obligatorio | Qué indicar |
|---|---|---|
| Name | sí | Hasta 255 caracteres |
| Summary | sí | Una frase para la tarjeta del catálogo, hasta 500 caracteres |
| Description | sí | Descripción completa en Markdown — el campo tiene una barra de formato |
| Category | no | Una de las tres siguientes |
| Labels | no | Palabras clave que facilitan encontrar el plugin |
| License | no | Texto libre: MIT, GPL-3.0, Proprietary |
| Source URL | no | Enlace a las fuentes, si están abiertas |
| Repository URL | no | Enlace al repositorio |
| Homepage URL | no | El sitio web del plugin o del autor |
Las categorías:
- Server Management — la mayoría de los plugins. Todo lo que añade acciones sobre un servidor de juegos.
- Files — extensiones del gestor de archivos: editores, visores de formatos concretos.
- Integrations — plugins que amplían sustancialmente lo que el panel puede hacer, por ejemplo la gestión de bases de datos.
El icono no se puede subir en este paso — el formulario lo advierte explícitamente; el control de subida aparece justo después de la creación.
Importante. Source URL y Repository URL afectan a algo más que la ficha. Si ninguno de los dos está relleno, cada versión tendrá que incluir un archivo con el código fuente — los moderadores necesitan algo con lo que verificar la compilación. Rellene al menos uno de ellos si sus fuentes son públicas.
Paso 3. El ID del plugin #
Tras pulsar Create llegará a la página de edición del plugin. Su primer bloque es el Plugin ID — un campo de solo lectura con un botón para copiar.
Este ID hay que escribirlo en el código fuente del plugin — en el campo id de la estructura
PluginInfo que devuelve el método GetInfo. Así es como el panel asocia un plugin instalado por
el usuario con su entrada en el marketplace.
El ID se genera una sola vez al crear el plugin y no puede cambiarse. Internamente es un número
de 64 bits (8 bytes aleatorios) escrito en base32 — 13 caracteres latinos y dígitos, por ejemplo
fmqnme42gg7da. El mismo ID aparece en la URL de la página del plugin y en la dirección del
endpoint de CI.
Cómo se ve en los plugins existentes:
- plugin-mysql — la constante
PLUGIN_ID(fmqnme42gg7da) - plugin-goldsrc-addons —
PLUGIN_ID(ezvdsxmlu6fbk) - plugin-minecraft-modrinth —
PLUGIN_ID(dshdabjp2l73a)
Importante. Escriba el ID y recompile el
.wasmantes de subir la primera versión. Las versiones son inmutables: no se puede volver a subir un archivo con el mismo número, habría que incrementar la versión.
Paso 4. Icono y traducciones #
En esa misma página de edición se puede subir un icono: JPG, PNG, WebP o SVG, hasta 2 MB; se recomienda 128×128.
La página del plugin tiene un bloque Translations. El catálogo es bilingüe y cada visitante ve la ficha en su propio idioma: sin traducción, un usuario ruso recibirá la descripción en inglés y viceversa. El nombre, el resumen y la descripción se traducen por separado para cada idioma — cinco minutos de trabajo que cambian notablemente el aspecto de la ficha.
Paso 5. Subida de una versión #
En la página del plugin busque la tarjeta Versions y pulse Upload Version.

| Campo | Obligatorio | Qué indicar |
|---|---|---|
| Version | sí | Versión semántica: 1.0.0, 1.2.0-beta.1 |
| Plugin File | sí | El .wasm compilado, hasta 100 MB |
| GPG Signature | no | Firma separada .sig o .asc, hasta 1 MB |
| Source Code Archive | depende | .zip o .tar.gz, hasta 50 MB |
| Changelog | no | Qué cambió respecto a la versión anterior, en Markdown |
| Stable Release | — | Un interruptor, activado por defecto |
| Min GameAP Version | no | La versión del panel a partir de la cual funciona el plugin |
La firma GPG es opcional pero bienvenida: el servidor la almacena tal cual y nunca la verifica — existe para que los usuarios puedan comprobar por sí mismos la autenticidad del archivo.
El archivo de código fuente es obligatorio cuando el plugin no tiene rellenos ni Source URL ni Repository URL — el formulario cambia por sí solo la etiqueta del campo de «(Optional)» a «(Required)». El archivo se usa solo para la moderación y la verificación de la compilación; nunca se publica ni es accesible a través de ningún endpoint público.
Importante. Una versión subida a través del dashboard permanece como borrador. Hasta que no la envíe a revisión, nadie la ve.
Capturas de pantalla de la versión #
Justo después de la subida se abre un segundo paso — Add Screenshots. Las capturas pertenecen a una versión concreta: JPG, PNG o WebP, hasta 10, de 5 MB cada una. El paso se puede omitir y retomar más tarde desde la página de la versión.
Paso 6. Envío a revisión #
Los plugins pasan por moderación — conforme a las mismas reglas de publicación que aceptó en el paso 1. La cabecera de la página del plugin tiene un botón Submit for Review — solo es visible mientras el plugin está en estado Draft o Rejected.
Un plugin sin ninguna versión no puede enviarse — suba primero una versión. Enviar una versión a revisión desde la tabla de versiones también mueve el propio plugin de Draft a Pending Review, así que normalmente no hace falta pulsar el botón de la cabecera por separado.
| Estado | Qué significa | Qué se puede hacer |
|---|---|---|
| Draft | Creado, no enviado a ninguna parte | Editar, enviar a revisión, eliminar |
| Pending Review | Esperando a un moderador | Esperar |
| Rejected | Un moderador lo devolvió | Corregirlo y enviarlo de nuevo |
| Released | Disponible para todos en el catálogo | Subir nuevas versiones |
| Approved | Un estado intermedio en el modelo de datos | — |
| Deprecated | Marcado como obsoleto | Aún instalable, pero señalizado |
| Retracted | Retirado de la publicación | No disponible para instalar |
La aprobación mueve el plugin y la versión directamente a Released. Solo los objetos en ese estado son visibles públicamente: si un plugin está publicado pero su única versión sigue pendiente de revisión, no hay nada que instalar.
El motivo del rechazo llega por correo electrónico — la página del plugin solo muestra el estado, así que revise su bandeja de entrada.
Tokens de despliegue #
Para publicar versiones desde CI se necesita un token de despliegue. Está al final de la página del plugin, en la tarjeta Deploy Tokens.

Pulse Create Token y rellene el diálogo: un nombre (GitHub Actions, por ejemplo) y,
opcionalmente, una fecha de caducidad.

Importante. El token se muestra exactamente una vez, justo después de su creación. En el servidor solo se guarda su hash y el valor no se puede recuperar — cópielo directamente en los secretos de su CI.
Lo que conviene saber sobre los tokens:
- Un token está vinculado a un solo plugin y solo puede subir versiones de ese plugin. No abre ni otros plugins ni el resto de la API.
- El formato es
gapd_más 43 caracteres, 48 en total. El prefijo lo detectan fácilmente los escáneres de secretos. - La tabla muestra el prefijo del token, la fecha de creación, el último uso y la caducidad — práctico para averiguar qué token sigue en uso.
- La revocación es inmediata: un pipeline con un token revocado fallará en su próxima ejecución.
- Un mismo plugin puede tener hasta 20 tokens.
Publicación desde CI #
El endpoint de CI acepta una nueva versión sin inicio de sesión interactivo — se autentica con un token de despliegue.
Subida con curl #
curl --fail-with-body -sS \
-H "Authorization: Bearer $GAMEAP_DEPLOY_TOKEN" \
-F "version=1.2.3" \
-F "file=@build/plugin.wasm" \
-F "signature=@build/plugin.wasm.asc" \
-F "changelog=Corregido un fallo al reiniciar el servidor" \
-F "min_gameap_version=4.1.0" \
-F "is_stable=true" \
"https://plugins.gameap.dev/api/ci/plugins/$GAMEAP_PLUGIN_ID/versions"
La petición es un POST con multipart/form-data. Los campos del formulario:
| Campo | Obligatorio | Descripción |
|---|---|---|
version | sí | Versión semántica, p. ej. 1.2.3 |
file | sí | El .wasm compilado, hasta 100 MB |
signature | no | Firma GPG separada, hasta 1 MB |
source | depende | Archivo de fuentes .zip/.tar.gz hasta 50 MB; obligatorio cuando el plugin no tiene ni Source URL ni Repository URL |
changelog | no | Notas de la versión; cómodo pasarlas desde un archivo: -F "changelog=<CHANGELOG.md" |
min_gameap_version | no | Versión mínima de GameAP |
min_plugin_api_version | no | Versión mínima del Plugin API (el formulario del dashboard no tiene este campo) |
is_stable | no | true o 1 marca la versión como estable |
submit | no | Por defecto true; false mantiene la versión como borrador |
No ponga una barra final en la URL. El router responde a .../versions/ con un 301, y curl
no reenvía el cuerpo del POST en una redirección — la subida se convertiría silenciosamente en un
GET.
Una respuesta exitosa es un 201 con un cuerpo como:
{
"id": 123,
"plugin_id": "fmqnme42gg7da",
"version": "1.2.3",
"file_size": 1048576,
"file_hash": "9f86d081884c7d65...",
"has_source": false,
"status": "pending_review"
}
GitHub Actions #
Este workflow se dispara cuando se publica un release de GitHub, compila el plugin, lo firma y lo envía a plugins.gameap.dev. El cuerpo del release se convierte en el changelog, y la versión se marca como estable solo cuando el release no es un pre-release.
name: Publish plugin
on:
release:
types: [published]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build plugin
run: make wasm # debe producir build/plugin.wasm
- name: Sign plugin
env:
GPG_SIGNING_KEY: ${{ secrets.GPG_SIGNING_KEY }}
run: |
printf '%s' "$GPG_SIGNING_KEY" | gpg --batch --import
gpg --batch --yes --detach-sign --armor \
-o build/plugin.wasm.asc build/plugin.wasm
- name: Publish to plugins.gameap.dev
env:
GAMEAP_DEPLOY_TOKEN: ${{ secrets.GAMEAP_DEPLOY_TOKEN }}
GAMEAP_PLUGIN_ID: ${{ vars.GAMEAP_PLUGIN_ID }}
TAG: ${{ github.event.release.tag_name }}
RELEASE_BODY: ${{ github.event.release.body }}
PRERELEASE: ${{ github.event.release.prerelease }}
run: |
VERSION="${TAG#v}"
printf '%s' "$RELEASE_BODY" > "$RUNNER_TEMP/changelog.md"
ARGS=(--fail-with-body -sS
-H "Authorization: Bearer ${GAMEAP_DEPLOY_TOKEN}"
-F "version=${VERSION}"
-F "file=@build/plugin.wasm"
-F "signature=@build/plugin.wasm.asc"
-F "changelog=<${RUNNER_TEMP}/changelog.md")
if [ "$PRERELEASE" != "true" ]; then
ARGS+=(-F "is_stable=true")
fi
curl "${ARGS[@]}" \
"https://plugins.gameap.dev/api/ci/plugins/${GAMEAP_PLUGIN_ID}/versions"
VERSION="${TAG#v}" elimina la v inicial para que el tag v1.2.3 se publique como versión
1.2.3.
La versión de producción de este workflow, con compilación del frontend, caché de Cargo y comprobación del estado HTTP, está en plugin-mysql.
Configuración del repositorio de GitHub #
El token y el ID del plugin no deben estar en el código — pertenecen a la configuración del repositorio. Abra Settings → Secrets and variables (en la sección Security and quality) → Actions.

En la pestaña Secrets pulse New repository secret y añada:
| Nombre | Valor |
|---|---|
GAMEAP_DEPLOY_TOKEN | El token de despliegue que copió al crearlo (empieza por gapd_) |
GPG_SIGNING_KEY | Una clave privada GPG en formato ASCII-armor, si firma sus compilaciones |

En la pestaña Variables pulse New repository variable y añada:
| Nombre | Valor |
|---|---|
GAMEAP_PLUGIN_ID | El ID del plugin, p. ej. fmqnme42gg7da |

El ID del plugin es el mismo identificador base32 que escribió en PluginInfo. Cópielo con el
botón junto al campo Plugin ID en la página de edición, o desde el bloque Details en la página del
plugin.
El ID va en variables y no en secretos a propósito: no es un secreto, y tenerlo visible en los logs de CI facilita mucho el diagnóstico de fallos. El token, en cambio, siempre es un secreto.
Así se exporta una clave privada GPG para GPG_SIGNING_KEY:
gpg --armor --export-secret-keys SU_ID_DE_CLAVE
Publique la clave pública donde los usuarios puedan encontrarla — en el README del plugin, por ejemplo — para que la firma sea verificable.
Dashboard y CI: valores por defecto distintos #
| Qué | Dashboard | CI |
|---|---|---|
| Stable release | El interruptor está activado por defecto | is_stable por defecto es false — pásalo explícitamente |
| Envío a revisión | Manual, pulsando un botón | submit por defecto es true — la versión va a revisión de inmediato |
| Capturas de pantalla | Se ofrecen justo después de la subida | No soportadas, añádalas a través del dashboard |
Si lo único que quiere de CI es subir el archivo y terminar los metadatos a mano, pase
submit=false y la versión permanecerá como borrador.
Errores #
| Código | Causa |
|---|---|
400 | ID de plugin inválido, un multipart mal formado o no se pasó file |
401 | El token falta, es inválido o ha caducado; la cabecera no tiene la forma Bearer gapd_... |
403 | El token es válido pero fue emitido para otro plugin |
409 | Ya existe una versión con ese número |
422 | La versión no pasa la comprobación de semver; el archivo de fuentes falta, es demasiado grande o no es .zip/.tar.gz; se superan los límites de tamaño del archivo o de la firma |
Los cuerpos de error tienen una forma común:
{
"status": "error",
"error": "version already exists",
"message": "version already exists",
"http_code": 409
}
Tras un error 5xx, no reintente la subida a ciegas. Escribir la versión y enviarla a revisión
no son una única transacción: la versión puede que ya exista, y un reintento devuelve 409. Abra
el dashboard y compruebe qué pasó realmente.
Actualización y retirada de versiones #
Una nueva versión se sube exactamente igual que la primera — a través del dashboard o desde CI. Las
versiones ya subidas son inmutables: volver a subir un archivo con el mismo número no es posible,
el intento devuelve 409. Si la compilación salió mal, incremente la versión de parche.
Cada fila de la tabla de versiones tiene sus propias acciones:
- Edit — cambiar el changelog y los metadatos.
- Submit for Review — para borradores y versiones rechazadas.
- Deprecate — para versiones publicadas. La versión sigue disponible pero se marca como obsoleta.
- Retract — para versiones publicadas y obsoletas. La versión se retira de la publicación.
Solo se puede eliminar un plugin en estado Draft. Un plugin publicado no se puede eliminar — se puede retractar.
Lista de comprobación #
- El correo está verificado, las reglas de publicación aceptadas y la cuenta tiene estado de desarrollador.
- El plugin está creado, y el nombre y ambas descripciones están rellenos.
- Source URL o Repository URL están rellenos — de lo contrario, cada versión necesita un archivo de fuentes.
- El ID del plugin está escrito en
PluginInfo.idy el.wasmse recompiló después. - El icono está subido y las traducciones de la ficha están en su sitio.
- La versión está subida, con firma y capturas de pantalla adjuntas.
- La versión está enviada a revisión, no dejada como borrador.
- Para CI: un token de despliegue creado y guardado en los secretos, el ID del plugin en las variables.
- El workflow no tiene barra final en la URL y pasa
is_stableexplícitamente. - Tras el release, se confirma que el plugin y la versión están en estado Released.