FUSE Brand API (External) — v1

Server-to-server API for a brand to build its own admin frontend. Generated from openapi.yaml by scripts/generate-api-reference.mjs on 2026-10-07 — do not edit by hand.

216operations total
216live now
x-api-keyauth header
read-onlydefault key scope
Authentication. Send your clinic-scoped API key in the x-api-key header on every /api/v1 request. Keys are minted from the brand-admin key-management endpoints (/api-keys), which use a brand-admin JWT (Authorization: Bearer … from POST /auth/signin) — the only JWT-authenticated rows below. Keys default to read-only; mutating endpoints require the write scope (403 INSUFFICIENT_SCOPE otherwise). Publishable keys (fuse_pk_…) may call exactly one endpoint: POST /api/v1/checkout/sessions. Every endpoint may return 429 Too Many Requests with a Retry-After header.
Every operation below is available to your brand. There is no enablement step and no 403 ENDPOINT_NOT_ENABLED — that per-clinic gate was removed on 2026-09-18. What still applies: your key's scopes (read by default), the clinic your key belongs to, your plan's entitlements for Affiliates (AFFILIATES_TIER_REQUIRED) and CRM Connect (CRM_TIER_REQUIRED), and rate limits.

Auth & Key Management (5) · Orders (8) · Customers (1) · Programs (24) · Program Templates & Titration (5) · Products & Catalog (17) · Payouts & Refunds (5) · Billing (8) · Organization (13) · Onboarding (4) · Page Builder (9) · Refund Requests (2) · Treatments (8) · Dashboard & Analytics (11) · CRM · Contacts (4) · CRM · Tags (6) · CRM · Sequences (6) · CRM · Templates (6) · CRM · Connection (5) · Affiliate Program (16) · Team & Users (5) · Organization & Clinic (9) · Custom Website (8) · Support & Conversations (8) · Forms & Global Products (3) · Intake Requests (2) · Misc / Uploads (13) · Checkout Sessions (2) · Webhooks (3)

Auth & Key Management (5)

Key management uses a brand-admin JWT (from /auth/signin), NOT an API key. Everything else uses x-api-key.

MethodPathSummary
POST /auth/signin Obtain a brand-admin JWT (to manage keys).
no auth
Schemas
Request body (application/json)
{
  "email": "you@brand.com",
  "password": "..."
}
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api-keys List this clinic's keys (metadata only — no secret).
JWT
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api-keys Issue a key. Default scope read-only + 1yr expiry; pass scopes:["write"] for full. Raw key returned once.
JWT
Schemas
Request body (application/json)
{
  "name": "My integration",
  "kind": "secret",
  "scopes": [
    "read"
  ]
}
Response 201
{
  "success": true,
  "message": "string",
  "data": null
}
DELETE /api-keys/{id} Revoke a key (immediate).
JWT
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/me Identify the key: clinic, name, scopes. Smoke-test connectivity.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}

Orders (8)

MethodPathSummary
GET /api/v1/orders Paginated orders. Each row includes the per-order feeBreakdown.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/orders/stats Aggregate order + earnings stats.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/orders/summary Aggregate order breakdowns — by status, program, shipping state, and refunds (no per-order rows).
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": {
    "window": {
      "startDate": "string",
      "endDate": "string"
    },
    "totalOrders": 0,
    "byStatus": [
      {
        "status": "string",
        "orders": 0
      }
    ],
    "byProgram": [
      {
        "programId": "string",
        "programName": "string",
        "orders": 0,
        "paidSales": 0
      }
    ],
    "byState": [
      {
        "state": "string",
        "orders": 0
      }
    ],
    "otherStates": {
      "states": 0,
      "orders": 0
    },
    "refunds": {
      "byStatus": [
        {
          "status": "string",
          "requests": 0
        }
      ],
      "approvedAmount": 0
    }
  }
}
GET /api/v1/orders/{id} Order detail with the full fee waterfall (matches the brand-admin UI).
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "orderNumber": "string",
    "status": "string",
    "totalAmount": 0,
    "subtotalAmount": 0,
    "discountAmount": 0,
    "taxAmount": 0,
    "shippingAmount": 0,
    "brandAmount": 0,
    "billingInterval": "string",
    "createdAt": "2026-01-01T00:00:00Z",
    "shippedAt": "2026-01-01T00:00:00Z",
    "deliveredAt": "2026-01-01T00:00:00Z",
    "fulfillmentType": "string",
    "approvedByDoctor": true,
    "feeBreakdown": {},
    "user": {
      "id": "00000000-0000-0000-0000-000000000000",
      "firstName": "string",
      "lastName": "string",
      "email": "string",
      "phoneNumber": "string"
    },
    "orderItems": [
      {
        "id": "00000000-0000-0000-0000-000000000000",
        "quantity": 0,
        "unitPrice": 0,
        "totalPrice": 0,
        "product": {
          "id": "00000000-0000-0000-0000-000000000000",
          "name": "string"
        }
      }
    ],
    "payment": {
      "status": "string",
      "paymentMethod": "string"
    },
    "shippingAddress": {
      "address": "string",
      "city": "string",
      "state": "string",
      "zipCode": "string",
      "country": "string"
    },
    "shippingOrders": [
      {
        "id": "00000000-0000-0000-0000-000000000000",
        "status": "string",
        "trackingNumber": "string",
        "trackingUrl": "string"
      }
    ]
  }
}
GET /api/v1/orders/{id}/events Chronological status/event timeline for one order.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": {
    "events": [
      {
        "id": "string",
        "eventType": "string",
        "actorType": "string",
        "createdAt": "2026-01-01T00:00:00Z",
        "metadata": {}
      }
    ],
    "hasPrescriptionPdf": true
  }
}
GET /api/v1/orders/{id}/lab-status Lab lifecycle state and lab-kit tracking for one order.
key
Schemas
Response 200
{
  "success": true,
  "data": {
    "orderId": "00000000-0000-0000-0000-000000000000",
    "isLabGated": true,
    "orderStatus": "string",
    "stage": "requisition_created",
    "timeline": [
      {
        "stage": "requisition_created",
        "reached": true,
        "occurredAt": "2026-01-01T00:00:00Z"
      }
    ],
    "kitShipmentToPatient": {
      "carrier": "string",
      "trackingNumber": "string",
      "deliveredAt": "2026-01-01T00:00:00Z"
    },
    "kitShipmentToLab": {
      "carrier": "string",
      "trackingNumber": "string",
      "receivedAt": "2026-01-01T00:00:00Z"
    },
    "resultsAvailableAt": "2026-01-01T00:00:00Z"
  }
}
GET /api/v1/orders/{id}/visit-status Telehealth visit status and appointment time for one order.
key
Schemas
Response 200
{
  "success": true,
  "data": {
    "orderId": "00000000-0000-0000-0000-000000000000",
    "visitStatus": "not_booked",
    "bookingRequired": true,
    "scheduledAt": "2026-01-01T00:00:00Z",
    "lastSyncedAt": "2026-01-01T00:00:00Z"
  }
}
GET /api/v1/orders/needs-attention List orders needing attention (failed payment / dunning queue).
key
Schemas
Response 200
{
  "success": true,
  "data": {
    "count": 0,
    "items": [
      {
        "orderId": "00000000-0000-0000-0000-000000000000",
        "orderNumber": "string",
        "patientName": null,
        "programName": null,
        "paymentFailedAt": null,
        "lastPaymentError": null,
        "enrichment": {}
      }
    ]
  }
}

Customers (1)

MethodPathSummary
GET /api/v1/customers Patient directory with order count, revenue, tags.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": [
    {
      "id": "00000000-0000-0000-0000-000000000000",
      "firstName": "string",
      "lastName": "string",
      "email": "string",
      "phoneNumber": "string",
      "createdAt": "2026-01-01T00:00:00Z",
      "orderCount": 0,
      "totalRevenue": 0,
      "categories": [
        "string"
      ],
      "hasActiveSubscription": true
    }
  ]
}

