Saltar al contenido
GuestMakerDesarrolladores
Vista generalDocumentaciónEventosSDKSandboxNovedades
EN/ES
Solicitar acceso
Vista generalDocumentaciónEventosSDKSandboxNovedades
Solicitar acceso
Volver a la vista general

Integración con PMS

de servidor a servidor

Un endpoint de lectura para cargar el estado del socio en la reserva. Cinco webhooks firmados con HMAC para mantenerte al día con los cambios de saldo. Sin consultas periódicas.

GET /reservation-snapshot
Devuelve en una sola llamada todo lo necesario para mostrar la interfaz de crédito monetario durante la estancia o a la salida.
GET /api/v1/loyalty/reservation-snapshot?reservation_id=${reservationId}
Authorization: Bearer ${GUESTMAKER_API_KEY}
Accept: application/json

// Response (200)
{
  "data": {
    "member": {
      "id": "uuid",
      "member_number": "ABC123",
      "email": "guest@example.com",
      "tier": "silver",
      "points_balance": 12500,
      "spendable_points": 9500    // = points_balance - active holds
    },
    "active_holds": [
      {
        "hold_id": "uuid",
        "external_reference_id": "BOOK-2026-001",
        "points": 3000,
        "amount_value": 30.00,
        "currency": "EUR",
        "surface": "booking_direct",
        "status": "active",
        "expires_at": "2026-06-01T12:30:00Z"
      }
    ],
    "config": {
      "enabled": true,
      "surfaces": { "booking_direct": true, "in_stay": true, "checkout": false },
      "allowed_channels": ["direct", "website", "phone"],
      "redemption_rate_eur": 100,        // points per EUR 1
      "min_points_per_redemption": 500,
      "hold_minutes": 10
    }
  }
}

Usa spendable_points para decidir qué puede aplicar el socio ahora. No uses points_balance. Las retenciones activas ya están descontadas.

Eventos de webhook
Cinco eventos. Todos firmados con HMAC. Se reintentan con espera exponencial (1m, 5m, 30m, 4h, 24h).
loyalty.credit.held
{
  "event": "loyalty.credit.held",
  "tenant_id": "uuid",
  "occurred_at": "2026-06-01T10:00:00Z",
  "data": {
    "hold_id": "uuid",
    "member_id": "uuid",
    "points": 3000,
    "amount_value": 30.00,
    "currency": "EUR",
    "surface": "booking_direct",
    "external_reference_id": "BOOK-2026-001",
    "expires_at": "2026-06-01T10:10:00Z"
  }
}
loyalty.credit.confirmed
{
  "event": "loyalty.credit.confirmed",
  "tenant_id": "uuid",
  "occurred_at": "2026-06-01T10:05:00Z",
  "data": {
    "hold_id": "uuid",
    "transaction_id": "uuid",
    "member_id": "uuid",
    "points": 3000,
    "amount_value": 30.00,
    "currency": "EUR",
    "external_reference_id": "BOOK-2026-001"
  }
}
loyalty.credit.released
{
  "event": "loyalty.credit.released",
  "tenant_id": "uuid",
  "occurred_at": "2026-06-01T10:11:00Z",
  "data": {
    "hold_id": "uuid",
    "external_reference_id": "BOOK-2026-001",
    "cause": "expired"   // "released" if called via /credit/release
  }
}
loyalty.credit.reversed
{
  "event": "loyalty.credit.reversed",
  "tenant_id": "uuid",
  "occurred_at": "2026-06-02T09:00:00Z",
  "data": {
    "hold_id": "uuid",
    "refund_transaction_id": "uuid",
    "member_id": "uuid",
    "points": 3000,
    "external_reference_id": "BOOK-2026-001",
    "cause": "cancellation"
  }
}
loyalty.balance.changed
{
  "event": "loyalty.balance.changed",
  "tenant_id": "uuid",
  "occurred_at": "2026-06-01T10:05:00Z",
  "data": {
    "member_id": "uuid",
    "new_balance": 9500
  }
}
Verificación de firma HMAC
Verifica X-Loyalty-Signature en todos los webhooks entrantes. Rechaza payloads sin firma o con firma incorrecta.
// Node.js: verify the X-Loyalty-Signature header on every webhook.
import crypto from 'node:crypto';

function verifyLoyaltyWebhook(rawBody: string, signature: string, secret: string) {
  const expected = crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
  // Constant-time compare to avoid timing side channels.
  const a = Buffer.from(expected, 'utf8');
  const b = Buffer.from(signature, 'utf8');
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

// Express handler
app.post('/webhooks/loyalty', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.header('X-Loyalty-Signature') || '';
  if (!verifyLoyaltyWebhook(req.body.toString('utf8'), signature, process.env.LOYALTY_WEBHOOK_SECRET!)) {
    return res.status(401).end();
  }
  const payload = JSON.parse(req.body.toString('utf8'));
  // ... dispatch on payload.event
  res.status(200).end();
});

El secreto de firma se genera al registrar el webhook en Ajustes → Fidelización → Crédito monetario. Para rotarlo, añade una URL de webhook nueva, verifica con ambos secretos en paralelo y elimina la antigua.

GuestMaker

El CRM con IA omnicanal
para grupos hoteleros.

● de Hotelinking ↗
DESARROLLARInicio rápidoReferencia de la APIAutenticaciónWebhooksSandbox de API
EXPLORAREventos webSDK y bibliotecasFidelización y SSOCrédito monetarioNovedades
CONECTARSolicitar acceso a la APIPlataforma GuestMakerIntegraciones
© 2026 GuestMaker · Hotelinking, S.L.Palma de Mallorca, España
PrivacidadCondicionesAviso legal