Saltar al contenido principal
- Referencia de endpoints

Referencia de endpoints de la API

Estos son los endpoints orientados al cliente en la primera versión de la API. Todas las rutas son relativas a su URL base de la API, que la aplicación muestra en Configuraciones → API keys una vez que haya creado una clave.

Recursos

MétodoRutaPropósito
POST/assetsImportar una URL remota como asset.
POST/assets/uploadsIniciar una subida directa.
POST/assets/uploads/{uploadId}/completeFinalizar una subida directa.
GET/assetsListar assets.
GET/PATCH/DELETE/assets/{id}Leer, actualizar o eliminar un asset.

Categorías, asignaciones, packs, enlaces y etiquetas

MétodoRutaPropósito
GET/POST/categoriesListar o crear categorías planas.
GET/PATCH/DELETE/categories/{id}Leer, renombrar o eliminar una categoría.
GET/POST/mappingsListar o insertar/actualizar asignaciones de productos de Shopify.
GET/PUT/DELETE/mappings/{id}Leer, reemplazar o eliminar una asignación.
GET/POST/packsListar o crear packs.
GET/DELETE/packs/{id}Leer o eliminar un pack.
GET/POST/linksListar o crear enlaces. Crear requiere un plan de pago; los límites de visitas y la caducidad siguen siendo exclusivos del admin.
GET/POST/license-key-tagsListar o crear etiquetas de claves de licencia.

POST /mappings y PUT /mappings/{id} aceptan un objeto opcional notify_customers ({}, o { "message": "…", "variant_ids": [ … ] }). Una vez confirmada la escritura, Alva pone en cola una notificación de actualización de producto para los compradores de la asignación que escribiste — la misma campaña que POST /products/{shopify_product_id}/notifications más abajo, con las mismas reglas de nota y el mismo límite de 7 días por producto. Antes de la escritura solo se ejecutan las comprobaciones sobre el propio texto de la nota: una nota en blanco, demasiado larga, que usa una variable desconocida o mal formada, que nombra más de cinco metacampos o que tiene un enlace en su texto es 422 invalid_message y no se escribe nada. Cualquier otro rechazo se informa dentro de la respuesta como data.notification con created: false y un código error — nunca como un 4xx, así que la escritura de la asignación sigue teniendo éxito. Eso incluye un problema con un metacampo (invalid_message con errors[]: un metacampo que no existe, de un tipo no admitido, demasiado largo o que contiene un enlace, o una nota demasiado larga una vez rellenadas sus variables), notification_cooldown con next_available_at, too_many_active_notifications con limit y active_notification_ids, no_eligible_recipients, email_disabled, y archive_not_queued cuando no se pudo poner en cola la regeneración del archivo. Una asignación recién creada aún no tiene compradores y devuelve no_eligible_recipients. data.notification solo está presente cuando enviaste el indicador. El indicador no añade coste de límite de frecuencia: la escritura de la asignación cuesta sus 2 tokens habituales. Repetir la misma Idempotency-Key devuelve la respuesta almacenada sin una segunda campaña; para reintentar solo la notificación, llama a POST /products/{shopify_product_id}/notifications con una clave nueva y variant_ids con las variantes de la asignación escrita, o con las mismas variant_ids que llevaba el indicador. Sin variant_ids, ese endpoint notifica a los compradores de todas las asignaciones del producto, no solo de la que escribiste.

Un indicador por producto, no uno por variante. El indicador envía emails solo a los compradores de la asignación que escribiste, pero consume el límite de 7 días del producto completo. Si escribes las asignaciones de las variantes de un producto una a una con el indicador en cada una, la primera campaña ocupa los 7 días del producto, así que las demás devuelven notification_cooldown. En su lugar, pon el indicador en una sola escritura, la última, para que la campaña espere también a las regeneraciones que pusieron en cola las escrituras anteriores. Indica en variant_ids todas las variantes cuyos compradores deban enterarse, incluidas las de la propia asignación escrita: variant_ids sustituye el alcance predeterminado en lugar de ampliarlo.

Pedidos y acceso

MétodoRutaPropósito
GET/orders/{shopify_order_id}Leer el estado de descarga de un pedido.
GET/POST/orders/{shopify_order_id}/assignmentsListar o crear asignaciones a nivel de producto.
GET/orders/{shopify_order_id}/assignments/{purchaseId}/download-urlsGenerar URLs de descarga.
POST/orders/{shopify_order_id}/revokeDesactivar el acceso.
POST/orders/{shopify_order_id}/restoreRestaurar el acceso.
POST/orders/{shopify_order_id}/grant-downloadsConceder descargas adicionales.
POST/orders/{shopify_order_id}/resendReenviar el email de entrega.

El endpoint de download-urls devuelve 422 withdrawal_consent_required cuando la tienda tiene activado el consentimiento del derecho de desistimiento de la UE y el pedido aún no tiene un registro de consentimiento; las URL de descarga se emiten en cuanto el cliente da su consentimiento.