Programs (24)

Modern KAN-414 program surface. Every /:id path is scoped to the key's clinic (404 on anything it does not own).

MethodPathSummary
POST /api/v1/programs/copilot/draft Draft a program with FUSE Copilot (AI).
key · write
Schemas
Request body (application/json)
{}
Response 200
{}
GET /api/v1/programs List the clinic's programs.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": [
    {
      "id": "00000000-0000-0000-0000-000000000000",
      "name": "string",
      "description": "string",
      "isActive": true,
      "isFeatured": true,
      "nonMedicalServiceFee": 0,
      "heroImageUrl": "string",
      "customSlug": "string",
      "accentColor": "string",
      "sellableProductCount": 0,
      "unpricedProductCount": 0,
      "programGlobalProducts": [
        {
          "id": "00000000-0000-0000-0000-000000000000",
          "displayOrder": 0,
          "isPatientVisible": true,
          "globalProduct": {}
        }
      ]
    }
  ]
}
POST /api/v1/programs Create a program.
key · write
Schemas
Request body (application/json)
{
  "name": "New program"
}
Response 201
{
  "success": true,
  "message": "string",
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "name": "string",
    "description": "string",
    "isActive": true,
    "isFeatured": true,
    "nonMedicalServiceFee": 0,
    "heroImageUrl": "string",
    "customSlug": "string",
    "accentColor": "string",
    "sellableProductCount": 0,
    "unpricedProductCount": 0,
    "programGlobalProducts": [
      {
        "id": "00000000-0000-0000-0000-000000000000",
        "displayOrder": 0,
        "isPatientVisible": true,
        "globalProduct": {}
      }
    ]
  }
}
GET /api/v1/programs/overview Dashboard stats + attention items.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": {
    "stats": {
      "livePrograms": 0,
      "draftPrograms": 0,
      "pausedPrograms": 0,
      "totalPatients": 0,
      "estBilledMonthlyCents": 0,
      "estNetMonthlyCents": 0
    },
    "perProgram": [
      {
        "programId": "00000000-0000-0000-0000-000000000000",
        "patients": 0,
        "estBilledMonthlyCents": 0,
        "estNetMonthlyCents": 0
      }
    ],
    "attention": [
      {
        "type": "string",
        "programId": "00000000-0000-0000-0000-000000000000",
        "programName": "string",
        "headline": "string",
        "detail": "string",
        "estValueCents": 0,
        "action": "string"
      }
    ]
  }
}
GET /api/v1/programs/copilot/suggestions AI copilot suggestions for improving the clinic's programs.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/programs/{id} Program detail.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "name": "string",
    "description": "string",
    "isActive": true,
    "isFeatured": true,
    "nonMedicalServiceFee": 0,
    "heroImageUrl": "string",
    "customSlug": "string",
    "accentColor": "string",
    "sellableProductCount": 0,
    "unpricedProductCount": 0,
    "programGlobalProducts": [
      {
        "id": "00000000-0000-0000-0000-000000000000",
        "displayOrder": 0,
        "isPatientVisible": true,
        "globalProduct": {}
      }
    ]
  }
}
PUT /api/v1/programs/{id} Update a program.
key · write
Schemas
Request body (application/json)
{
  "name": "Renamed"
}
Response 200
{
  "success": true,
  "message": "string",
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "name": "string",
    "description": "string",
    "isActive": true,
    "isFeatured": true,
    "nonMedicalServiceFee": 0,
    "heroImageUrl": "string",
    "customSlug": "string",
    "accentColor": "string",
    "sellableProductCount": 0,
    "unpricedProductCount": 0,
    "programGlobalProducts": [
      {
        "id": "00000000-0000-0000-0000-000000000000",
        "displayOrder": 0,
        "isPatientVisible": true,
        "globalProduct": {}
      }
    ]
  }
}
DELETE /api/v1/programs/{id} Delete one of the clinic's programs.
key · write
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "name": "string",
    "description": "string",
    "isActive": true,
    "isFeatured": true,
    "nonMedicalServiceFee": 0,
    "heroImageUrl": "string",
    "customSlug": "string",
    "accentColor": "string",
    "sellableProductCount": 0,
    "unpricedProductCount": 0,
    "programGlobalProducts": [
      {
        "id": "00000000-0000-0000-0000-000000000000",
        "displayOrder": 0,
        "isPatientVisible": true,
        "globalProduct": {}
      }
    ]
  }
}
GET /api/v1/programs/{id}/global-products Fee-adjusted product pool for a program.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/programs/{id}/duplicate Clone a program (deep copy of its product config).
key · write
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/programs/{id}/products Effective per-product patient pricing for a program.
key
Schemas
Response 200
{
  "success": true,
  "data": {
    "programId": "00000000-0000-0000-0000-000000000000",
    "nonMedicalServiceFee": 0,
    "nonMedicalServiceFeeIncludedInDisplayPrice": true,
    "products": [
      {
        "globalProductId": "00000000-0000-0000-0000-000000000000",
        "name": "string",
        "displayOrder": 0,
        "linkSource": "program",
        "isPatientVisible": true,
        "displayPrice": 0,
        "effectiveProgramFee": 0,
        "feeSource": "clinic_override",
        "clinicProgramFee": 0,
        "programBaseFee": 0,
        "placeholderPrice": 0,
        "pharmacyBasePrice": 0,
        "facilitationFee": 0,
        "packDurationMonths": 0,
        "vialsPerPack": 0,
        "supplyDays": 0,
        "allowPrepay": true,
        "isSellable": true,
        "isCostBacked": true,
        "hasResolvedPrice": true
      }
    ]
  }
}
PUT /api/v1/programs/{id}/products Replace the program's product set.
key · write
Schemas
Request body (application/json)
{
  "products": [
    {
      "productId": "<global-product-uuid>"
    }
  ]
}
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/programs/{id}/upload-image Upload a program cover image (multipart, field `image`).
key · write
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/programs/sync-all Re-sync ALL of the clinic's template-derived programs against their source templates.
key · write
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "name": "string",
    "description": "string",
    "isActive": true,
    "isFeatured": true,
    "nonMedicalServiceFee": 0,
    "heroImageUrl": "string",
    "customSlug": "string",
    "accentColor": "string",
    "sellableProductCount": 0,
    "unpricedProductCount": 0,
    "programGlobalProducts": [
      {
        "id": "00000000-0000-0000-0000-000000000000",
        "displayOrder": 0,
        "isPatientVisible": true,
        "globalProduct": {}
      }
    ]
  }
}
POST /api/v1/programs/{id}/sync Re-sync one derived program against its source template.
key · write
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/programs/{id}/sync-status Whether a derived program is behind its source template.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/programs/{id}/products/activation-status Per-product activation state within a program.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/programs/{id}/products/visibility-status Per-product patient-visibility state within a program.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
PATCH /api/v1/programs/{id}/products/{productId}/activate Activate/deactivate a product in the program.
key · write
Schemas
Request body (application/json)
{
  "isActive": true
}
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
PATCH /api/v1/programs/{id}/products/{productId}/visibility Toggle a product's patient visibility.
key · write
Schemas
Request body (application/json)
{
  "isPatientVisible": true
}
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/programs/{id}/titration-protocols Titration protocols attached to a program.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/programs/{id}/titration-protocols Attach a titration protocol to a program.
key · write
Schemas
Request body (application/json)
{
  "titrationProtocolId": "<protocol-uuid>",
  "flatFee": 0,
  "allowedBillingMonths": [
    1,
    3
  ],
  "position": 0
}
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
PUT /api/v1/programs/{id}/titration-protocols/{attachmentId} Update a program's titration-protocol attachment.
key · write
Schemas
Request body (application/json)
{
  "flatFee": 25,
  "allowedBillingMonths": [
    1,
    3,
    6
  ],
  "position": 1
}
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
DELETE /api/v1/programs/{id}/titration-protocols/{attachmentId} Detach a titration protocol from a program.
key · write
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}

