TL;DR. Sí, la App Store Connect API puede actualizar tu keyword field, el subtítulo, la descripción y el texto promocional sin que abras App Store Connect a mano. Pero el nombre y el subtítulo viven en el recurso appInfoLocalization, mientras que las keywords, la descripción, el texto promocional y el What’s New viven en appStoreVersionLocalization — un recurso distinto con sus propias reglas de estado. Si intentas hacer PATCH de las keywords en una versión que está en vivo o en revisión, obtendrás un 409 STATE_ERROR. La API no evita el ciclo de release de Apple, solo te da una forma programable de disparar las mismas acciones que harías a golpe de clic.

Si gestionas metadatos de más de una app, o localizas a seis o más idiomas y vuelves a escribir el mismo cambio de keyword field en seis pestañas de locale en cada release, la App Store Connect API te quita el clic. No te quita las restricciones. Saber dónde viven realmente esas restricciones te ahorra una sesión de debugging la primera vez que un PATCH falla por una razón que no tiene nada que ver con tu JSON.

¿Puedo actualizar mi keyword field vía la App Store Connect API?

Sí. El atributo keywords vive en el recurso appStoreVersionLocalization, y lo actualizas con un PATCH al endpoint de ese recurso, delimitado a un locale. Esto funciona exactamente igual que editar el keyword field a mano en la sección de Información Localizable de App Store Connect — mismo campo de 100 caracteres, mismas reglas de tokenización, misma recomendación de no repetir tu título. La API no relaja nada de eso; es solo una puerta distinta a la misma habitación.

Lo que confunde a la gente no es el cuerpo del request. Es que este endpoint solo acepta escrituras mientras la versión de App Store a la que pertenece está en un estado editable.

¿Qué recurso contiene cada campo de metadatos?

Esta es la parte que la mayoría de las guías de integración se saltan, y la razón por la que un PATCH que funciona para un campo puede fallar el mismo día para otro campo.

appInfoLocalization contiene campos que no están ligados a una versión específica:

  • name
  • subtitle
  • privacyPolicyUrl, privacyPolicyText, privacyChoicesUrl

appStoreVersionLocalization contiene campos que están ligados a una versión específica:

  • keywords
  • description
  • promotionalText
  • whatsNew
  • marketingUrl, supportUrl

La división parece implicar que el nombre y el subtítulo podrían publicarse en vivo de forma independiente al envío de una versión, ya que el propio modelo de recursos de Apple no los anida bajo una versión. En la práctica no funciona así: ambos campos solo surten efecto cuando se publica una versión, igual que las keywords. Si estás validando un cambio de subtítulo y sueles revisar el estado de la versión buscando “Ready for Sale” antes de confiar en una métrica, ese hábito aplica igual aquí — la API cambia cómo escribes el campo, no cuándo Apple realmente lo publica. Es la misma brecha entre release y aprobación que cubre la guía de opciones de lanzamiento de App Store Connect.

¿Por qué falla mi PATCH con un 409 STATE_ERROR?

Porque los campos de appStoreVersionLocalization solo se pueden editar mientras la versión a la que pertenecen está en un estado editable — PREPARE_FOR_SUBMISSION, DEVELOPER_REJECTED, REJECTED o METADATA_REJECTED. En cuanto una versión pasa a WAITING_FOR_REVIEW, IN_REVIEW, PENDING_DEVELOPER_RELEASE o READY_FOR_SALE, ese mismo PATCH que funcionaba ayer devuelve un 409 con "code": "STATE_ERROR" y un mensaje de que el atributo no se puede editar en este momento.

Esto es la API aplicando exactamente la misma regla que ya conoces de la interfaz manual: una vez enviada la versión, el keyword field queda bloqueado hasta que la revisión se resuelva o retires la versión con un rechazo de developer. La solución no es una forma distinta de request — es comprobar el estado de la versión con un GET antes de intentar la escritura, y solo enviar la actualización cuando el estado sea uno de los editables mencionados arriba. Si estás scripteando esto como parte de un pipeline de release, esa comprobación de estado va antes del PATCH, no en un bucle de reintentos después de que falle.

¿Cómo funciona realmente la autenticación?

Cada request necesita un JSON Web Token firmado con ES256, generado a partir de una clave privada que creas en App Store Connect. Las Team Keys se generan desde Usuarios y Acceso → Integrations → Team Keys, y generar una requiere el rol de Administrador en la cuenta — un requisito más estrecho que el grupo Titular de cuenta/Administrador/Gestor de apps/Marketing que puede editar el keyword field a mano. Las Individual Keys, generadas desde tu propio perfil de usuario, heredan tu propio rol de cuenta y tus apps asignadas en lugar de acceso a nivel de cuenta.

Dos consecuencias prácticas:

  • Las Team Keys ven todas las apps de la cuenta, sin forma de limitar una a una sola app. Si gestionas metadatos de una sola app, una Individual Key ligada a tu propio rol de App Manager o Marketing es la opción con alcance más ajustado.
  • La clave privada se descarga exactamente una vez. Apple no guarda una copia redescargable. Si la pierdes, revocas la key y generas una nueva — tampoco puedes recuperar ni renombrar el nivel de acceso de una key existente.
  • Apple recomienda vidas cortas de token para requests estándar (la App Store Connect API limita los tokens de request normales a unos 20 minutos), no el máximo permitido para el conjunto reducido de scopes de reporting de solo lectura. Genera un token por cada ejecución de tu script en lugar de fijar uno con una expiración larga.

¿Realmente vale la pena construir esto para un equipo indie?

Si gestionas una app en uno o dos locales y cambias tu keyword field cada pocas semanas, no — la interfaz manual es más rápida que escribir y mantener una integración con la API. La API empieza a valer la pena cuando gestionas metadatos en varios locales de forma recurrente, o en más de una app, donde el mismo cambio de campo hay que repetirlo idéntico muchas veces y un error de copiar y pegar en el locale cinco es fácil de pasar por alto.

El caso de uso realista inicial no es la automatización completa — es un script que lea tu keyword field, descripción y subtítulo actuales en cada locale de una versión, para que puedas comparar un cambio propuesto contra lo que realmente está en vivo antes de tocar nada a mano. El acceso de lectura no tiene ninguno de los problemas de bloqueo por estado mencionados arriba, porque los requests GET funcionan sin importar el estado de la versión, así que es el punto de partida de menor riesgo.

Antes de construir contra esta API

  1. Confirma en qué recurso vive tu campo objetivo antes de escribir el request — appInfoLocalization para nombre/subtítulo, appStoreVersionLocalization para keywords/descripción/texto promocional/What’s New.
  2. Haz un GET del estado de la versión antes de cada PATCH a appStoreVersionLocalization. Escribe solo cuando sea PREPARE_FOR_SUBMISSION, DEVELOPER_REJECTED, REJECTED o METADATA_REJECTED.
  3. Decide entre Team Key e Individual Key según el alcance, no la comodidad — una Team Key que solo necesitabas para una app es una credencial permanente a nivel de cuenta que no hacía falta crear.
  4. Recuerda que la API cambia cómo editas los metadatos, no cuándo se publican. El timing del release sigue la misma regla de release vs. aprobación que las ediciones manuales, y los requisitos de rol siguen aplicando según quién puede tocar el keyword field en primer lugar.