---
title: "Proxied HubSpot Forms submission (non-enterprise contact + newsletter)"
method: POST
path: "/contact/submit"
tags: ["Misc"]
---

# Proxied HubSpot Forms submission (non-enterprise contact + newsletter)

`POST /contact/submit`

## Request

- Base URL: `https://api.mnemom.ai/v1`
- URL: `https://api.mnemom.ai/v1/contact/submit`
- Auth: none required

Server-side replacement for the old browser→HubSpot Forms submission. Routes /contact (general/support/privacy) and newsletter signups through the Worker so they're gated by the anti-spam guard (honeypot + strict email/char/length validation + optional Cloudflare Turnstile verification) before anything reaches HubSpot. `form_type=contact` requires a Turnstile token (once `TURNSTILE_SECRET_KEY` is set on the Worker); `form_type=newsletter` runs honeypot + validation only. On success the Worker also performs the CRM upsert + hot-lead Slack alert (same as /contact/notify). Returns a non-2xx so the UI can keep the form open on rejection.

## Request body

- object
  - `form_type` 'contact' | 'newsletter': Which HubSpot form to submit. Defaults to `contact`. `contact` requires a Turnstile token when the Worker has TURNSTILE_SECRET_KEY set; `newsletter` does not.
  - `email` string, email, required: Contact email address (required).
  - `name` string: Contact's display name; split into firstname/lastname on the HubSpot side.
  - `reason` string: Contact-form reason (general/support/privacy). Stored as the HubSpot `contact_reason` field.
  - `message` string: Free-form message body.
  - `source` string: Origin surface. Defaults to `contact_page` for form_type=contact and `newsletter` for form_type=newsletter.
  - `turnstile_token` string: Cloudflare Turnstile token from the website widget. Required when form_type=contact AND the Worker has TURNSTILE_SECRET_KEY set; ignored otherwise.
  - `company_website` string: Honeypot — must be empty. Real users never see the field; any non-empty value silently rejects the submission as bot traffic.
  - `context` object: Optional HubSpot form context forwarded to the Forms API (preserves hutk / page attribution).
    - `hutk` string: HubSpot tracking cookie (hubspotutk).
    - `pageUri` string: URL the form was submitted from.
    - `pageName` string: document.title of the submitting page.
  - `utms` object: UTM parameters merged into the HubSpot form fields for attribution.
  - `engagement` object: Optional engagement telemetry used for hot-lead scoring (same shape as /contact/notify).

## Response `200`

Submission accepted. The Worker performed the HubSpot Forms submission and the CRM upsert + Slack alert.

- object
  - `ok` true, required
  - `notified` boolean: True only when the hot-lead Slack alert fired.

## Other responses

- `400`: Bad request
- `403`: Anti-spam guard rejected the submission (Turnstile failed / required token missing).
- `429`: Too many requests
- `500`: Server error — request was well-formed but the server failed to fulfill it. Typically a downstream dependency (DB / RPC / external API) returned an unexpected error.
- `502`: Upstream HubSpot Forms submission failed.

---

[API](https://skmtc.dev/mnemom/apis/mnemom-api.md) · [All operations](https://skmtc.dev/mnemom/apis/mnemom-api/llms.txt) · [OpenAPI document](https://skmtc.dev/mnemom/apis/mnemom-api/revisions/274b7a6ea182?raw)