Program Templates & Titration (5)

Shared FUSE catalogues (global by design — same posture as GET /config/fees). No clinic filter, no PHI.

MethodPathSummary
GET /api/v1/titration-schedule/fulfillment-held List titration schedules held for fulfillment (awaiting revisit).
key
Schemas
Response 200
{
  "success": true,
  "data": [
    {
      "id": "string",
      "currentLevel": 0,
      "maxLevel": 0,
      "status": "string",
      "nextRevisitDueAt": "2026-01-01T00:00:00Z",
      "lastRevisitAt": "2026-01-01T00:00:00Z",
      "heldSince": "2026-01-01T00:00:00Z",
      "daysOverdue": 0,
      "order": {
        "id": "string",
        "orderNumber": "string",
        "status": "string"
      },
      "user": {
        "id": "string",
        "firstName": "string",
        "lastName": "string"
      },
      "program": {
        "id": "string",
        "name": "string"
      },
      "titrationProtocol": {
        "id": "string",
        "name": "string",
        "maxLevel": 0
      }
    }
  ],
  "pagination": {
    "page": 0,
    "limit": 0,
    "total": 0,
    "totalPages": 0
  }
}
GET /api/v1/program-templates List the shared FUSE program templates.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/program-templates/{id} One program template.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/program-templates/{id}/global-products Global products carried by a program template.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/titration-protocols List the shared FUSE titration protocols.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}

Products & Catalog (17)

MethodPathSummary
POST /api/v1/products/{id}/upload-image Upload or remove a product's image.
key · write
Schemas
Request body (application/json)
{
  "removeImage": true
}
Response 200
{}
GET /api/v1/public/products/{productId}/pharmacy-coverages List a product's pharmacy coverages (clinic-scoped).
key
Schemas
Response 200
{
  "success": true,
  "data": [
    {}
  ]
}
GET /api/v1/catalog Storefront catalog (light view) — same source as the brand portal.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": [
    {
      "id": "00000000-0000-0000-0000-000000000000",
      "name": "string",
      "slug": "string",
      "categories": [
        "string"
      ],
      "imageUrl": "string",
      "description": "string",
      "requiresCooler": true,
      "pharmacyPrice": 0,
      "facilitationFee": 0,
      "price": 0,
      "pharmacyName": "string",
      "pharmacyRole": "primary"
    }
  ]
}
GET /api/v1/products Product management view (clinic's own + shared platform products).
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": [
    {
      "id": "00000000-0000-0000-0000-000000000000",
      "name": "string",
      "slug": "string",
      "description": "string",
      "category": "string",
      "categories": [
        "string"
      ],
      "isActive": true,
      "pharmacyProvider": "string",
      "pharmacyPrice": 0,
      "pharmacyProductId": "string",
      "brandName": "string",
      "imageUrl": "string",
      "pharmacyCoverages": [
        {
          "id": "string",
          "customName": "string",
          "pharmacy": {
            "id": "string",
            "name": "string",
            "slug": "string"
          }
        }
      ]
    }
  ]
}
POST /api/v1/products Create a custom product for the key clinic's brand.
key · write
Schemas
Request body (application/json)
{
  "name": "string",
  "description": "string",
  "pharmacyPrice": 0,
  "pharmacyProductId": "string",
  "isActive": true
}
Response 201
{}
GET /api/v1/products/{id} One product (accepts a Product id or a GlobalProduct id).
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "name": "string",
    "slug": "string",
    "description": "string",
    "category": "string",
    "categories": [
      "string"
    ],
    "isActive": true,
    "pharmacyProvider": "string",
    "pharmacyPrice": 0,
    "pharmacyProductId": "string",
    "brandName": "string",
    "imageUrl": "string",
    "pharmacyCoverages": [
      {
        "id": "string",
        "customName": "string",
        "pharmacy": {
          "id": "string",
          "name": "string",
          "slug": "string"
        }
      }
    ]
  }
}
PUT /api/v1/products/{id} Update one of the clinic's OWN products.
key · write
Schemas
Request body (application/json)
{
  "description": "Updated copy"
}
Response 200
{
  "success": true,
  "message": "string",
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "name": "string",
    "slug": "string",
    "description": "string",
    "category": "string",
    "categories": [
      "string"
    ],
    "isActive": true,
    "pharmacyProvider": "string",
    "pharmacyPrice": 0,
    "pharmacyProductId": "string",
    "brandName": "string",
    "imageUrl": "string",
    "pharmacyCoverages": [
      {
        "id": "string",
        "customName": "string",
        "pharmacy": {
          "id": "string",
          "name": "string",
          "slug": "string"
        }
      }
    ]
  }
}
GET /api/v1/brand/product-catalog Alias of /catalog — the brand's fee-adjusted product catalog.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": [
    {
      "id": "00000000-0000-0000-0000-000000000000",
      "name": "string",
      "slug": "string",
      "categories": [
        "string"
      ],
      "imageUrl": "string",
      "description": "string",
      "requiresCooler": true,
      "pharmacyPrice": 0,
      "facilitationFee": 0,
      "price": 0,
      "pharmacyName": "string",
      "pharmacyRole": "primary"
    }
  ]
}
GET /api/v1/products-management/{id} Alias of GET /products/:id — read one of the clinic's own products.
key
Schemas
Response 200
{
  "success": true,
  "data": {}
}
PUT /api/v1/products-management/{id} Alias of PUT /products/:id — update one of the clinic's own products.
key · write
Schemas
Request body (application/json)
{
  "description": "Updated copy"
}
Response 200
{
  "success": true,
  "message": "string",
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "name": "string",
    "slug": "string",
    "description": "string",
    "category": "string",
    "categories": [
      "string"
    ],
    "isActive": true,
    "pharmacyProvider": "string",
    "pharmacyPrice": 0,
    "pharmacyProductId": "string",
    "brandName": "string",
    "imageUrl": "string",
    "pharmacyCoverages": [
      {
        "id": "string",
        "customName": "string",
        "pharmacy": {
          "id": "string",
          "name": "string",
          "slug": "string"
        }
      }
    ]
  }
}
GET /api/v1/tenant-products The clinic's own tenant-product offerings + facilitation fees.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/global-products/discontinued-in-use Discontinued global SKUs still referenced by THIS clinic's programs.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/tenant-products/update Set the price of one tenant product (creates a real Stripe price).
key · write
Schemas
Request body (application/json)
{
  "tenantProductId": "<tenant-product-uuid>",
  "price": 99
}
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/tenant-products/update-selection Update the clinic's selected tenant products (enforces plan limits + billing caps).
key · write
Schemas
Request body (application/json)
{
  "products": [
    {
      "productId": "<product-uuid>",
      "questionnaireId": "<questionnaire-uuid>"
    }
  ]
}
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/global-products/{id}/upload-image Upload a brand-scoped image override for a global product (multipart, field `image`; never mutates the shared product).
key · write
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/global-form-structures Shared FUSE global form-builder structure catalog (no clinic data / no PHI).
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/products-management List the brand's products (product-management view).
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": {
    "products": [
      {}
    ],
    "pagination": {
      "page": 0,
      "limit": 0,
      "total": 0,
      "totalPages": 0
    }
  }
}

Payouts & Refunds (5)

