/ REMP integrace Interní dokument

02 — API kontrakt mezi systémy

Přehled komunikačních kanálů

Folio CMS  ──HTTP JSON──►  REMP CRM      (subscription sync, user sync, entitlement check)
Folio CMS  ──HTTP form/json──►  REMP Mailer    (newsletter template handoff, job creation)
Folio CMS frontend    ──JS (remplib)─►  REMP Campaign  (showtime, banner delivery)
REMP CRM              ──Webhook──►     Folio CMS      (subscription state changes, optional)
Ecoidentita           ──SSO / userinfo──►   Folio CMS      (authentication)
Ecoidentita           ──identity sync──►  REMP CRM       (user provisioning)

A. Economia → REMP CRM API

Poznámka: Na rozdíl od sekcí Mailer/Campaign níže nemáme lokálně k dispozici zdrojový kód REMP CRM. Následující CRM endpointy jsou tedy pracovní návrh integračního kontraktu, který je potřeba potvrdit s FatChilli.

A1. User Provisioning

Po registraci / přihlášení uživatele přes Ecoidentita, Folio CMS musí zajistit existenci uživatele v REMP CRM.

Endpoint (volaný z Folio CMS):

POST /api/v1/users/register
Authorization: Bearer {crm_api_token}
Content-Type: application/json

{
  "email": "user@example.com",
  "ext_id": "ecoidentita_user_id_12345",
  "source": "economia-cms",
  "first_name": "Jan",
  "last_name": "Novák",
  "send_email": false,
  "disable_email_validation": true
}

Response:

{
  "status": "ok",
  "user": {
    "id": 42,
    "email": "user@example.com",
    "ext_id": "ecoidentita_user_id_12345"
  }
}

Kdy se volá: Při prvním přihlášení uživatele přes Ecoidentita (pokud ještě neexistuje v CRM). Implementuje se jako after_sign_in callback nebo background job.

CMS třída: Economia::Remp::UserSyncService (nová) Folio model: Folio::Userremp_user_id (nové pole)


A2. User Update

Endpoint:

PUT /api/v1/users/{remp_user_id}
Authorization: Bearer {crm_api_token}

{
  "email": "new@example.com",
  "first_name": "Jan",
  "last_name": "Novák"
}

Kdy se volá: Při změně profilu uživatele v CMS (pokud CMS spravuje profil UI).


A3. Subscription Lifecycle (vlastní REMP CRM)

Důležité: Předplatné (subscription) vytváří, spravuje a ruší REMP CRM (FatChilli). CMS nevytváří subscriptions v CRM — místo toho se dotazuje na stav (viz A5 Entitlement Check) a přijímá webhooky (viz D1).

Typický flow:

  1. Čtenář přejde na checkout (REMP CRM UI nebo CRM API volaný z CMS frontendu)
  2. REMP CRM zpracuje platbu, vytvoří subscription
  3. REMP CRM notifikuje CMS webhookem (D1) → CMS invaliduje entitlement cache
  4. CMS ověřuje přístup přes A5 Entitlement Check

Self-care (zrušení, změna): Probíhá v REMP CRM — buď vlastní UI, nebo API volané z CMS frontendu. K vyjasnění s FatChilli.


A5. Entitlement Check (paywall)

Folio CMS volá při renderování článku s PaywallTag.

Endpoint:

GET /api/v1/users/{remp_user_id}/subscriptions?active=true
Authorization: Bearer {crm_api_token}

Response:

{
  "status": "ok",
  "subscriptions": [
    {
      "id": 789,
      "subscription_type": {
        "code": "hn_digital_monthly",
        "content_access": ["web", "premium"]
      },
      "start_time": "2026-08-01T00:00:00+02:00",
      "end_time": "2026-09-01T00:00:00+02:00"
    }
  ]
}

Logika v CMS:

# Economia::Paywall::EntitlementChecker (nová třída)
class EntitlementChecker
  def has_access?(user:, paywall_tag:)
    return true unless paywall_tag.present?
    return false unless user&.remp_user_id

    subscriptions = Remp::CrmClient.active_subscriptions(user.remp_user_id)
    subscriptions.any? do |sub|
      sub.content_access.include?(paywall_tag.access_level)
    end
  end
end

Cachování: Výsledek cachovat v Redis s TTL 60-300s per user, aby se nevolalo CRM API při každém page load.

Alternativa: REMP CRM by mohl poskytnout jednodušší endpoint GET /api/v1/users/{id}/access?content_type=premium — záleží na CRM verzi.