Los endpoints download-urls y resend devuelven 409 delivery_not_yet_released cuando el producto tiene configurado un retraso de entrega de la descarga y los archivos del comprador aún no se han desbloqueado. El valor error.details.release_at es el instante ISO 8601 en el que se desbloquean, y el endpoint grant-downloads libera el pedido antes de tiempo.

Notificaciones de actualización de producto

Envía por email a los compradores de un producto el aviso de que se ha actualizado — la misma campaña que un comerciante inicia con Notificar a clientes en la página de un producto en la app — desde tu propio sistema. Disponible en todos los planes de pago; 403 forbidden significa que la API está desactivada para la app (el interruptor global de emergencia) o que Alva ha desactivado la función — contacta con nosotros si la recibes. En la ruta, {shopify_product_id} es el id numérico del producto sin más (recomendado) o un GID codificado en porcentaje como un único segmento de ruta (gid%3A%2F%2Fshopify%2FProduct%2F123); un gid://shopify/Product/123 literal ocupa varios segmentos de ruta y no llega a este endpoint.

MétodoRutaPropósito
POST/products/{shopify_product_id}/notificationsPoner en cola una campaña para todos los compradores elegibles del producto (202). Envía { "dry_run": true } para ejecutar las mismas comprobaciones y obtener el número de destinatarios, el asunto y la nota renderizada sin enviar nada (200). Cuesta 10 tokens del límite de frecuencia en ambos casos.
GET/notifications/{notificationId}Leer una campaña: estado, recuentos, waiting_for_archive, error. Las campañas iniciadas desde la app también aparecen.
POST/notifications/{notificationId}/cancelCancelar una campaña que sigue en cola (200, estado cancelled). El límite de 7 días del producto se mantiene.

Cuerpo de la solicitud (todos los campos son opcionales; {} notifica el producto completo sin nota). message: una nota de texto sin formato de hasta 2.000 caracteres, que aparece como “Una nota de {tu tienda}:” encima del botón de descarga. La nota sirve para describir qué ha cambiado en el producto — correcciones, archivos nuevos, qué volver a descargar — y no debe usarse para promociones ni descuentos. Puede usar {customer.first_name}, {shop.name}, {product.title} y {product.metafields.<namespace>.<key>} (hasta cinco metacampos de tipo texto, número, fecha o lista de texto; los demás tipos se rechazan). No se permiten enlaces en ningún punto de la nota — se rechazan las direcciones web, www., los dominios sueltos y las direcciones de email, también dentro del valor de un metacampo — y una variable desconocida se rechaza en lugar de dejarse como texto. Un message presente pero en blanco se rechaza; omite el campo si no quieres nota. variant_ids: limita la campaña a las asignaciones que sirven a esas variantes (ids sueltos o GIDs, 100 como máximo); omítelo para el producto completo. Un array vacío es 400 invalid_request, nunca “todo”. dry_run: ver la tabla.

A quién se envía. Por defecto, a todas las asignaciones del producto que tienen archivos, packs o enlaces; las asignaciones solo con clave y las personalizadas se omiten. Un comprador cuenta una sola vez sin importar cuántas variantes objetivo haya comprado, y el botón abre su compra más reciente. Los compradores que se dieron de baja de los emails de actualización de producto se omiten y se cuentan en opted_out_count.

Una campaña por producto cada 7 días, contando todas sus variantes y todos los orígenes — este endpoint, el indicador notify_customers en una escritura de asignación y el propio botón del comerciante. Dentro de esa semana, y mientras una campaña del producto siga en cola o enviándose, la respuesta es 429 notification_cooldown con Retry-After (segundos, hasta siete días) y error.details.next_available_at. No es el bucket de tokens por clave: no lo reintentes automáticamente — un bucle de reintentos basado en el 429 girará durante una semana. Programa la siguiente llamada en next_available_at. Cancelar una campaña no devuelve al producto sus 7 días; usa dry_run para comprobar una nota antes de enviar. Una campaña que falla con cero envíos sí libera el límite, así que basta con reintentarla.

Como máximo 5 campañas por tienda a la vez. Una tienda puede tener como máximo 5 campañas en cola o enviándose al mismo tiempo, contando todos sus productos y todos los orígenes. Una sexta es 429 too_many_active_notifications: error.details.limit es el máximo y error.details.active_notification_ids lista las campañas en cola o enviándose de esta tienda, de la más antigua a la más reciente. No hay Retry-After; consulta periódicamente GET /notifications/{id} de una de ellas y reintenta cuando haya terminado. Un dry run se rechaza de la misma manera. En una escritura de asignación se informa en data.notification, nunca como un 4xx.

Un email de actualización de producto por comprador al día. Un comprador recibe como máximo un email de actualización de producto de una tienda en cualquier periodo de 24 horas, contando por dirección de email, en todas las campañas, productos y orígenes. Se aplica cuando la campaña envía: un comprador que ya recibió uno se omite, y una omisión no es un fallo. Los compradores omitidos no se cuentan en sent_count, failed_count ni suppressed_count, así que recipient_count puede ser mayor que su suma. Una campaña en la que se omitieron todos los compradores termina en failed con error: recipients_recently_notified y no consume los 7 días del producto. Una en la que solo se omitieron algunos se completa con normalidad y sí los consume.