MethodPathSummary
GET /api/v1/payouts Order-level payout history.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": [
    {
      "id": "00000000-0000-0000-0000-000000000000",
      "type": "string",
      "orderId": "00000000-0000-0000-0000-000000000000",
      "orderNumber": "string",
      "amount": 0,
      "totalAmount": 0,
      "date": "2026-01-01T00:00:00Z",
      "status": "string",
      "stripeTransferId": "string",
      "customer": {
        "name": "string",
        "email": "string"
      }
    }
  ]
}
GET /api/v1/payouts/balance Balance, reserve, held, Stripe — the portal's exact numbers.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": {
    "balance": {
      "totalReceived": 0,
      "totalWithdrawn": 0,
      "currentBalance": 0,
      "lastUpdated": "2026-01-01T00:00:00Z"
    },
    "stripeBalance": {
      "available": 0,
      "pending": 0
    },
    "withdrawable": 0,
    "reserve": {
      "totalHeld": 0,
      "totalReleased": 0,
      "totalForfeited": 0,
      "heldCount": 0
    },
    "heldBalance": {
      "heldOwed": 0,
      "hasHeldBalance": true,
      "isConnected": true
    },
    "recentActivity": [
      {}
    ]
  }
}
GET /api/v1/payouts/disputes Dispute summary + history.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/payouts/withdraw Withdraw available balance to the connected Stripe account.
key · write
Schemas
Request body (application/json)
{
  "amount": 100
}
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/refunds Full refund on one of the clinic's own orders (30-day + balance guard).
key · write
Schemas
Request body (application/json)
{
  "orderId": "<order-uuid>",
  "reason": "customer request"
}
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}

Billing (8)

MethodPathSummary
GET /api/v1/stripe/connect/status Stripe Connect account status.
key
Schemas
Response 200
{}
GET /api/v1/billing/validate-coupon Validate a subscription coupon code.
key
Schemas
Response 200
{
  "success": true,
  "data": {}
}
GET /api/v1/billing/plans List active brand subscription plans.
key
Schemas
Response 200
{
  "success": true,
  "plans": [
    {}
  ]
}
GET /api/v1/billing/current Current subscription (stub, always null).
key
Schemas
Response 200
{
  "success": true,
  "subscription": {}
}
GET /api/v1/billing/basic-info Basic subscription info for the key's clinic.
key
Schemas
Response 200
{
  "success": true,
  "data": {}
}
POST /api/v1/billing/preview-upgrade Preview proration for a plan change.
key · write
Schemas
Request body (application/json)
{
  "newPlanId": "string"
}
Response 200
{}
POST /api/v1/billing/cancel Cancel the clinic's active subscription.
key · write
Schemas
Response 200
{}
POST /api/v1/billing/change Change the clinic's subscription plan.
key · write
Schemas
Request body (application/json)
{
  "newPlanId": "string"
}
Response 200
{}

Organization (13)

MethodPathSummary
GET /api/v1/organization/sms/twilio Get the clinic's Twilio SMS config.
key
Schemas
Response 200
{}
PUT /api/v1/organization/sms/twilio Set the clinic's Twilio SMS config.
key · write
Schemas
Request body (application/json)
{
  "accountSid": "string",
  "authToken": "string",
  "phoneNumber": "string"
}
Response 200
{}
DELETE /api/v1/organization/sms/twilio Remove the clinic's Twilio SMS config.
key · write
Schemas
Response 200
{}
GET /api/v1/organization/sms/status SMS provisioning status (AWS Pinpoint).
key
Schemas
Response 200
{}
POST /api/v1/organization/sms/activate Provision a toll-free SMS number (AWS Pinpoint).
key · write
Schemas
Response 200
{}
DELETE /api/v1/organization/sms/release Release the clinic's toll-free SMS number.
key · write
Schemas
Response 200
{}
POST /api/v1/clinic/custom-domain/start Begin custom-domain setup (ACM cert request).
key · write
Schemas
Request body (application/json)
{
  "domain": "string"
}
Response 200
{}
POST /api/v1/clinic/custom-domain/verify Verify custom-domain DNS/ACM validation.
key · write
Schemas
Response 200
{}
POST /api/v1/clinic/custom-domain/finalize Finalize custom-domain (attach to ALB).
key · write
Schemas
Response 200
{}
POST /api/v1/clinic/custom-domain/remove Remove the clinic's custom domain.
key · write
Schemas
Response 200
{}
PUT /api/v1/organization/update Update organization/clinic profile.
key · write
Schemas
Request body (application/json)
{}
Response 200
{}
PUT /api/v1/clinic/{id} Update the key's clinic (clinic-scoped).
key · write
Schemas
Request body (application/json)
{}
Response 200
{}
GET /api/v1/clinic/check-slug/{slug} Check clinic-slug availability.
key
Schemas
Response 200
{
  "success": true,
  "available": true
}

Onboarding (4)

MethodPathSummary
GET /api/v1/onboarding/status Onboarding status for the key's clinic.
key
Schemas
Response 200
{
  "success": true,
  "data": {}
}
POST /api/v1/onboarding/request-name-change One-time brand-owner name change.
key · write
Schemas
Request body (application/json)
{
  "firstName": "string",
  "lastName": "string"
}
Response 200
{}
POST /api/v1/onboarding/confirm-signature-declaration Confirm the electronic-signature declaration.
key · write
Schemas
Request body (application/json)
{
  "typedName": "string"
}
Response 200
{}
POST /api/v1/onboarding/save-business-details Save brand business details.
key · write
Schemas
Request body (application/json)
{
  "ein": "string",
  "stateOfRegistration": "string",
  "address": "string",
  "city": "string",
  "state": "string",
  "zipCode": "string",
  "phoneNumber": "string",
  "businessType": "string",
  "companyName": "string"
}
Response 200
{}

Page Builder (9)

MethodPathSummary
POST /api/v1/page-builder/upload-image Upload a page-builder image.
key · write
Schemas
Response 200
{}
GET /api/v1/page-builder/pages List the key clinic's pages.
key
Schemas
Response 200
{
  "success": true,
  "data": [
    {}
  ]
}
POST /api/v1/page-builder/pages Create a new draft page.
key · write
Schemas
Request body (application/json)
{
  "slug": "string",
  "pageType": "string",
  "isHomepage": true,
  "draftContent": {},
  "seoTitle": "string",
  "seoDescription": "string"
}
Response 201
{}
GET /api/v1/page-builder/pages/{id} Fetch one page (clinic-scoped).
key
Schemas
Response 200
{}
PUT /api/v1/page-builder/pages/{id} Save page draft (autosave).
key · write
Schemas
Request body (application/json)
{
  "slug": "string",
  "draftContent": {},
  "isHomepage": true,
  "seoTitle": "string",
  "seoDescription": "string",
  "seoOgImage": "string",
  "seoCanonical": "string"
}
Response 200
{}
DELETE /api/v1/page-builder/pages/{id} Soft-delete a page.
key · write
Schemas
Response 200
{}
POST /api/v1/page-builder/pages/{id}/publish Publish a page (promote draft to published).
key · write
Schemas
Response 200
{}
GET /api/v1/page-builder/navigation Get the clinic's header/footer menus.
key
Schemas
Response 200
{}
PUT /api/v1/page-builder/navigation Upsert the clinic's navigation menus.
key · write
Schemas
Request body (application/json)
{
  "headerMenu": [
    {}
  ],
  "footerMenu": [
    {}
  ]
}
Response 200
{}

Refund Requests (2)

Incoming patient-initiated refund-request triage. PENDING — approve moves real money; gated behind per-clinic enablement (ask your FUSE contact).

MethodPathSummary
GET /api/v1/refund-requests List incoming patient refund requests for the clinic.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/refund-requests/{id}/{action} Approve or deny a refund request (:action = approve|deny). Approve issues the refund.
key · write
Schemas
Request body (application/json)
{
  "reviewNotes": "Approved per policy"
}
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}

Treatments (8)

Legacy treatment surface (programs are the modern surface). Writes are pending a product decision.

