Start a Loop with the UOCL Webhook API
Use this inbound webhook to start a tokenized Loop experience from your own system. You POST JSON; Indemption / BuzzWorks normalizes the payload against the Loop template, issues a launch token and QR, and returns URLs your team or customer can open. Connected Apps and Lead Feeds then deliver results to the destinations you configure.
Contract version: UOCL Loop Start v1. This guide documents the CURRENT Ride Start inbound webhook used in production, and clearly marks PLANNED generic Loop aliases that are not live yet.
Overview
The UOCL (Universal Offer & Campaign Loop) inbound webhook is the machine entry point for starting a Loop. Your booking system, CRM automation, or internal service posts structured JSON. The platform stores a schema-less field model, creates a high-entropy token, and returns a QR Launch URL for the experience.
Conceptual model
YOUR SYSTEM → POST JSON → UOCL WEBHOOK → NORMALIZE → TEMPLATE (field model / copy / branding) → TOKEN + LAUNCH URL → QR LAUNCH EXPERIENCE → RESPONSE → DESTINATIONS (Connected Apps / feeds)
The template and Loop configuration determine what the participant sees after scan — title, instructions, which fields are locked vs editable, submit labels, success copy, and branding. Your JSON supplies values and optional field definitions; it does not replace the Loop’s configured experience type.
Quick Start
- Obtain an API key for your authorized account (see API Keys).
POSTJSON to the CURRENT Ride Start endpoint withContent-Type: application/jsonandx-api-key.- Include a correlation id — for Ride Start that is
hubspot_deal_id(aliases accepted). - Optionally include
fields[]for the on-screen form model and abookingobject for confirmation email context. - Read
ok,token,ride_url, and optionalqr_png_urlfrom the response. - Open or share
ride_url(or the QR image) to launch the Loop.
Machine-readable examples: curl, JavaScript fetch, Python. JSON Schema: loop-start-v1.schema.json.
Authentication
Send these headers on production calls:
Content-Type: application/json x-api-key: YOUR_API_KEY
Content-Type: application/json— required.x-api-key— send on every production call once a key is issued for your account. Use a server-side secret only. Do not place keys in browser JavaScript, public repos, or apps that ship the secret to end users.
Self-serve API key create / view / revoke in Connected Apps is being added. Until that UI and inbound enforcement fully ship, keys for approved integrations are provisioned by Indemption / BuzzWorks — contact mail@buzzworksai.com. Always send x-api-key when you have one. See API Keys for the intended product experience and current gaps.
Endpoint
CURRENT (supported today) — Ride Start inbound webhook
POST https://flows.mmdirect-n8n.com/webhook/ride-start
This is the proven production path used by Ride / Loop booking starts. It accepts the JSON contract below, normalizes fields, creates a tokenized Ride experience, and returns launch + QR metadata.
PLANNED — generic Loop Start alias
POST …/webhook/loop-start
A generic /webhook/loop-start (and related non-Ride inbound paths) is not live as a public contract. Do not point production systems at invented aliases. When a stable generic path ships, this guide will list it under CURRENT and keep Ride Start documented for Ride templates.
Method: POST only. Body: JSON object.
JSON Payload
UOCL Loop Start v1 is intentionally small and template-driven. Required keys for the CURRENT Ride Start path are listed first.
| Field | Type | Required | Description |
|---|---|---|---|
hubspot_deal_id |
string | Yes (Ride Start) | Correlation id for the booking / deal. Aliases accepted: hubspotDealId, deal_id. |
title |
string | No | Experience title. Default if omitted: Ride Details. |
instructions |
string | No | Helper text shown above the form. |
submitLabel |
string | No | Submit button label. Default: Submit Ride. |
successMessage |
string | No | Message after successful submit. |
fields |
array or object | No | Form field model. Prefer an array of field objects (see Fields). A map of name → value (or name → field object) is also accepted. |
booking |
object | No | Booking / recipient context (for example name, email, phone). Preserved for confirmation email resolution; not rendered as the primary /r/ form unless also present in fields. |
data |
object | No | Optional nested object. May carry fields, title/instructions, or additional context. See Custom Data. |
source |
string | No | Caller label for diagnostics (for example my_crm_booking). |
logoUrl, backgroundUrl, bannerUrl |
string | No | Optional style overrides when supported by the experience. |
Use stable field name keys (snake_case recommended). Labels may change for display; keys should stay stable across retries and CRM mappings. Do not put API secrets, passwords, or security-challenge answers that must stay server-side into field values.
Fields
Each entry in fields[] describes one on-screen control:
| Property | Type | Notes |
|---|---|---|
name | string | Required stable key. |
label | string | Display label; humanized from name if omitted. |
type | string | For example text, email, tel, date, time, select, textarea. Default text. |
value | any | Prefill value. Default empty string. |
editable | boolean | When omitted, treated as editable (true). Set false for locked booking facts. |
options | array | For select fields. |
required | boolean | Optional client/form hint. |
placeholder | string | Optional placeholder text. |
Custom Data
You may include a data object for nested fields or extra context. For CURRENT Ride Start, known UI keys inside data (title, instructions, fields, style URLs) are read during normalize. Prefer top-level fields for the form model when possible.
Arbitrary business context that must appear on the form should be expressed as fields[] entries with stable name keys. Do not invent undocumented top-level keys (for example fabricated loop_id / template_id properties) expecting them to drive routing today — template selection is configured in the Loop / project, not by inventing payload keys.
Ride Example
Complete example matching the production Ride Start booking shape:
{
"hubspot_deal_id": "123456789",
"source": "example_booking_system",
"title": "Ride Confirmation",
"instructions": "Please review the trip and complete the driver fields.",
"submitLabel": "Submit Ride",
"successMessage": "Thank you. The Ride information was submitted.",
"booking": {
"name": "Jane Smith",
"email": "jane@example.com",
"cell_phone": "+15555550100",
"airport": "Airport Terminal A",
"arrival_date": "2026-08-15",
"arrival_time": "14:30",
"flight_number": "AA100"
},
"fields": [
{
"name": "name",
"label": "Name",
"type": "text",
"value": "Jane Smith",
"editable": false
},
{
"name": "email",
"label": "Email",
"type": "email",
"value": "jane@example.com",
"editable": false
},
{
"name": "airport",
"label": "Airport",
"type": "text",
"value": "Airport Terminal A",
"editable": false
},
{
"name": "driver_name",
"label": "Driver Name",
"type": "text",
"value": "",
"editable": true
},
{
"name": "status",
"label": "Ride Status",
"type": "select",
"options": ["Completed", "No Show", "Cancelled"],
"editable": true
}
]
}
Minimal Example
{
"hubspot_deal_id": "123456789"
}
A minimal body is accepted when the correlation id is present. The experience then uses template defaults for title, instructions, and fields. Prefer sending explicit fields so participants see the booking facts you intend.
Response
Successful CURRENT Ride Start response (HTTP 200):
{
"ok": true,
"token": "ABC123XYZ",
"hubspot_deal_id": "123456789",
"ride_url": "https://qr-launch.netlify.app/r/ABC123XYZ",
"qr_svg": "<svg xmlns='http://www.w3.org/2000/svg' …>…</svg>",
"qr_png_url": "https://example-cdn.example/rides/ABC123XYZ/qr.png",
"email": {
"status": "sent",
"recipient": "j***@example.com",
"message_id": "…"
}
}
| Field | Status | Description |
|---|---|---|
ok | CURRENT | true on success. |
token | CURRENT | High-entropy launch token. |
hubspot_deal_id | CURRENT | Echo of the correlation id. |
ride_url | CURRENT | Canonical QR Launch URL for the experience. |
qr_svg | CURRENT | SVG markup for the QR (may be null if generation failed). |
qr_png_url | CURRENT | Public PNG URL when available. |
qr_error | CURRENT | Present when QR generation failed (create may still succeed). |
email | CURRENT | Confirmation email status object. |
launch_url | PLANNED alias | Not returned today. Use ride_url. A generic alias may be added later for non-Ride Loops. |
Errors
Errors observed on the CURRENT Ride Start inbound webhook:
| HTTP | Example body | When |
|---|---|---|
| 400 | {"ok":false,"error":"hubspot_deal_id_required"} |
Missing / blank hubspot_deal_id (and aliases). |
| 502 | {"ok":false,"error":"ride_create_failed"} |
Downstream create failed after validation. |
Additional status codes such as 401 (invalid / missing API key), 404, 409, and 422 may appear as API key enforcement and broader Loop validation expand. Do not assume wallet-preview codes apply to this webhook. Treat non-ok JSON and non-2xx HTTP statuses as failures; retry only when safe for your business process.
Idempotency: Client-supplied idempotency keys are a recommended future enhancement and are not part of the CURRENT public contract. Today each successful Start call issues a new token. Coordinate retries carefully if your system must avoid duplicate launches for the same booking.
Security
- Call the webhook over HTTPS only.
- Keep API keys on server-to-server systems (your backend, secure automation host, or approved middleware). Never embed keys in browser JavaScript, public front ends, or client-distributed apps.
- Do not put secrets, passwords, private tokens, or security-challenge answers into
fieldsordata. - Validate and sanitize values in your system before POST.
- Rate limits may apply. Back off on repeated failures.
- Rotate keys when staff, vendors, or integrations change (once key management is available for your account).
Testing
- Use a non-production correlation id (for example a test deal id).
- POST the minimal or Ride payload with your key.
- Confirm
ok: trueand openride_urlin a browser. - Verify field prefill, editable vs locked fields, and submit behavior for your template.
- Confirm Connected Apps / webhook destinations receive post-submit events when configured.
Example tools: the curl / fetch / Python samples under docs/api/examples/. Replace YOUR_API_KEY — never commit real keys.
API Keys
Desired product experience (target Connected Apps / developer settings):
- Create a named key with optional scopes (for example Loop Start, wallet validate, outcomes).
- Show the secret once at creation time.
- Store only a hash server-side; list keys by name / prefix / created date.
- Revoke or rotate without downtime for other keys.
API key management is being added. Connected Apps currently shows an API Keys placeholder (“No API keys created yet” / Create API Key) that does not yet create, list, reveal, or revoke account-scoped keys. There is no self-serve production key vault UI to document as live. Until that ships, request provisioning from mail@buzzworksai.com for approved integrations.
Implementation TODO / gaps (internal)
- Persist hashed keys with name, scopes, mail-owner / client binding, created/revoked timestamps.
- Wire create / list / revoke UI in Connected Apps (replace placeholder modal).
- Enforce
x-api-keyon inbound Loop Start for issued keys; return clear401bodies. - Document scopes in this guide once they are real.
Output Connections
Starting a Loop is the inbound half of the journey. After a participant submits the experience, results can fan out through Connected Apps and Automation Feeds (email, CRM, webhook destinations, sheets, and more) configured for the Mail Owner / Campaign / Project.
- Connected Apps (signed-in Indemption account) — authorize providers and destination defaults.
- APIs & Integrations — product overview.
- Developer Documentation — wallet and other API preview topics.
- HubSpot / Salesforce — CRM integration stories.
Inbound Start (this guide) and outbound event delivery are complementary. Configure destinations in Connected Apps inside your account; do not expect Start response JSON to replace feed delivery.
Versioning
This payload and response contract is labeled UOCL Loop Start v1. There is no runtime version query parameter or header required today. Additive fields may appear over time; documented CURRENT fields will be preserved where practical. Breaking changes will ship under a new contract version label in this documentation.
JSON Schema (flexible data, required correlation id for Ride Start): docs/api/schemas/loop-start-v1.schema.json.
Support
For API keys, Loop Start onboarding, or partner integrations, contact mail@buzzworksai.com.