La espera del archivo. Si el archivo ZIP de una asignación objetivo se está regenerando — acabas de reemplazar sus archivos — la campaña espera hasta que la regeneración haya terminado para que ningún comprador descargue el archivo antiguo: waiting_for_archive: true en el 202 y en el GET. Solo una asignación que entrega un archivo ZIP hace esperar a una campaña. Una regeneración que falla, o que no avanza durante 60 minutos mientras se ejecuta (6 horas mientras aún está a la espera de empezar o de un nuevo intento), contados desde el último cambio de estado de la regeneración, no desde que se creó la campaña, hace fallar la campaña con cero envíos (error es archive_build_failed o archive_not_ready) y libera el límite; corrige los archivos y reintenta.

Idempotencia. Un 202 se repite durante 24 horas bajo la misma clave (mismo id, sin segunda campaña). Los rechazos nunca se almacenan, así que un reintento con la misma clave después de next_available_at se evalúa de nuevo. Usa una Idempotency-Key nueva por cada dry run: una clave repetida devuelve la vista previa almacenada, y la misma clave con y sin dry_run es 409 idempotency_conflict.

Estado en el GET. queued → processing → completed, failed o cancelled. completed con partial: true significa que algunos envíos fallaron o se suprimieron (ver sent_count, failed_count, suppressed_count), o que el envío se detuvo a mitad (ver más abajo). En failed, error es uno de interrupted, worker_crashed, send_aborted, archive_build_failed, archive_not_ready, email_disabled, invalid_message, plan_required, notifications_suspended, notifications_switched_off, nothing_sent, recipients_recently_notified, no_eligible_recipients, failed. source es admin, api o api_mapping.

Comprobaciones durante el envío. Antes de cada lote de hasta 500 emails, la campaña vuelve a comprobar la tienda. Se detiene si la suscripción pasó a estar inactiva o la tienda pasó al plan Free (plan_required), si se desactivaron los emails a clientes (email_disabled), si el envío se suspendió tras quejas (notifications_suspended) o si Alva desactivó las notificaciones (notifications_switched_off). Si se detiene antes de enviar un email a nadie, la campaña queda en failed con ese error y se liberan los 7 días del producto. Si se detiene después de enviar a algunos compradores, queda en completed con partial: true. nothing_sent significa que fallaron todos los envíos, así que nadie recibió el email; también libera los 7 días. no_eligible_recipients significa que, cuando la campaña envió, ya no quedaba nadie a quien enviar el email (todos los compradores se habían dado de baja o habían perdido el acceso a la descarga), así que no se envió nada y se liberan los 7 días.

Rechazos. 402 plan_required (la tienda está en el plan Free o su suscripción no está activa), 403 forbidden (la API está desactivada para la app o Alva ha desactivado la función — contacta con nosotros), 403 notifications_suspended (el envío está suspendido tras quejas — contacta con soporte), 404 mapping_not_found (no hay asignación para el producto, o una variante a la que ninguna asignación sirve o que Shopify no incluye entre las variantes del producto — error.details.unresolved_variant_ids), 409 multiple_mappings_match (error.details.ambiguous_variant_ids), 409 personalized_product, 422 invalid_message (error.details.errors[] nombra cada regla incumplida, error.details.max_length es el máximo), 422 email_disabled (los emails a clientes están desactivados en la app), 422 no_downloadable_content, 422 no_eligible_recipients (error.details.opted_out_count), 429 notification_cooldown, 429 too_many_active_notifications (error.details.limit, error.details.active_notification_ids), 409 app_not_installed (la nota nombra un metacampo o enviaste variant_ids, y Alva no tiene una sesión de Shopify activa para la tienda, normalmente porque se desinstaló la app), 500 internal_error (por ejemplo, Shopify no pudo devolver los metacampos del producto para la nota ni confirmar las variantes solicitadas, o la creación esperó más de 8 segundos detrás de las demás creaciones de la tienda: cada 500 de este endpoint libera la Idempotency-Key, así que reintenta la misma solicitud con la misma clave; si el intento fallido sí llegó a poner la campaña en cola, el reintento se rechaza con 429 notification_cooldown en lugar de iniciar una segunda). GET y cancel responden 404 notification_not_found para un id inexistente o ajeno, y cancel responde 409 notification_not_cancellable con error.details.status una vez que una campaña ha salido de la cola. Consulta la página de errores para saber qué hacer con cada uno.

Salud y estado

MétodoRutaPropósito
GET/healthComprobar la disponibilidad de la API.
GET/pingComprobar la autenticación.
GET/jobs/{jobId}Leer el estado de un trabajo asíncrono.

Documentación de la API

¿Te ha resultado útil?

¿Sigues con dudas? Escribe a admin@alvaapps.com.

Última actualización 2026-10-20