MethodPathSummary
GET /api/v1/treatments Clinic treatments.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": [
    {
      "id": "00000000-0000-0000-0000-000000000000",
      "name": "string",
      "slug": "string",
      "selected": true,
      "brandColor": "string",
      "brandLogo": "string",
      "clinicSlug": "string",
      "productsPrice": 0
    }
  ]
}
POST /api/v1/treatments Create a treatment.
key · write
Schemas
Request body (application/json)
{
  "name": "New treatment",
  "description": "..."
}
Response 201
{
  "success": true,
  "message": "string",
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "name": "string",
    "slug": "string",
    "selected": true,
    "brandColor": "string",
    "brandLogo": "string",
    "clinicSlug": "string",
    "productsPrice": 0
  }
}
GET /api/v1/treatments/{id} One treatment (clinic-scoped by id + clinicId).
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "name": "string",
    "slug": "string",
    "selected": true,
    "brandColor": "string",
    "brandLogo": "string",
    "clinicSlug": "string",
    "productsPrice": 0
  }
}
PUT /api/v1/treatments/{id} Update one of the clinic's own treatments.
key · write
Schemas
Request body (application/json)
{
  "name": "Renamed treatment"
}
Response 200
{
  "success": true,
  "message": "string",
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "name": "string",
    "slug": "string",
    "selected": true,
    "brandColor": "string",
    "brandLogo": "string",
    "clinicSlug": "string",
    "productsPrice": 0
  }
}
GET /api/v1/brand-treatments Global treatments joined with this brand's selections.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": [
    {
      "id": "00000000-0000-0000-0000-000000000000",
      "name": "string",
      "treatmentLogo": "string",
      "active": true,
      "selected": true,
      "brandLogo": "string",
      "brandColor": "string",
      "clinicSlug": "string"
    }
  ]
}
POST /api/v1/brand-treatments Select a global treatment for the brand.
key · write
Schemas
Request body (application/json)
{
  "treatmentId": "<treatment-uuid>"
}
Response 201
{
  "success": true,
  "message": "string",
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "name": "string",
    "treatmentLogo": "string",
    "active": true,
    "selected": true,
    "brandLogo": "string",
    "brandColor": "string",
    "clinicSlug": "string"
  }
}
DELETE /api/v1/brand-treatments Deselect a global treatment for the brand.
key · write
Schemas
Request body (application/json)
{
  "treatmentId": "<treatment-uuid>"
}
Response 200
{
  "success": true,
  "message": "string",
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "name": "string",
    "treatmentLogo": "string",
    "active": true,
    "selected": true,
    "brandLogo": "string",
    "brandColor": "string",
    "clinicSlug": "string"
  }
}
POST /api/v1/treatment/{id}/upload-logo Upload/remove a treatment logo (multipart, field `logo`; send removeLogo=true to clear).
key · write
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}

Dashboard & Analytics (11)

Clinic-level aggregates only (recent-activity is HIPAA-scrubbed). Reads take clinicId from the key, never the query.

MethodPathSummary
GET /api/v1/dashboard/overview Top-line dashboard summary.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/dashboard/metrics Key metric tiles (orders, revenue, patients).
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/dashboard/earnings-report Earnings breakdown report.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/dashboard/recent-activity Recent clinic activity feed (PHI-scrubbed).
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/dashboard/revenue-chart Time-series revenue chart data.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/dashboard/projected-revenue Projected revenue from active subscriptions.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/analytics/forms The clinic's own intake-form metrics (no PHI).
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/likes/admin/analytics/{tenantProductId} Like/engagement analytics for one of the clinic's tenant products.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/likes/admin/counts Bulk like counts for a list of tenant products (POST only because ids travel in the body; mutates nothing).
key · write
Schemas
Request body (application/json)
{
  "tenantProductIds": [
    "<tenant-product-uuid>"
  ]
}
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/analytics/forms/{formId}/sessions Per-form intake funnel sessions.
key
Schemas
Response 200
{
  "success": true,
  "data": {}
}
GET /api/v1/analytics/programs/{questionnaireId}/sessions Per-program intake funnel sessions.
key
Schemas
Response 200
{
  "success": true,
  "data": {}
}

CRM · Contacts (4)

MethodPathSummary
GET /api/v1/contacts List contacts (patients).
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": [
    {
      "id": "00000000-0000-0000-0000-000000000000",
      "firstName": "string",
      "lastName": "string",
      "email": "string",
      "phoneNumber": "string",
      "emailOptedOut": true,
      "smsOptedOut": true,
      "optOutDate": "2026-01-01T00:00:00Z",
      "createdAt": "2026-01-01T00:00:00Z",
      "lastLoginAt": "2026-01-01T00:00:00Z",
      "lastContactDate": "2026-01-01T00:00:00Z",
      "tags": [
        {
          "id": "00000000-0000-0000-0000-000000000000",
          "name": "string",
          "description": "string",
          "category": "string",
          "color": "string",
          "clinicId": "00000000-0000-0000-0000-000000000000",
          "isActive": true,
          "createdAt": "2026-01-01T00:00:00Z",
          "updatedAt": "2026-01-01T00:00:00Z"
        }
      ]
    }
  ]
}
POST /api/v1/contacts Create a contact (provisions a patient + welcome email).
key · write
Schemas
Request body (application/json)
{
  "firstName": "Jane",
  "lastName": "Doe",
  "email": "jane@example.com"
}
Response 201
{
  "success": true,
  "message": "string",
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "firstName": "string",
    "lastName": "string",
    "email": "string",
    "phoneNumber": "string",
    "emailOptedOut": true,
    "smsOptedOut": true,
    "optOutDate": "2026-01-01T00:00:00Z",
    "createdAt": "2026-01-01T00:00:00Z",
    "lastLoginAt": "2026-01-01T00:00:00Z",
    "lastContactDate": "2026-01-01T00:00:00Z",
    "tags": [
      {
        "id": "00000000-0000-0000-0000-000000000000",
        "name": "string",
        "description": "string",
        "category": "string",
        "color": "string",
        "clinicId": "00000000-0000-0000-0000-000000000000",
        "isActive": true,
        "createdAt": "2026-01-01T00:00:00Z",
        "updatedAt": "2026-01-01T00:00:00Z"
      }
    ]
  }
}
PUT /api/v1/contacts/{id} Update a contact.
key · write
Schemas
Request body (application/json)
{
  "firstName": "Jane"
}
Response 200
{
  "success": true,
  "message": "string",
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "firstName": "string",
    "lastName": "string",
    "email": "string",
    "phoneNumber": "string",
    "emailOptedOut": true,
    "smsOptedOut": true,
    "optOutDate": "2026-01-01T00:00:00Z",
    "createdAt": "2026-01-01T00:00:00Z",
    "lastLoginAt": "2026-01-01T00:00:00Z",
    "lastContactDate": "2026-01-01T00:00:00Z",
    "tags": [
      {
        "id": "00000000-0000-0000-0000-000000000000",
        "name": "string",
        "description": "string",
        "category": "string",
        "color": "string",
        "clinicId": "00000000-0000-0000-0000-000000000000",
        "isActive": true,
        "createdAt": "2026-01-01T00:00:00Z",
        "updatedAt": "2026-01-01T00:00:00Z"
      }
    ]
  }
}
POST /api/v1/contacts/import Bulk CSV import (multipart, field `csv`, 5 MB). Headers: firstname,lastname,email[,phonenumber]. Patient emails are redacted from error rows.
key · write
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "firstName": "string",
    "lastName": "string",
    "email": "string",
    "phoneNumber": "string",
    "emailOptedOut": true,
    "smsOptedOut": true,
    "optOutDate": "2026-01-01T00:00:00Z",
    "createdAt": "2026-01-01T00:00:00Z",
    "lastLoginAt": "2026-01-01T00:00:00Z",
    "lastContactDate": "2026-01-01T00:00:00Z",
    "tags": [
      {
        "id": "00000000-0000-0000-0000-000000000000",
        "name": "string",
        "description": "string",
        "category": "string",
        "color": "string",
        "clinicId": "00000000-0000-0000-0000-000000000000",
        "isActive": true,
        "createdAt": "2026-01-01T00:00:00Z",
        "updatedAt": "2026-01-01T00:00:00Z"
      }
    ]
  }
}

