Caracol (POS)
Wine-vertical point-of-sale with a narrow consumer-read API for the Cookie Monster B2B portal.
URL: caracol.redbroomsoftware.comStatus: LIVE Tier: T2 (narrow surface)
What you can integrate
- Consumer linking — look up consumer accounts by phone or email across all Caracol tenants that have the portal enabled
- Portal branding — fetch a tenant's display name, logo, and brand colors for embedded catalog surfaces
- Product catalog reads — list active SKUs and prices for a tenant
- Order history + invoice request — surface a consumer's past orders and let them request CFDI invoicing (stamped via Constanza)
Authentication
Server-to-server only today. Requests carry:
http
X-API-Key: <COOKIE_MONSTER_API_KEY>
X-Source-App: cookie-monster
Content-Type: application/jsonThe API key is validated against the COOKIE_MONSTER_API_KEY environment variable on the Caracol side. OAuth2/PKCE user flows are not exposed for Caracol — all user identity flows through Camino.
Endpoints
| Method | Path |
|---|---|
| GET | /api/address/postal-code |
| POST | /api/ayuda/chat |
| POST | /api/ayuda/feedback |
| GET, POST | /api/ayuda/tickets |
| GET, PATCH | /api/ayuda/tickets/:id |
| POST | /api/ayuda/tickets/:id/sync |
| POST | /api/cfdi/adenda |
| POST | /api/cfdi/cancel |
| GET | /api/cfdi/cancel/preflight |
| POST | /api/cfdi/complemento-pago |
151 total — 21 admin/cron/internal (hidden) — +120 more primary endpoints not shown. Source: src/routes/api/**/+server.{ts,js} in the caracol repo.
Events emitted
| Event | Receivers | Description |
|---|---|---|
activity.logged | camino | A billable or tracked activity has been logged (time entry from Agora ghost timer, POS customer action in Caracol, vet/hotel log in Cosmos Pet or Madriguera) and sent to Camino for CRM activity tracking |
ai.usage | colectiva | AI token usage report for metering |
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). |
caja.closed | constanza | Cash register (caja) close summary from Caracol POS — end-of-day totals for fiscal reconciliation in Constanza |
caracol.creditnote.cancelled | constanza | Caracol cancelled a previously-stamped credit note — Constanza reverses both pólizas posted at issuance (revenue reversal + COGS reclass), restoring the books to their state before the credit note was issued. |
caracol.creditnote.issued | constanza | Caracol stamped a credit note (nota de crédito) for a customer — Constanza generates reversal pólizas: revenue side (Dr 4102 Devoluciones sobre Ventas / Cr payment) and COGS reclass (Dr 1151 Inventario or Dr 5005 Merma / Cr 5001) per item returnsTo flag. |
caracol.intercompany_movement_completed | constanza | Inter-tenant movement reaches ownership-transfer state (FOB-Destination = at receive; FOB-Origin = at dispatch). Triggers Constanza intercompany CFDI emission with partes-relacionadas detection (per OL-2). |
caracol.invoice.stamped | camino, constanza | A CFDI was stamped through Caracol's own PAC flow (not routed through Constanza). Distinct from cfdi.stamped which Constanza emits after stamping. Used for unified fiscal record + subscription metering. |
caracol.order.created | camino | A new order was created in Caracol POS — feeds Camino CRM order pipeline and activity feed |
caracol.order.status_changed | camino | Order status transition in Caracol POS (e.g., preparing → ready → delivered) — Camino mirrors for CRM timeline |
caracol.shipment.created | camino | A Skydropx shipment label was generated in Caracol — Camino records cost, applies markup, and bills the tenant. Also triggers WhatsApp tracking notification via Camino. |
cfdi_global.stamped | camino, constanza | Monthly factura global (CFDI Público en General) successfully stamped by the monthly-cfdi-publico cron. Distinct from caracol.invoice.stamped (per-sale) — carries batch context (period, salesIds) for downstream fiscal reconciliation and subscription metering. |
cobranza.reminder | (none declared) | B2B payment collection reminder triggered when caracol sales data shows overdue invoices. Internal lifecycle event reserved for the cobranza/dunning feature; no emit site exists today (designIntentReserved S327). When wired, caracol owns the trigger logic and surfaces reminders to end-customers directly via WhatsApp/email — no cross-app receivers planned. |
customer.created | camino, constanza, garita | A new customer/contact/third-party record was created — used for CRM sync, fiscal pre-registration, and cross-app contact linking. |
customer.updated | agente, colectiva, constanza, cosmos-pet, garita, hoja, madriguera | A customer/contact record was updated in Camino — receiver apps sync the changed fields to their local customer records for display and invoicing accuracy. |
inventory.cogs | constanza | Cost of goods sold event emitted by POS on sale completion. Triggers Constanza to post a COGS poliza (Dr 5001 / Cr 1151). |
inventory.low | camino, colectiva | A 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. |
inventory.received | agente | An inventory shipment was received at the warehouse — Agente updates the shipment status and the landed cost is finalized for COGS accounting. |
inventory.transit_loss | constanza | Pérdida en tránsito recorded at receive time when the user picks the 'register as transit loss' resolution for a short-receive (received < shipped). Constanza posts a merma póliza Dr 5005 / Cr 1151 when totalCost is present, and persists an audit row in caracol_inventory_transit_losses keyed on (movementId, productId, branchId) for idempotency. Sender clears source.reserved by the full shipped quantity but does NOT restore source.quantity — the diff is written off as merma. Restore-to-source resolution does NOT emit this event (no loss occurred). |
sale.completed | colectiva, constanza | A POS sale has been completed |
vendor.created | constanza | A vendor (supplier) was created in a source app. Constanza accumulates these for monthly SAT DIOT submission (Declaración Informativa de Operaciones con Terceros). PD-074 (S313) — replaces the broken Constanza→{caracol,hoja,cosmos-pet,colectiva} POST /api/ecosystem/diot/vendors pull (S271 BROKEN #7). |
vendor.updated | constanza | A vendor's fields changed in a source app. Constanza merges non-undefined fields into the accumulated DIOT vendor record (matched by vendorId). PD-074 (S313). |
Events consumed
| Event | Senders | Description |
|---|---|---|
constanza.poliza.reclassified | constanza | An accountant reclassified partidas in a póliza (journal entry) — Caracol mirrors the updated category metadata on the referenced sale so future margin and ROI metrics reflect the corrected classification. No inventory mutation downstream. |
creditnote.issued | constanza | A credit note (nota de crédito) was issued in Constanza — Caracol records the adjustment against the original invoice for reconciliation |
employee.missing_data | constanza | Constanza detected an employee with missing fiscal data (RFC/CURP/etc.) — routed back to the source app that created the employee so the missing fields can be completed. |
fiscal.resico_warning | constanza | Constanza detected an organization whose RESICO income utilization crossed the warning threshold (>=90%). Routed to accounting-sensitive apps so they can surface limit warnings in POS/invoice flows. |
handoff.completed | baul | Generic physical handoff completed with proof. Covers document delivery, product returns, sample collection, key handoff, equipment transfer. Baul physical layer event. |
inventory.in_transit | baul | A Baúl delivery order has been dispatched and is en route — Caracol surfaces an in-transit status on the linked movement. Fire-and-forget; Caracol may show location + ETA when provided. |
inventory.pickup_discrepancy | baul | The driver pickup count was short at Baúl pickup time — Caracol surfaces a banner so the user can accept_short_pickup or dispute. Carries per-product expected vs actual counts. |
invoice.compliance_issue | constanza | Constanza detected an invoice compliance issue (missing/invalid RFC, duplicate, format error) — routed back to the source app for review. |
payment.cancelled | (none declared) | A payment was cancelled before capture (abandoned/voided checkout) — distinct from payment.refunded (post-capture reversal). Receivers release any provisional hold/order tied to the payment. S410 registry-integrity reconciliation: caracol + cosmos-pet declared this receiver in apps.json without a matching events.json entry; no ecosystem sender is wired yet (senders:[] until a payment source emits it). |
payment.chargeback_resolved | colectiva | A MercadoPago chargeback reached a terminal state. Colectiva emits this when verdict.terminal && outcome ∈ {lost, won, coverage}. Constanza uses it to post a counter-póliza and (on lost + originalCfdiUuid present) cancel the original CFDI. Canonical contract is whatever colectiva/src/lib/services/ecosystem-webhook.service.js notifyPaymentChargebackResolved emits. |
payment.refunded | colectiva, comal | A 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. |
reservation.arrived | mancha | A reservation party arrived at the restaurant — Caracol POS updates the table status from waiting to arrived, La Hoja POS mirrors the reservation timeline. |
reservation.cancelled | mancha | A reservation was cancelled in Mancha — Caracol POS removes from the waitlist/queue and releases the table. |
reservation.completed | mancha | A restaurant reservation was completed (the party finished dining) — Colectiva records for revenue analytics, Caracol POS releases the table, La Hoja POS mirrors the timeline. |
reservation.created | madriguera, mancha | A restaurant reservation has been created |
reservation.seated | mancha | A reservation party was seated at the restaurant — Caracol POS starts the table timer, La Hoja POS mirrors the seating event. |
reservation.updated | mancha | Reservation details changed in Mancha (time/party size/contact) — Caracol POS and La Hoja POS update their mirrors. |
shipment.received | agente | [auto-derived] shipment.received event |
subscription.activated | camino, colectiva | A subscription plan has been activated for a tenant — all apps that gate features behind the subscription tier update their local tier state. |
subscription.cancelled | camino, colectiva | A subscription has been cancelled — all apps that gate features behind the subscription tier update their local tier state to free/cancelled. |
subscription.changed | camino | A subscription plan has been upgraded or downgraded — receiver apps update their tier gates and feature access accordingly. |
subscription.suspended | camino | A subscription was suspended due to non-payment or compliance issue — Camino disables access until resolution. Receiver apps lock out the tenant and surface a suspension banner. |
tips.processed | colectiva | Tips collected via Colectiva have been processed and distributed to staff — Caracol POS records the tip distribution for shift reports and labor analytics. |
Webhook signature
Standard ecosystem HMAC-SHA256 over the raw body with a 5-minute timestamp window. See Webhooks.
Gotchas
- Phone normalization strips Mexican country code (
+52) and mobile prefix (1) before matching. Always pass the number in any format — normalization happens server-side. - The Consumer API is read-only for partners. POS mutations (create sale, refund) are internal to the Caracol operator console.
- Invoice requests are async — they emit
invoice.requested, Constanza stamps, andcfdi.stampedfires back into Camino for CRM attachment. Do not block the user on stamping.