Send website inquiries to CRM

Request and response reference for submitting website forms.

Send website inquiries to CRM

This is the reference for the developer wiring a website form into a Workspace CRM inbox. A submission creates an Inquiry that Owners and Managers review, respond to, and manage in Backoffice.

Before using this, someone in the Workspace needs to create a key and set up inquiry types. See Connect your website to CRM for that.

Base path:

https://backoffice.mindfulltechnologies.com

Submission modes

The endpoint accepts two credential modes. Use exactly one per request.

1. Browser form submissions

Send the public formKey in the JSON body. This is safe in website JavaScript because the backend validates the form key, the Workspace CRM capability, and the allowed origins configured for that key. Send the browser Origin header.

POST /api/public/v1/inquiries
Content-Type: application/json
Origin: https://hotel.example.com
X-External-Submission-Id: contact-form-2026-06-26-001
{
  "formKey": "mf_form_public_abc123",
  "typeSlug": "general",
  "contact": {
    "name": "Anu Mathew",
    "email": "anu@example.com",
    "phone": "+91 99999 99999"
  },
  "subject": "Question about rooms",
  "message": "Do you have parking available?",
  "additionalDetails": {
    "page": "/contact",
    "campaign": "monsoon-offer"
  }
}

2. Server-to-server submissions

Send the secret API key as a bearer token and omit formKey from the body. Do not expose this key in browser JavaScript.

POST /api/public/v1/inquiries
Content-Type: application/json
Authorization: Bearer mf_live_secret_value
X-External-Submission-Id: room-form-2026-08-12-anu
{
  "typeSlug": "rooms",
  "contact": {
    "name": "Anu Mathew",
    "email": "anu@example.com",
    "phone": "+91 99999 99999"
  },
  "message": "We would like two rooms if available.",
  "startsAt": "2026-08-12",
  "endsAt": "2026-08-15",
  "arrivalTime": "18:30",
  "guestCount": 4,
  "additionalDetails": {
    "sourceSystem": "wordpress",
    "roomType": "Deluxe"
  }
}

Request fields

FieldRequiredNotes
formKeyBrowser form submissions onlyRequired when no bearer API key is sent. Omit for server-to-server submissions.
typeIdOptionalInquiry type id. Omit to use the Workspace default type.
typeSlugOptionalInquiry type slug, such as rooms or events. Omit to use the default.
contact.nameOptionalCustomer or guest name. Up to 120 characters.
contact.emailRequired unless phone is presentMust be a valid email if provided, up to 254 characters. Used for matching.
contact.phoneRequired unless email is presentStored on the CRM contact. Up to 32 characters, spaces and brackets included.
contact.companyOptionalUseful for business accounts. Up to 120 characters.
subjectOptionalShort summary shown in the inquiry list. Up to 500 characters.
messageOptionalCustomer message. Up to 4000 characters.
startsAtOptionalISO date such as 2026-08-12.
endsAtOptionalISO date such as 2026-08-15.
arrivalTimeOptionalHH:mm format, 24 hour.
guestCountOptionalPositive integer.
additionalDetailsOptionalObject of custom form fields, up to 8 KB as JSON. Do not send secrets.

A value over its limit is refused with 400 and VALIDATION_FAILED, and the message names the field and its limit, such as Name must be 120 characters or fewer. Nothing is filed, so correct the value and send it again.

Inquiry type slugs come from Settings then Inquiry types in Backoffice. A submission that sends neither typeId nor typeSlug is filed under the Workspace default type, General.

Retries and email notification matching

Send the X-External-Submission-Id header so a retry does not create a duplicate inquiry for the same Workspace:

X-External-Submission-Id: canoeville-contact-a1b2c3d4e5f678901234567890abcdef

Use a unique, stable value per submission.

If your website also sends a notification email about the same submission to a connected CRM email channel, put an X-External-Submission-Id header with the identical value on that email. The email then attaches to the inquiry this API created instead of arriving as a second, separate inquiry.

Responses

A new inquiry returns 201.

{
  "inquiry": {
    "id": "inquiry_123",
    "workspaceId": "workspace_123",
    "type": {
      "id": "type_rooms",
      "name": "Rooms",
      "slug": "rooms",
      "isDefault": false
    },
    "status": "NEW",
    "source": "WEBSITE_FORM",
    "sourceName": "Hotel website",
    "subject": null,
    "message": "We would like two rooms if available.",
    "preferredStartAt": "2026-08-12T00:00:00.000Z",
    "preferredEndAt": "2026-08-15T00:00:00.000Z",
    "arrivalTime": "18:30",
    "guestCount": 4,
    "receivedAt": "2026-06-26T10:00:00.000Z",
    "updatedAt": "2026-06-26T10:00:00.000Z",
    "contact": {
      "id": "contact_123",
      "name": "Anu Mathew",
      "email": "anu@example.com",
      "phone": "+91 99999 99999"
    },
    "assignedMember": null
  }
}

A retry with an already-used X-External-Submission-Id returns 200 with idempotent: true. Treat it as success.

{
  "inquiry": {
    "id": "inquiry_123"
  },
  "idempotent": true
}

If the notification email reached CRM before this request did, the existing email inquiry is filled in with the form's details rather than duplicated. That returns 200 with upgraded: true. Treat it as success too.

{
  "inquiry": {
    "id": "inquiry_123"
  },
  "upgraded": true
}

Errors

Errors return a JSON object with an error holding a code and a message. The message is safe to log; do not show it to your website visitors, since it describes the integration rather than what they did.

{
  "error": {
    "code": "VALIDATION_FAILED",
    "message": "Contact email is invalid"
  }
}
StatusMeaning
400A field is missing or malformed.
401The form key or API key is missing, unknown, or disabled.
403The Origin is not on the key's allowed list, or CRM is off for the Workspace.
429Too many submissions. Wait before retrying; see the limits below.
500Unexpected server error. Safe to retry with the same submission id.

Limits

The intake accepts up to 10 submissions a minute from one address per Workspace, and up to 1,000 a day for the Workspace as a whole. A submission over either limit is answered 429 with the code INQUIRY_RATE_LIMITED and is not stored, so a client that retries should wait at least a minute before sending the same submission id again. A real website form does not reach these; a script that does is the reason they exist.

Versioning

This endpoint is versioned under /v1. New fields may appear in responses, so ignore fields you do not recognise. Breaking changes will use a new version path.