CRM · Tags (6)

MethodPathSummary
GET /api/v1/tags List tags (category/isActive filters).
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": [
    {
      "id": "00000000-0000-0000-0000-000000000000",
      "name": "string",
      "description": "string",
      "category": "string",
      "color": "string",
      "clinicId": "00000000-0000-0000-0000-000000000000",
      "isActive": true,
      "createdAt": "2026-01-01T00:00:00Z",
      "updatedAt": "2026-01-01T00:00:00Z"
    }
  ]
}
POST /api/v1/tags Create a tag.
key · write
Schemas
Request body (application/json)
{
  "name": "VIP",
  "color": "#3B82F6"
}
Response 201
{
  "success": true,
  "message": "string",
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "name": "string",
    "description": "string",
    "category": "string",
    "color": "string",
    "clinicId": "00000000-0000-0000-0000-000000000000",
    "isActive": true,
    "createdAt": "2026-01-01T00:00:00Z",
    "updatedAt": "2026-01-01T00:00:00Z"
  }
}
PUT /api/v1/tags/{id} Update a tag.
key · write
Schemas
Request body (application/json)
{
  "color": "#123456"
}
Response 200
{
  "success": true,
  "message": "string",
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "name": "string",
    "description": "string",
    "category": "string",
    "color": "string",
    "clinicId": "00000000-0000-0000-0000-000000000000",
    "isActive": true,
    "createdAt": "2026-01-01T00:00:00Z",
    "updatedAt": "2026-01-01T00:00:00Z"
  }
}
DELETE /api/v1/tags/{id} Delete a tag (cascades assignments).
key · write
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "name": "string",
    "description": "string",
    "category": "string",
    "color": "string",
    "clinicId": "00000000-0000-0000-0000-000000000000",
    "isActive": true,
    "createdAt": "2026-01-01T00:00:00Z",
    "updatedAt": "2026-01-01T00:00:00Z"
  }
}
POST /api/v1/tags/{id}/assign Assign a tag to a patient.
key · write
Schemas
Request body (application/json)
{
  "userId": "<patient-uuid>"
}
Response 201
{
  "success": true,
  "message": "string",
  "data": null
}
DELETE /api/v1/tags/{id}/assign/{userId} Unassign a tag.
key · write
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}

CRM · Sequences (6)

MethodPathSummary
GET /api/v1/sequences List sequences.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": [
    {
      "id": "00000000-0000-0000-0000-000000000000",
      "clinicId": "00000000-0000-0000-0000-000000000000",
      "name": "string",
      "description": "string",
      "status": "draft",
      "trigger": {},
      "steps": [
        {
          "id": "string",
          "type": "delay",
          "timeSeconds": 0,
          "useCustomText": true,
          "templateId": "00000000-0000-0000-0000-000000000000",
          "customText": "string",
          "customSubject": "string"
        }
      ],
      "analytics": {},
      "isActive": true,
      "createdAt": "2026-01-01T00:00:00Z",
      "updatedAt": "2026-01-01T00:00:00Z"
    }
  ]
}
POST /api/v1/sequences Create a sequence (draft). Key-created rows store createdBy=null (audited).
key · write
Schemas
Request body (application/json)
{
  "name": "Welcome series",
  "triggerEvent": "manual"
}
Response 201
{
  "success": true,
  "message": "string",
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "clinicId": "00000000-0000-0000-0000-000000000000",
    "name": "string",
    "description": "string",
    "status": "draft",
    "trigger": {},
    "steps": [
      {
        "id": "string",
        "type": "delay",
        "timeSeconds": 0,
        "useCustomText": true,
        "templateId": "00000000-0000-0000-0000-000000000000",
        "customText": "string",
        "customSubject": "string"
      }
    ],
    "analytics": {},
    "isActive": true,
    "createdAt": "2026-01-01T00:00:00Z",
    "updatedAt": "2026-01-01T00:00:00Z"
  }
}
GET /api/v1/sequences/{id} Sequence detail + analytics.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "clinicId": "00000000-0000-0000-0000-000000000000",
    "name": "string",
    "description": "string",
    "status": "draft",
    "trigger": {},
    "steps": [
      {
        "id": "string",
        "type": "delay",
        "timeSeconds": 0,
        "useCustomText": true,
        "templateId": "00000000-0000-0000-0000-000000000000",
        "customText": "string",
        "customSubject": "string"
      }
    ],
    "analytics": {},
    "isActive": true,
    "createdAt": "2026-01-01T00:00:00Z",
    "updatedAt": "2026-01-01T00:00:00Z"
  }
}
PUT /api/v1/sequences/{id} Update a sequence.
key · write
Schemas
Request body (application/json)
{
  "name": "Renamed"
}
Response 200
{
  "success": true,
  "message": "string",
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "clinicId": "00000000-0000-0000-0000-000000000000",
    "name": "string",
    "description": "string",
    "status": "draft",
    "trigger": {},
    "steps": [
      {
        "id": "string",
        "type": "delay",
        "timeSeconds": 0,
        "useCustomText": true,
        "templateId": "00000000-0000-0000-0000-000000000000",
        "customText": "string",
        "customSubject": "string"
      }
    ],
    "analytics": {},
    "isActive": true,
    "createdAt": "2026-01-01T00:00:00Z",
    "updatedAt": "2026-01-01T00:00:00Z"
  }
}
PUT /api/v1/sequences/{id}/steps Replace a sequence's steps.
key · write
Schemas
Request body (application/json)
{
  "steps": []
}
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/sequence-triggers/manual Manually trigger an active sequence for a user or a tag (provide exactly one).
key · write
Schemas
Request body (application/json)
{
  "sequenceId": "<seq-uuid>",
  "userId": "<patient-uuid>"
}
Response 201
{
  "success": true,
  "message": "string",
  "data": null
}

CRM · Templates (6)

MethodPathSummary
GET /api/v1/message-templates List message templates.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": [
    {
      "id": "00000000-0000-0000-0000-000000000000",
      "clinicId": "00000000-0000-0000-0000-000000000000",
      "name": "string",
      "description": "string",
      "type": "email",
      "subject": "string",
      "body": "string",
      "category": "string",
      "mergeFields": [
        "string"
      ],
      "isActive": true,
      "version": 0,
      "createdAt": "2026-01-01T00:00:00Z"
    }
  ]
}
POST /api/v1/message-templates Create a template. Key-created rows store createdBy=null (audited).
key · write
Schemas
Request body (application/json)
{
  "name": "Welcome email",
  "type": "email",
  "subject": "Welcome",
  "body": "Hi {{firstName}}"
}
Response 201
{
  "success": true,
  "message": "string",
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "clinicId": "00000000-0000-0000-0000-000000000000",
    "name": "string",
    "description": "string",
    "type": "email",
    "subject": "string",
    "body": "string",
    "category": "string",
    "mergeFields": [
      "string"
    ],
    "isActive": true,
    "version": 0,
    "createdAt": "2026-01-01T00:00:00Z"
  }
}
PUT /api/v1/message-templates/{id} Update a template.
key · write
Schemas
Request body (application/json)
{
  "body": "Hi {{firstName}}"
}
Response 200
{
  "success": true,
  "message": "string",
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "clinicId": "00000000-0000-0000-0000-000000000000",
    "name": "string",
    "description": "string",
    "type": "email",
    "subject": "string",
    "body": "string",
    "category": "string",
    "mergeFields": [
      "string"
    ],
    "isActive": true,
    "version": 0,
    "createdAt": "2026-01-01T00:00:00Z"
  }
}
DELETE /api/v1/message-templates/{id} Delete a template (soft).
key · write
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "clinicId": "00000000-0000-0000-0000-000000000000",
    "name": "string",
    "description": "string",
    "type": "email",
    "subject": "string",
    "body": "string",
    "category": "string",
    "mergeFields": [
      "string"
    ],
    "isActive": true,
    "version": 0,
    "createdAt": "2026-01-01T00:00:00Z"
  }
}
POST /api/v1/message-templates/upload-image Upload an image for use in a template (multipart, field `image`).
key · write
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "clinicId": "00000000-0000-0000-0000-000000000000",
    "name": "string",
    "description": "string",
    "type": "email",
    "subject": "string",
    "body": "string",
    "category": "string",
    "mergeFields": [
      "string"
    ],
    "isActive": true,
    "version": 0,
    "createdAt": "2026-01-01T00:00:00Z"
  }
}
POST /api/v1/message-templates/{id}/duplicate Duplicate a message template.
key · write
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}

