Skip to main content

Crear pase

POST /v1/passes/create

Headers

HeaderValor
X-API-KeyTu API key
Content-Typeapplication/json

Apple Wallet — Event Ticket con QR

{
  "pass_type": "apple",
  "pass_data": {
    "serial_number": "EVT-2026-001",
    "organization_name": "Mi Empresa",
    "description": "Entrada al evento",
    "style": "eventTicket",
    "background_color": "rgb(30, 60, 120)",
    "foreground_color": "rgb(255, 255, 255)",
    "label_color": "rgb(200, 200, 255)",
    "logo_text": "Mi Empresa",
    "barcodes": [{
      "message": "EVT-2026-001",
      "format": "PKBarcodeFormatQR",
      "messageEncoding": "iso-8859-1"
    }],
    "header_fields": [
      {"key": "date", "label": "FECHA", "value": "15 Mayo 2026"}
    ],
    "primary_fields": [
      {"key": "event", "label": "EVENTO", "value": "Torneo MX Open"}
    ],
    "secondary_fields": [
      {"key": "loc", "label": "LUGAR", "value": "Club Deportivo"},
      {"key": "time", "label": "HORA", "value": "10:00 AM"}
    ],
    "icon_base64": "iVBORw0KGgo..."
  }
}

Campos de pass_data (Apple)

CampoTipoDescripción
serial_numberstringRequerido. Identificador único del pase
organization_namestringRequerido. Nombre de la organización
descriptionstringRequerido. Descripción del pase
stylestringeventTicket, boardingPass, coupon, storeCard, generic (default)
background_colorstringColor de fondo CSS, e.g. "rgb(30, 60, 120)"
foreground_colorstringColor de texto
label_colorstringColor de labels
logo_textstringTexto junto al logo
barcodesarrayBarcodes: PKBarcodeFormatQR, PKBarcodeFormatPDF417, PKBarcodeFormatAztec, PKBarcodeFormatCode128
header_fieldsarrayCampos en la parte superior
primary_fieldsarrayCampos principales (grandes)
secondary_fieldsarrayCampos secundarios
auxiliary_fieldsarrayCampos auxiliares
back_fieldsarrayCampos en el reverso del pase

Estructura de campos (Apple)

Cada campo en header_fields, primary_fields, secondary_fields, auxiliary_fields y back_fields tiene esta estructura:
PropiedadTipoDescripción
keystringRequerido. Identificador único del campo
valuestringRequerido. Valor visible en el pase
labelstringEtiqueta sobre el valor
changeMessagestringMensaje de notificación al actualizar. Usa %@ para insertar el nuevo valor
textAlignmentstringPKTextAlignmentLeft, PKTextAlignmentCenter, PKTextAlignmentRight
changeMessage y notificaciones push: Para que el usuario reciba una notificación visible en la pantalla de bloqueo al actualizar un pase, el campo debe incluir changeMessage. Sin este atributo, el pase se actualiza silenciosamente.
{
  "key": "match",
  "label": "PRÓXIMO PARTIDO",
  "value": "Sáb 10:00am · Cancha 3 vs Borjas/Reyes",
  "changeMessage": "Partido actualizado: %@"
}
Cuando el valor cambia via PUT, iOS muestra un banner:
Pase actualizado — Partido actualizado: Dom 2:30pm · Cancha 5 vs García/López | icon_base64 | string | Icon PNG @1x (29×29 pt) | | icon_2x_base64 | string | Icon PNG @2x (58×58 px) — recomendado | | icon_3x_base64 | string | Icon PNG @3x (87×87 px) | | logo_base64 | string | Logo PNG @1x (160×50 pt) | | logo_2x_base64 | string | Logo PNG @2x (320×100 px) — recomendado | | logo_3x_base64 | string | Logo PNG @3x (480×150 px) | | strip_base64 | string | Strip PNG @1x (375×144 pt) — banda de acento con info dinámica | | strip_2x_base64 | string | Strip PNG @2x (750×288 px) — recomendado | | strip_3x_base64 | string | Strip PNG @3x (1125×432 px) | | thumbnail_base64 | string | Thumbnail PNG (90×90 pt / 180×180 @2x) | | relevant_date | string | Fecha W3C para relevancia | | expiration_date | string | Fecha de expiración W3C | | locations | array | [{"latitude": 19.43, "longitude": -99.13, "relevantText": "Cerca del evento"}] |

Crear pase desde template

Si tienes un template configurado, solo necesitas template_id + los overrides:
{
  "template_id": "entrada-torneo",
  "pass_data": {
    "serial_number": "TP-2026-042",
    "barcodes": [{"message": "TP-2026-042", "format": "PKBarcodeFormatQR", "messageEncoding": "iso-8859-1"}],
    "header_fields": [{"key": "date", "label": "FECHA", "value": "1 Jun 2026"}],
    "primary_fields": [{"key": "event", "label": "EVENTO", "value": "Torneo Padel Verano"}],
    "secondary_fields": [
      {"key": "loc", "label": "LUGAR", "value": "Club Reforma"},
      {"key": "time", "label": "HORA", "value": "9:00 AM"}
    ],
    "auxiliary_fields": [{"key": "cat", "label": "CATEGORIA", "value": "Open"}]
  }
}
El pass_type y style se infieren del template. Los campos del template se mergean con los overrides (el request gana).

