← Назад к документацииAPI

Публичное API Funnelica

Публичные эндпойнты Funnelica для размещения форм и страниц, трекинга событий, checkout и входа в студенческий портал. Эти методы не требуют токена пользователя платформы; где нужно, используется студенческий токен.

Базовый URL, заголовки, ответы

Базовый URL зависит от окружения. В dev обычно используется http://localhost:4000. В проде — адрес backend, например https://api.example.com. Если backend проксируется на /api, используйте этот префикс.

Заголовки
  • Content-Type: application/json — для JSON-запросов.
  • x-tenant-host — укажите домен, если нужно резолвить workspace не по текущему Host (актуально для страниц/сайтов).
  • x-session-id — связывает события и просмотры в одну сессию.
  • Authorization: Bearer <studentAccessToken> — только для защищенных student-эндпойнтов.
Формат ошибок

Ошибка возвращается как JSON:

{
  "statusCode": 400,
  "message": "Form is not available",
  "error": "Bad Request",
  "path": "/forms/xxx/submit",
  "timestamp": "2025-12-19T12:00:00.000Z",
  "requestId": "..."
}

Формы (public submit)

Публичная отправка формы. Workspace определяется по домену формы (Host). Поле payload обязательно, остальные — опциональны.

POST /forms/:id/submit
{
  "name": "Иван",
  "email": "ivan@example.com",
  "phone": "+7 (999) 000-00-00",
  "company": "ООО Пример",
  "pageUrl": "https://site.example.com/landing",
  "source": "form:Landing",
  "utm": { "utm_source": "ads", "utm_campaign": "winter" },
  "payload": {
    "question": "Что вы предлагаете?"
  }
}

Ответ:

{
  "submissionId": "sub_...",
  "contactId": "contact_...",
  "status": "received"
}

Публичные страницы и трекинг

Получение страницы для рендера и трекинг просмотров. Если домен не совпадает с workspace, передайте x-tenant-host илиworkspaceId в query. Для создания/привязки контакта можно передать email, phone, nameв query.

GET /public/pages/by-path?path=/landing&workspaceId=...

Возвращает страницу (включая schema) и данные A/B-эксперимента.

{
  "id": "page_...",
  "name": "Landing",
  "path": "/landing",
  "status": "published",
  "schema": { "editor": "grapesjs", "html": "...", "css": "..." },
  "experiment": { "experimentId": "exp_...", "variant": "A" }
}
GET /public/pages/:id
POST /public/pages/:path/track
{
  "contactId": "contact_...",
  "sessionId": "session_...",
  "utm": { "utm_source": "ads" }
}

Ответ: { "success": true, "viewId": "view_..." }

Публичные воронки

GET /public/funnels/:id
{
  "id": "funnel_...",
  "name": "Воронка запуска",
  "steps": [{ "id": "step_1", "type": "page", "pageId": "page_..." }],
  "status": "active"
}
POST /public/funnels/:funnelId/steps/:stepId/track
{
  "contactId": "contact_...",
  "metadata": { "utm_campaign": "winter" }
}

Ответ: { "success": true }

GET /public/funnels/:funnelId/next-step?currentStepId=step_1

Ответ: { "nextStepId": "step_2" }

Checkout и заказы

GET /public/checkout/by-path?path=/checkout/abc

Возвращает настройки checkout (продукт, цена, настройки оплаты).

POST /public/checkout/validate-coupon
{
  "checkoutPath": "/checkout/abc",
  "couponCode": "SUMMER10"
}
POST /public/checkout/create-order
{
  "checkoutPath": "/checkout/abc",
  "email": "ivan@example.com",
  "phone": "+7 (999) 000-00-00",
  "name": "Иван",
  "company": "ООО Пример",
  "couponCode": "SUMMER10",
  "referralCode": "ref-123"
}

Ответ содержит данные заказа и paymentUrl для оплаты.

GET /public/orders/:orderId/redirect-url

Возвращает URL для редиректа после оплаты (thank-you/upsell).

POST /public/orders/:orderId/upsell-response
{
  "action": "accept",
  "type": "upsell",
  "checkoutPath": "/checkout/upsell-1"
}

Резолв доменов

GET /public/tenants/resolve?host=example.com&kind=sites
{
  "matched": true,
  "workspaceId": "workspace_...",
  "slug": "company",
  "kind": "sites",
  "domainId": "domain_...",
  "host": "company.sites.example.com"
}

Email-трекинг и отписка

GET /emails/track/open?messageId=... — пиксель открытия (GIF).
GET /emails/track/click?messageId=...&url=... — редирект по ссылке.
GET /unsubscribe?email=...&workspace=...
POST /unsubscribe — one-click unsubscribe (List-Unsubscribe-Post).

Студенческий портал

Вход по коду подтверждения. Ответ на запрос кода всегда успешный — это защищает от перебора почтовых адресов. Если известен workspace, передавайте workspaceId.

POST /student/auth/request-login
{
  "email": "student@example.com",
  "workspaceId": "workspace_..." // опционально
}
POST /student/auth/verify-code
{
  "email": "student@example.com",
  "code": "123456",
  "workspaceId": "workspace_..." // опционально
}

Ответ: { accessToken, refreshToken, contact }

POST /student/auth/refresh
{ "refreshToken": "..." }

Защищенные эндпойнты требуют Authorization: Bearer <accessToken>:/student/me,/student/dashboard,/student/courses,/student/enrollments/:id/...