A4. Subscription Type Configuration

Před integrací FatChilli nakonfiguruje subscription types v REMP CRM. CMS potřebuje znát kódy pro entitlement check.

Endpoint (admin/setup — volá FatChilli):

POST /api/v1/subscription-types
Authorization: Bearer {crm_api_token}

{
  "code": "hn_digital_monthly",
  "name": "HN Digital – měsíční",
  "length": 31,
  "content_access": ["web", "premium"],
  "active": true
}

Mapování (REMP CRM definuje produkty, CMS zná kódy pro paywall):

REMP CRM produktSubscription Type CodeContent Access
HN Digital – měsíčníhn_digital_monthly["web", "premium"]
HN Digital – ročníhn_digital_yearly["web", "premium"]
HN Print + Digitalhn_print_digital_monthly["web", "premium", "print"]
HN Premiumhn_premium_monthly["web", "premium", "archive"]

B. Folio CMS → REMP Mailer API

Scope boundary: CMS v této integraci připravuje newsletterový obsah a předává ho do REMP Maileru. Reader subscriptions, user registration events, transactional reader e-maily, mail types a delivery ownership zůstávají na straně REMP/FatChilli.

B1. Newsletter Template Handoff

CMS vytvoří nebo zaktualizuje template v REMP Maileru z obsahu připraveného v editoru Folio.

Endpoint:

POST /api/v1/mailers/templates
Authorization: Bearer {mailer_api_token}
Content-Type: application/x-www-form-urlencoded

name=HN%20Denni%20prehled%20-%202026-08-01&
code=hn_daily_digest_20260801&
description=Generated%20by%20Folio%20CMS&
mail_type_code=hn_daily_digest&
mail_layout_code=hn_newsletter_layout&
subject=HN%20Denni%20prehled&
template_text=...&
template_html=...&
preheader=To%20nejdulezitejsi%20za%20dnesek

Poznámky z reálného remp kódu:

  • Handler přijímá form data, ne JSON
  • mail_type_code musí v Maileru existovat
  • Template musí mít mail_layout_id nebo mail_layout_code
  • code je v Maileru deduplikován na unikátní hodnotu

Relevantní Mailer handler: MailCreateTemplateHandler


B2. Stored Template Preview

REMP umí vyrenderovat již uložený template podle code.

Endpoint:

GET /api/v1/mailers/render-template?code=hn_daily_digest_20260801
Authorization: Bearer {mailer_api_token}

Důležité omezení: RenderTemplateApiHandler renderuje uložený template podle code; není to endpoint pro preview libovolného draft HTML. Draft preview je potřeba primárně řešit lokálně v CMS a/nebo až po uložení template do Maileru.

Relevantní Mailer handler: RenderTemplateApiHandler


B3. Newsletter Job Creation

Po předání template CMS vytvoří job, který REMP Mailer odešle na REMP-spravovaný segment / subscriber base.

Doporučený endpoint:

POST /api/v2/mailers/jobs
Authorization: Bearer {mailer_api_token}
Content-Type: application/json

{
  "template_code": "hn_daily_digest_20260801",
  "include_segments": [
    {
      "provider": "crm-segment",
      "code": "all_hn_digital"
    }
  ],
  "context": "daily_digest_2026_08_01",
  "start_at": "2026-08-01T06:00:00Z"
}

Poznámky z reálného remp kódu:

  • v1 endpoint používá template_id, segment_code, segment_provider
  • v2 endpoint používá template_code, include_segments[], exclude_segments[]
  • Mailer používá aliasy providerů crm-segment, remp-segment, mailer-segment

Relevantní Mailer handler: MailJobCreateApiHandler

CMS třída: Economia::Remp::NewsletterComposerService (nová)


B4. Reader E-mail Flows V REMP

Tyto endpointy v aktuálním remp existují, ale nejsou součástí CMS integračního kontraktu. Patří do reader části spravované v REMP/FatChilli:

  • POST /api/v1/users/user-registered
  • POST /api/v1/users/subscribe
  • POST /api/v1/users/un-subscribe
  • POST /api/v1/users/user-preferences
  • POST /api/v1/mailers/send-email
  • POST /api/v1/mailers/mail-type-upsert

C. REMP Campaign ← Folio Frontend

C1. Showtime (banner delivery)

Na frontendu Folio CMS se načte remplib.js, který komunikuje s Campaign:

<!-- V layoutu Folio CMS -->
<script src="https://campaign.remp.economia.cz/assets/lib/js/remplib.js"></script>
<script>
  var rempConfig = {
    userId: "<%= current_user&.remp_user_id %>",
    userSubscribed: <%= current_user_subscribed? %>,
    cookieDomain: ".hn.cz",
    campaign: {
      url: "https://campaign.remp.economia.cz",
      variables: {
        article_id: {
          value: function () { return "<%= @article.id %>" }
        },
        content_type: {
          value: function () { return "<%= @article.content_type %>" }
        }
      },
      pageviewAttributes: {
        section: "<%= @article.primary_category&.slug %>",
        content_type: "<%= @article.content_type %>"
      }
    }
  };

  remplib.campaign.init(rempConfig);
</script>

Campaign interně:

  • Vyhodnotí segmenty (přes segment provider → CRM nebo Beam)
  • Vrátí banner config pro showtime

C2. Campaign API (admin)

Vytváření a správa kampaní přes API (pro automatizaci z CMS):

POST /api/campaigns
Authorization: Bearer {campaign_api_token}

GET /api/campaigns
GET /api/banners
POST /api/schedule/{id}/start
POST /api/schedule/{id}/pause

Relevantní Campaign routes: Campaign/extensions/campaign-module/routes/api.php

  • Route::apiResource('campaigns', CampaignController::class)
  • Route::apiResource('banners', BannerController::class)
  • Route::apiResource('schedule', ScheduleController::class)

D. REMP → Economia (webhooky, volitelné)

D1. Subscription State Change Webhook

REMP CRM může notifikovat Folio CMS o změnách (pro cache invalidation):

POST https://hn.cz/api/internal/remp/webhooks/subscription-changed
X-REMP-Signature: {hmac_sha256}

{
  "event": "subscription.updated",
  "user_id": 42,
  "subscription_id": 789,
  "subscription_type_code": "hn_digital_monthly",
  "status": "expired",
  "timestamp": "2026-09-01T00:00:01+02:00"
}

CMS třída: Api::Internal::Remp::WebhooksController (nová) Akce: Invalidace entitlement cache, update lokálního stavu


E. Autentizace API komunikace

SměrMechanismusSpráva tokenů
CMS → REMP CRMBearer token (REMP CRM API token)Generován v REMP CRM admin
CMS → REMP MailerBearer token (Mailer API token)Konfigurace v Mailer .env
CMS → REMP CampaignBearer token (Campaign API token)Konfigurace v Campaign .env
REMP → CMS webhookHMAC-SHA256 signatureSdílený secret v konfiguraci obou systémů
Frontend → CampaignVeřejný showtime request přes remplib.jsBez write tokenu; případný top-level rempConfig.token je Beam property token, ne Campaign admin token
Čtenář → CMSEGO-SSO session / cookiesSession cookie na doméně

F. Nové třídy a služby v Economia CMS

Třída / ModulOdpovědnost
Economia::Remp::CrmClientHTTP klient pro REMP CRM API
Economia::Remp::MailerClientHTTP klient pro REMP Mailer API
Economia::Remp::CampaignClientHTTP klient pro REMP Campaign API (admin)
Economia::Remp::UserSyncServiceSynchronizace uživatelů Folio → CRM
Economia::Remp::NewsletterComposerServiceRender newsletter obsahu v CMS a handoff template/jobu do Maileru
Economia::Paywall::EntitlementCheckerOvěření přístupu uživatele k obsahu
Economia::Remp::EntitlementCacheRedis cache pro entitlement data z CRM
Economia::Remp::SyncUserJobSidekiq job pro async user sync
Api::Internal::Remp::WebhooksControllerPříjem webhooků z REMP CRM (cache invalidation)
Economia::Remp::ConfigurationRails config/initializer s URL/tokeny

G. Konfigurace (Environment Variables)

# REMP CRM
REMP_CRM_URL=https://crm.remp.economia.cz
REMP_CRM_API_TOKEN=xxxxxxxx

# REMP Mailer
REMP_MAILER_URL=https://mailer.remp.economia.cz
REMP_MAILER_API_TOKEN=xxxxxxxx

# REMP Campaign
REMP_CAMPAIGN_URL=https://campaign.remp.economia.cz
REMP_CAMPAIGN_API_TOKEN=xxxxxxxx

# Webhook
REMP_WEBHOOK_SECRET=xxxxxxxx

# Entitlement cache
REMP_ENTITLEMENT_CACHE_TTL=120