Respuesta (202)

{
  "job_id": "623f7796-...",
  "status": "pending"
}
Consulta GET /v1/jobs/{job_id} para obtener el resultado:
{
  "status": "success",
  "result": {
    "pass_id": "b4eb23fa-...",
    "pkpass_base64": "UEsDBBQAAA..."
  }
}

Descarga directa

GET /v1/passes/{pass_id}/download
Devuelve el .pkpass con Content-Type: application/vnd.apple.pkpass.

Google Wallet

Paso 1: Crear clase (una por torneo/evento)

POST /v1/google/classes
Cada torneo o evento necesita su propia clase. Los datos de la clase (nombre, sede, fechas) se muestran en el frente de todos los pases de esa clase.
{
  "class_type": "eventTicket",
  "class_data": {
    "id": "ISSUER_ID.torneo-slug",
    "issuerName": "Mi Empresa",
    "reviewStatus": "UNDER_REVIEW",
    "eventName": {
      "defaultValue": {"language": "es", "value": "Nombre del Torneo"}
    },
    "venue": {
      "name": {"defaultValue": {"language": "es", "value": "Club / Sede"}},
      "address": {"defaultValue": {"language": "es", "value": "Ciudad, Estado"}}
    },
    "dateTime": {
      "start": "2026-06-22T09:00:00",
      "end": "2026-06-28T22:00:00"
    },
    "hexBackgroundColor": "#0B1F3A",
    "logo": {
      "sourceUri": {"uri": "https://url-del-logo.png"}
    },
    "heroImage": {
      "sourceUri": {"uri": "https://url-del-banner-1032x336.png"}
    }
  }
}
Respuesta (201):
{"status": "created", "class_id": "ISSUER_ID.torneo-slug"}

Actualizar clase

Si cambia la sede, fechas o nombre del torneo:
PUT /v1/google/classes/{class_id}
{
  "class_type": "eventTicket",
  "class_data": {
    "venue": {
      "name": {"defaultValue": {"language": "es", "value": "Nueva Sede"}}
    }
  }
}
Todos los pases de esa clase se actualizan automáticamente.

Consultar clase

GET /v1/google/classes/{class_id}?class_type=eventTicket

Paso 2: Crear pase (uno por jugador)

{
  "pass_type": "google",
  "pass_data": {
    "class_id": "ISSUER_ID.torneo-slug",
    "class_type": "eventTicket",
    "object_id": "ISSUER_ID.jugador-UUID",
    "object_data": {
      "id": "ISSUER_ID.jugador-UUID",
      "classId": "ISSUER_ID.torneo-slug",
      "state": "ACTIVE",
      "ticketHolderName": "Nombre del Jugador",
      "ticketType": {"defaultValue": {"language": "es", "value": "Categoría"}},
      "ticketNumber": "BIB-0241",
      "barcode": {"type": "QR_CODE", "value": "UUID-JUGADOR"},
      "textModulesData": [
        {"id": "next_match", "header": "Próximo Partido", "body": "Por definir"}
      ]
    }
  }
}
Campo del objetoDescripción
ticketHolderNameNombre del jugador (visible en el frente)
ticketTypeCategoría del jugador
ticketNumberDorsal o ID del jugador
textModulesDataCampos dinámicos (próximo partido, resultado, etc.)
El eventName, venue y dateTime del frente vienen de la clase (no del objeto). Resultado:
{
  "status": "success",
  "result": {
    "pass_id": "...",
    "save_link": "https://pay.google.com/gp/v/save/<jwt>"
  }
}
Importante: cada object_id debe ser único. Si se reutiliza un ID ya creado, Google rechaza el save link.

Actualizar pase

PUT /v1/passes/{pass_id}
Actualiza un pase existente. Mergea los campos nuevos sobre los existentes, re-firma el .pkpass, y envía push notification a dispositivos registrados.

Apple Wallet

Acepta campos en camelCase (auxiliaryFields) o snake_case (auxiliary_fields). Incluir changeMessage para notificación visible en lock screen.
{
  "pass_data": {
    "auxiliaryFields": [
      {
        "key": "match",
        "label": "PRÓXIMO PARTIDO",
        "value": "Dom 2:30pm · Cancha 5 vs García/López",
        "changeMessage": "Partido actualizado: %@"
      }
    ]
  }
}

Google Wallet