CRM · Connection (5)

Connect the brand's OWN CRM (GoHighLevel). PENDING (third-party secret custody) + tier-gated (hasCrmIntegration).

MethodPathSummary
GET /api/v1/crm/connection CRM connection status (safe projection — no secret).
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
DELETE /api/v1/crm/connection Disconnect the brand's CRM.
key · write
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/crm/connect/apikey Connect a CRM via GHL API key.
key · write
Schemas
Request body (application/json)
{
  "provider": "gohighlevel",
  "apiKey": "<ghl-api-key>"
}
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/crm/connect/oauth/start Build the GHL OAuth authorize URL (signed state; no mutation).
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
PATCH /api/v1/crm/connection/phi-sync Enable or disable patient-data (PHI) sync to the connected CRM.
key · write
Schemas
Request body (application/json)
{
  "phiSyncEnabled": true,
  "baaAttested": true
}
Response 200
{
  "success": true,
  "data": {}
}

Affiliate Program (16)

Affiliate/referral module. PENDING (money movement) + tier-gated (Affiliates plan entitlement resolved from the key's clinic).

MethodPathSummary
GET /api/v1/affiliate-program Affiliate program config for the clinic.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
PUT /api/v1/affiliate-program Update affiliate program config (rates, cookie window, payout thresholds).
key · write
Schemas
Request body (application/json)
{
  "affiliateProgramEnabled": true,
  "affiliateCommissionMode": "percentage",
  "affiliateFirstOrderRate": 20,
  "affiliateDefaultRate": 10,
  "affiliateCommissionDurationMonths": 12,
  "affiliateCookieWindowDays": 30,
  "affiliateMinimumPayoutThreshold": 50,
  "affiliatePayoutFrequency": "monthly",
  "affiliateMaxCount": 100
}
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/affiliate-program/margin-estimate Estimated margin impact of the current commission config.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/affiliate-program/affiliates List the clinic's affiliates.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
PATCH /api/v1/affiliate-program/affiliates/{membershipId} Update per-affiliate rate overrides / payout details.
key · write
Schemas
Request body (application/json)
{
  "firstOrderRate": 25,
  "commissionRate": 12,
  "payoutContactMethod": "email",
  "payoutNotes": "..."
}
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/affiliate-program/payouts List affiliate payouts.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/affiliate-program/payouts/generate Generate the next payout batch from accrued commissions.
key · write
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/affiliate-program/payouts/{id}/commissions Commissions included in a payout.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/affiliate-program/payouts/{id}/approve Approve a pending payout.
key · write
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/affiliate-program/payouts/{id}/mark-paid Mark a payout as paid (records payout metadata).
key · write
Schemas
Request body (application/json)
{
  "notes": "Paid via ACH"
}
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/affiliate-program/payouts/{payoutId}/exclude-commissions Exclude specific commissions from a payout.
key · write
Schemas
Request body (application/json)
{
  "commissionIds": [
    "<commission-uuid>"
  ]
}
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/affiliate-program/tax-documents List affiliate W-9 / tax documents for review.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/affiliate-program/tax-documents/{docId}/verify Mark a tax document verified.
key · write
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/affiliate-program/tax-documents/{docId}/reject Reject a tax document (reason required).
key · write
Schemas
Request body (application/json)
{
  "reason": "Illegible — please resubmit"
}
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/affiliate-program/tiers Create a commission tier.
key · write
Schemas
Request body (application/json)
{
  "minActiveReferrals": 5,
  "percentage": 15,
  "label": "Silver"
}
Response 201
{
  "success": true,
  "message": "string",
  "data": null
}
DELETE /api/v1/affiliate-program/tiers/{tierId} Delete a commission tier.
key · write
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}

Team & Users (5)

Brand-staff management. PENDING — exposes staff identity/2FA and grants/revokes FUSE-platform access.

MethodPathSummary
GET /api/v1/team/members Brand-staff roster + pending team invitations (no patient PHI).
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/team/invite Invite a team member.
key · write
Schemas
Request body (application/json)
{
  "email": "colleague@brand.com",
  "role": "member"
}
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
DELETE /api/v1/team/invitations/{invitationId} Revoke a pending team invitation.
key · write
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
DELETE /api/v1/team/{userId} Remove a team member from the clinic.
key · write
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
PATCH /api/v1/team/{userId}/role Change a team member's role ('admin' or 'member'; ownership cannot be assigned via the API).
key · write
Schemas
Request body (application/json)
{
  "role": "admin"
}
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}

Organization & Clinic (9)

Clinic settings. GET /clinic and GET /config/fees are live; org profile + SendGrid email-domain auth + logo upload are PENDING (shared-infra/DNS + org writes).

MethodPathSummary
GET /api/v1/clinic The key clinic's profile.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/config/fees Fee configuration for the clinic (pharmacy, doctor, Stripe, merchant fees).
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/organization The key clinic's org settings + notification config.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/clinic/email-domain SendGrid email-domain authentication status.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
PUT /api/v1/clinic/email-sender Update the reply-to email sender address.
key · write
Schemas
Request body (application/json)
{
  "replyTo": "support@brand.com"
}
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/clinic/email-domain/start Start SendGrid domain authentication (returns DNS records to add).
key · write
Schemas
Request body (application/json)
{
  "domain": "brand.com",
  "fromLocalPart": "support"
}
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/clinic/email-domain/verify Verify the SendGrid domain authentication DNS records.
key · write
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/clinic/email-domain/remove Remove SendGrid domain authentication.
key · write
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/clinic/{id}/upload-logo Upload the clinic logo (multipart, field `logo`; :id is ignored, always the key's own clinic).
key · write
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}

Custom Website (8)

Storefront/portal config (CustomWebsite). No PHI. logo-proxy is a pending CORS-convenience byte proxy.

MethodPathSummary
GET /api/v1/custom-website The clinic's storefront config.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/custom-website Create/update the storefront config.
key · write
Schemas
Request body (application/json)
{
  "heroPrimaryButtonText": "Get started",
  "isActive": true,
  "footerColor": "#111827",
  "socialMediaLinks": {
    "instagram": "https://instagram.com/brand"
  }
}
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/custom-website/toggle-active Enable/disable the custom website.
key · write
Schemas
Request body (application/json)
{
  "isActive": true
}
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/custom-website/reset-footer Reset footer content to defaults.
key · write
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/custom-website/reset-social-media Reset social-media links to defaults.
key · write
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/custom-website/upload-logo Upload the storefront logo (multipart, field `logo`).
key · write
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/custom-website/upload-hero Upload the storefront hero image (multipart, field `heroImage`).
key · write
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/custom-website/logo-proxy CORS-convenience proxy that streams the storefront logo bytes.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}

