Skip to Content
Getting StartedExternal Product

External Product Integration

Integrate third-party products with the Loop comms platform using webhooks, API keys, and the event schema system.

Overview

External products (e-commerce platforms, CRMs, analytics tools, etc.) connect to the comms platform through:

  1. Inbound webhooks — Your product sends events to our webhook endpoint
  2. Outbound webhooks — The comms platform sends delivery events to your endpoint
  3. REST API — Direct API calls for event firing and management

API Keys

Each external integration gets a scoped API key. Request one through the admin panel or the MCP brands.create tool.

Key Format

API keys are prefixed for easy identification:

PrefixScope
lk_live_Production — real message delivery
lk_test_Test — messages routed to sandbox
lk_dev_Development — local testing, no delivery

Authentication

Include the key in the Authorization header:

curl -X POST https://comms.loop.health/api/events \ -H "Authorization: Bearer lk_live_abc123..." \ -H "Content-Type: application/json" \ -d '{"event": "lead.captured.v1", "payload": {...}}'

Rate Limits

TierRateBurst
Standard100 req/s200
Premium1,000 req/s2,000

Rate limit headers are included in every response:

X-RateLimit-Limit: 100 X-RateLimit-Remaining: 97 X-RateLimit-Reset: 1716134400

Webhook-Based Integration

For products that push events (e.g., Shopify order webhooks, Typeform submissions), configure a webhook endpoint in the comms platform.

Register an Inbound Webhook

{ "tool": "events.declare", "input": { "name": "order.completed.v1", "source": "shopify", "webhookPath": "/webhooks/shopify/order-completed", "transform": { "eventId": "$.id", "occurredAt": "$.created_at", "brandId": "$.note_attributes.brand_id", "email": "$.email" } } }

The transform field maps incoming webhook payloads to the comms event schema using JSONPath expressions.

Supported Webhook Sources

The platform includes built-in transforms for:

  • Shopify (orders, customers, fulfillments)
  • BigCommerce (orders, customers)
  • Typeform (form submissions)
  • Calendly (bookings)
  • Custom (provide your own transform)

Event Schema Validation

All events are validated against their declared schema before processing. Invalid events are rejected with a 422 response.

Validate Locally Before Sending

If you’re building a custom integration, validate payloads before sending:

import { validateEvent } from '@loop/contracts'; const result = validateEvent('lead.captured.v1', { eventId: '550e8400-e29b-41d4-a716-446655440000', occurredAt: '2026-05-19T12:00:00Z', brandId: 'brand-uuid', email: 'user@example.com', source: 'inbound_lead', attribution: {}, personId: null, }); if (!result.success) { console.error(result.error.issues); }

Schema Discovery

Retrieve the current schema for any event type:

GET https://comms.loop.health/api/events/schema/lead.captured.v1

Response:

{ "name": "lead.captured.v1", "fields": { "eventId": { "type": "uuid", "required": true }, "occurredAt": { "type": "datetime", "required": true }, "brandId": { "type": "uuid", "required": true }, "email": { "type": "email", "required": true }, "source": { "type": "enum", "values": ["vsl_form", "quiz_completion", "inbound_lead", "other"], "required": true }, "attribution": { "type": "object", "required": true }, "personId": { "type": "uuid", "required": false } } }

Error Handling

HTTP Status Codes

CodeMeaning
200Event accepted
400Malformed request body
401Invalid or missing API key
422Schema validation failed
429Rate limit exceeded
500Internal server error (retry safe)

Error Response Format

{ "ok": false, "error": { "code": "VALIDATION_ERROR", "message": "payload.email must be a valid email address", "issues": [ { "path": "email", "message": "Invalid email", "code": "invalid_string" } ] } }

Retry Strategy

For 5xx errors and network failures, retry with exponential backoff:

AttemptDelay
11 second
25 seconds
330 seconds
42 minutes
510 minutes

Include an Idempotency-Key header (use the eventId) to prevent duplicate processing on retries.

Next Steps