Incluir notify_message para enviar notificación visible al usuario.
{
  "pass_data": {
    "textModulesData": [
      {"id": "next_match", "header": "Próximo Partido", "body": "Dom 2:30pm · Cancha 5 vs García/López"}
    ],
    "notify_message": "Tu próximo partido fue actualizado"
  }
}

Respuesta (202)

{
  "pass_id": "b4eb23fa-...",
  "job_id": "...",
  "status": "updating"
}

Estado del pase

GET /v1/passes/{pass_id}/status
Consulta si un pase está instalado en el dispositivo del usuario.

Respuesta (200) — Apple Wallet

{
  "pass_id": "e39b84be-...",
  "pass_type": "apple",
  "version": 5,
  "status": "active",
  "installed_devices": 2,
  "is_installed": true
}
Apple notifica a Axelo cuando un dispositivo agrega o elimina el pase. installed_devices muestra cuántos dispositivos lo tienen activo.

Respuesta (200) — Google Wallet

{
  "pass_id": "a4864ef7-...",
  "pass_type": "google",
  "version": 3,
  "status": "active",
  "google_status": "ACTIVE",
  "has_users": true,
  "is_installed": true
}
CampoDescripción
google_statusEstado del objeto en Google: ACTIVE, COMPLETED, EXPIRED, INACTIVE, o not_found si fue borrado
has_userstrue si al menos un usuario tiene el pase guardado en Google Wallet
is_installedResumen: true si hay evidencia de que el pase está en un dispositivo
Google no envía callbacks en tiempo real cuando un usuario borra el pase — este endpoint consulta el estado directamente a la API de Google.

Webhook de device registration (Apple)

Axelo puede notificar a tu backend cuando un usuario instala o elimina un pase de Apple Wallet.

Configuración

En el dashboard admin → detalle del tenant → sección “Wallet Webhook”, configura la URL destino. O via API:
PUT /dash/api/tenants/{id}/wallet-webhook
{"wallet_webhook_url": "https://api.tuapp.com/webhooks/wallet"}

Payload que recibe tu webhook

POST https://api.tuapp.com/webhooks/wallet
Content-Type: application/json

{
  "action": "register",
  "pass_id": "e3ade6ad-1bff-4161-ae48-5d18faa6f0ee",
  "serial_number": "461911c7-86e1-40b5-9358-d2c572647f54",
  "device_id": "de95fb1794d9857bb1eb5bcf7fd72014",
  "tenant_id": "torneos-pro",
  "timestamp": "2026-04-29T05:09:38Z"
}
CampoDescripción
action"register" cuando el usuario agrega el pase, "unregister" cuando lo elimina
pass_idID del pase en Axelo
serial_numberSerial del pase en Apple Wallet
device_idIdentificador del dispositivo (deviceLibraryIdentifier de Apple)
timestampHora UTC del evento
El webhook se dispara de forma asíncrona — no bloquea la respuesta a Apple. Si tu endpoint falla, Axelo loguea el error pero no reintenta. Solo aplica a Apple Wallet. Google Wallet no notifica cuando un usuario elimina un pase — usa GET /v1/passes/{id}/status para consultar bajo demanda.

Guía de diseño

Colores del sistema

TokenHexUso
Navy#0B1F3AbackgroundColor base de todos los pases
Blue#1A56DBCTA, links, acento Torneos Pro default
Sky#3B82F6Acento secundario, iconos
White#FFFFFFforegroundColor y labelColor

Color de acento por torneo

El labelColor en Apple y hexBackgroundColor en Google se usan para el acento del torneo:
AcentoHexUso típico
Amber#F59E0BTorneos de verano
Green#22C55ECorporativos
Sky#3B82F6Series oficiales (default)
Red#EF4444Premium / invitacionales
Purple#A855F7Femenino / alternativos

Strip image (Apple)

La strip.png es la banda de acento que muestra la hora del próximo partido. Se genera dinámicamente con el accent del torneo y se re-envía en cada update:
  • Dimensiones: 375×144 @1x, 750×288 @2x, 1125×432 @3x
  • Contenido: fondo con gradient del accent + hora del partido + pista + rival
  • Enviar como: strip_base64 (o strip_2x_base64 para retina)
  • Regenerar: cada vez que cambia el próximo partido

Catálogo de push notifications

EventoTriggerMensaje ejemplo
match.upcoming30 min antes del partido”Tu partido empieza en 30 min — Pista 4 · 09:30 · vs López”
match.result.recordedOrganizador registra resultado”Resultado registrado · 6-3, 6-4 — Pasas a cuartos”
player.advancedJugador avanza de ronda”¡Felicitaciones! Avanzaste a semifinales”
tournament.finishedFinal registrada”Torneo finalizado · 2º lugar”
Para Apple, incluir changeMessage en los campos dinámicos. Para Google, incluir notify_message en el PUT.

Errores

CódigoCausa
400pass_type inválido o pass_data faltante
401API key inválida
402Saldo insuficiente (1 token por pase)
403Canal wallet no habilitado para tu tenant
404Pase no encontrado