Support & Conversations (8)

Patient support threads + tickets. PENDING — contains patient PHI (authors + messages). Every handler 404s anything outside the key's clinic.

MethodPathSummary
GET /api/v1/conversations/{id} One support conversation thread (own-clinic only).
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/conversations/{id}/messages Post a message to a conversation.
key · write
Schemas
Request body (application/json)
{
  "message": "Thanks for reaching out — how can we help?",
  "isInternalNote": false
}
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/conversations/{id}/resolve Mark a conversation resolved.
key · write
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/support/tickets List the clinic's support tickets.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/support/users Users available for support-ticket assignment.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/support/tickets/{id}/messages Post a message on a support ticket.
key · write
Schemas
Request body (application/json)
{
  "message": "We've escalated this to the pharmacy."
}
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/support/tickets/{id} One support ticket (own-clinic only).
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
PUT /api/v1/support/tickets/{id} Update a support ticket (title/description/assignment/status).
key · write
Schemas
Request body (application/json)
{
  "title": "Shipment delayed",
  "description": "...",
  "assignedTeam": "fulfillment",
  "status": "in_progress"
}
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}

Forms & Global Products (3)

Global-product intake-form builder (TenantProductForm rows). PENDING — builder surface behind per-clinic enablement (ask your FUSE contact).

MethodPathSummary
GET /api/v1/forms/global-products List the clinic's global-product intake forms.
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/forms/global-products Attach an intake form to a global product.
key · write
Schemas
Request body (application/json)
{
  "globalProductId": "<global-product-uuid>",
  "formId": "<form-uuid>"
}
Response 201
{
  "success": true,
  "message": "string",
  "data": null
}
DELETE /api/v1/forms/global-products Detach an intake form from a global product.
key · write
Schemas
Request body (application/json)
{
  "formId": "<form-uuid>"
}
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}

Intake Requests (2)

MethodPathSummary
GET /api/v1/intake-requests The clinic's own intake-form requests (no PHI).
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/intake-requests Create an intake-form request (requestedByUserId stored NULL for a key actor).
key · write
Schemas
Request body (application/json)
{
  "treatmentName": "New treatment intake",
  "notes": "..."
}
Response 201
{
  "success": true,
  "message": "string",
  "data": null
}

Misc / Uploads (13)

MethodPathSummary
POST /api/v1/upload/logo Upload a logo to S3 and set Clinic.logo for the key's clinic (multipart, field `logo`).
key · write
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/teleform-removals Teleform wind-down rows for the clinic (no PHI).
key
Schemas
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
POST /api/v1/teleform-removals/{id}/cancel Cancel a scheduled teleform removal (own-clinic only).
key · write
Schemas
Request body (application/json)
{
  "reason": "Keeping this form active"
}
Response 200
{
  "success": true,
  "message": "string",
  "data": null
}
GET /api/v1/notifications List the brand's notifications.
key
Schemas
Response 200
{
  "success": true,
  "data": {
    "notifications": [
      {}
    ],
    "unreadCount": 0,
    "total": 0
  }
}
POST /api/v1/notifications/read Mark brand notifications as read.
key · write
Schemas
Request body (application/json)
{
  "ids": [
    "00000000-0000-0000-0000-000000000000"
  ]
}
Response 200
{
  "success": true,
  "data": {
    "updated": 0
  }
}
GET /api/v1/coupons List the brand's customer coupons.
key
Schemas
Response 200
{
  "success": true,
  "data": [
    {}
  ]
}
POST /api/v1/coupons Create a customer coupon.
key · write
Schemas
Request body (application/json)
{
  "code": "string",
  "description": null,
  "discountType": "percent",
  "discountValue": 0,
  "startsAt": null,
  "expiresAt": null,
  "isActive": true,
  "scope": "first_charge",
  "overMarginBehavior": "reject",
  "maxRedemptions": null,
  "perCustomerLimit": null,
  "minOrderAmount": null
}
Response 201
{
  "success": true,
  "data": {}
}
GET /api/v1/coupons/{id} Get one of the brand's coupons.
key
Schemas
Response 200
{
  "success": true,
  "data": {}
}
PUT /api/v1/coupons/{id} Update one of the brand's coupons.
key · write
Schemas
Request body (application/json)
{
  "code": "string",
  "description": null,
  "discountType": "percent",
  "discountValue": 0,
  "startsAt": null,
  "expiresAt": null,
  "isActive": true,
  "scope": "first_charge",
  "overMarginBehavior": "reject",
  "maxRedemptions": null,
  "perCustomerLimit": null,
  "minOrderAmount": null
}
Response 200
{
  "success": true,
  "data": {}
}
DELETE /api/v1/coupons/{id} Delete one of the brand's coupons.
key · write
Schemas
Response 200
{
  "success": true
}
GET /api/v1/coupons/{id}/performance Coupon performance (redemptions, discount totals).
key
Schemas
Response 200
{
  "success": true,
  "data": {}
}
GET /api/v1/pharmacy-price-changes/alerts List outstanding pharmacy price-change alerts.
key
Schemas
Response 200
{
  "success": true,
  "data": {
    "count": 0,
    "alerts": [
      {
        "id": "00000000-0000-0000-0000-000000000000",
        "productId": null,
        "programId": null,
        "globalProductId": null,
        "direction": "increase",
        "currentProgramFee": null,
        "suggestedProgramFee": null,
        "perUnitMarginDelta": null,
        "status": "string",
        "createdAt": "2026-01-01T00:00:00Z"
      }
    ]
  }
}
POST /api/v1/pharmacy-price-changes/alerts/{alertId}/acknowledge Acknowledge a pharmacy price-change alert.
key · write
Schemas
Response 200
{
  "success": true,
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "status": "string"
  }
}

Checkout Sessions (2)

MethodPathSummary
POST /api/v1/checkout/sessions Create a checkout session for one of the clinic's own programs
key · write
Schemas
Request body (application/json)
{
  "programId": "00000000-0000-0000-0000-000000000000",
  "metadata": {},
  "successUrl": null
}
Response 201
{
  "success": true,
  "data": {
    "sessionId": "00000000-0000-0000-0000-000000000000",
    "sessionToken": "string",
    "embedUrl": "string",
    "expiresAt": "2026-01-01T00:00:00Z"
  }
}
GET /api/v1/checkout/sessions/{id} Get checkout session status (own-clinic only)
key
Schemas
Response 200
{
  "success": true,
  "data": {
    "sessionId": "00000000-0000-0000-0000-000000000000",
    "status": "created",
    "orderId": null,
    "expiresAt": "2026-01-01T00:00:00Z"
  }
}

Webhooks (3)

MethodPathSummary
GET /api/v1/webhooks List the clinic's webhook endpoints (secrets omitted)
key
Schemas
Response 200
{
  "success": true,
  "data": [
    {
      "id": "00000000-0000-0000-0000-000000000000",
      "url": "string",
      "events": [
        "string"
      ],
      "isActive": true,
      "lastTriggeredAt": "2026-01-01T00:00:00Z",
      "consecutiveFailures": 0
    }
  ]
}
POST /api/v1/webhooks Register an outbound webhook endpoint
key · write
Schemas
Request body (application/json)
{
  "url": "string",
  "events": [
    "session.completed"
  ]
}
Response 201
{
  "success": true,
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "url": "string",
    "events": [
      "string"
    ],
    "isActive": true,
    "secret": "string"
  }
}
DELETE /api/v1/webhooks/{id} Delete a webhook endpoint (own-clinic only)
key · write
Schemas
Response 200
{
  "success": true,
  "data": {
    "id": "00000000-0000-0000-0000-000000000000"
  }
}