Skip to content

Comal (comal.redbroomsoftware.com)

Multi-tenant e-commerce SaaS — store builder with subscription clubs, gated digital content, physical product shipping, gift cards, and store credit, all on a single platform.

URL: https://comal.redbroomsoftware.comStatus: LIVE Tier: T2 (vertical SaaS primitive)

T1 apps are indispensable horizontal primitives. T2 apps are vertical SaaS or single-domain primitives — primitive-like in their domain but not universal dependencies.

What you can integrate

  • Order events — receive order.completed and order.refunded when a consumer checkout finalizes or a refund is issued
  • Customer creationcustomer.created fires when a new buyer registers on a store, enabling Camino CRM enrichment
  • Product catalog syncproduct.updated keeps downstream inventory or search indexes current
  • Subscription club hooks — Comal manages recurring subscription orders; consume catalog.sync.completed / catalog.sync.failed for Camino-driven catalog pushes
  • Fiscal integration — receives cfdi.stamped / cfdi.failed from Constanza and wallet.payout_completed from Colectiva for merchant earnings settlement

Authentication

http
Authorization: Bearer <api_key>
Content-Type: application/json

User identity flows through Camino SSO. Per-store API keys are issued from the Comal merchant console. Consumer-facing checkout uses session tokens, not API keys.

Endpoints

MethodPath
GET/api/address/lookup
GET/api/catalog/:slug
POST/api/content/:id
POST/api/content/purchase
POST/api/content/stream-upload-url
POST/api/content/upload-url
POST/api/discounts/validate
POST/api/ecosystem/upsell-track
GET, POST/api/ecosystem/webhooks
GET/api/gift-cards/denominations

40 total — 9 admin/cron/internal (hidden) — +21 more primary endpoints not shown. Source: src/routes/api/**/+server.{ts,js} in the comal repo.

Events emitted

EventReceiversDescription
app.tenant_id_assigned(none declared)An app has bound its local tenant identifier to a canonical RBS org for the first time (or backfilled an existing binding). NOT routed via the standard webhook bus — producer calls CPR POST /api/v1/internal/tenant-mapping/upsert directly with X-RBS-Auth: App HMAC. Receiver list is empty because no app-side handler exists; the consumer is the Control Plane (ecosystem.redbroomsoftware.com). Topic 25 Phase 3 substrate — populates app_tenant_mappings junction. Senders list will grow as each app's producer wires (caracol first per S381 Phase 1 Session 3).
customer.createdcamino, constanza, garitaA new customer/contact/third-party record was created — used for CRM sync, fiscal pre-registration, and cross-app contact linking.
inventory.lowcamino, colectivaA product inventory fell below the low-stock threshold — Colectiva records the alert for analytics; Camino logs it as a TenantIntelligence signal in organization_activity_log.
order.completedcolectiva, constanzaAn e-commerce order has been completed (paid + fulfilled)
order.refundedcolectiva, constanzaAn e-commerce order has been refunded
payment.refundedbaul, mancha, servilleta, agora, constanza, cosmos-pet, caracolA payment was refunded by Colectiva — voluntary refund initiated by a tenant app or by Colectiva ops, OR an involuntary MP-platform-side refund. Receivers branch on paymentReferenceType. For voluntary refunds with proration, isPartial=true and proration block carries period bounds. paymentLayer is the primary routing discriminator; receivers MUST check it before paymentReferenceType.
product.createdcaminoA new product was created in Comal — Camino syncs to the CRM product catalog for cross-channel posting (e.g., TikTok catalog, social feeds).
product.deletedcaminoA Comal product was deleted — Camino removes from cross-channel catalog mirrors.
product.updatedcamino[auto-derived] product.updated event

Events consumed

EventSendersDescription
catalog.sync.completedcaminoCamino → Comal callback when a TikTok catalog sync succeeds for a Comal store product. Comal updates products.tiktok_product_id + tiktok_synced_at.
catalog.sync.failedcaminoCamino → Comal callback when a TikTok catalog sync fails. Comal surfaces the error to the merchant in the product list.
cfdi.failedconstanzaA CFDI invoice stamping has failed
cfdi.stampedconstanzaA CFDI invoice has been stamped by the SAT via Constanza — receiver apps attach the UUID to their local invoice record and update status.
invoice.compliance_issueconstanzaConstanza detected an invoice compliance issue (missing/invalid RFC, duplicate, format error) — routed back to the source app for review.
subscription.activatedcamino, colectivaA subscription plan has been activated for a tenant — all apps that gate features behind the subscription tier update their local tier state.
subscription.cancelledcamino, colectivaA subscription has been cancelled — all apps that gate features behind the subscription tier update their local tier state to free/cancelled.
subscription.changedcaminoA subscription plan has been upgraded or downgraded — receiver apps update their tier gates and feature access accordingly.
subscription.expiredcaminoA subscription has expired (end of billing period, no renewal)
subscription.past_duecaminoA tenant's subscription entered past_due state after a failed renewal — Camino dunning flow pauses feature access without cancelling. Receiver apps mark memberships or subscriptions past_due until payment is received.
subscription.trial_expiringcaminoA trial subscription is expiring soon — receiver apps surface an upgrade prompt to the tenant operator.
subscription.trial_startedcaminoA trial subscription was started — receiver apps activate trial-tier features for the new tenant.
wallet.payout_completedcolectiva[auto-derived] wallet.payout_completed event

Webhook signature

Standard ecosystem HMAC-SHA256 over the raw body with a 5-minute timestamp window. See Webhooks.

OpenAPI

Coming in the OpenAPI generator phase — see /reference/openapi.

SDK

See /sdk/ for @r-bsoftware/ecosystem-sdk helpers.

Gotchas

  • Comal stores are isolated by comal_store_{id}. An API key is scoped to a single store — there is no cross-store query surface.
  • Subscription club orders emit order.completed like a standard one-time order. Differentiate recurring from one-time purchases using the subscriptionId field in the payload.
  • CFDI invoice requests (/api/invoices/request) are async — they emit invoice.requested, Constanza stamps, and cfdi.stamped fires back. Do not poll the payment endpoint for fiscal status.

Red Broom Software Ecosystem