These three endpoints are publicly accessible — no JWT is required. They power the marketing site’s contact form, the company onboarding request form, and the CSRF token handshake used by all state-mutating public requests. Every public form submission passes through four independent anti-spam layers before being processed:Documentation Index
Fetch the complete documentation index at: https://mintlify.com/sdurutr436/stay-sidekick/llms.txt
Use this file to discover all available pages before exploring further.
| Layer | Mechanism |
|---|---|
| Rate limiting | Per-IP limits enforced by Flask-Limiter. Exceeding the limit returns 429 Too Many Requests. |
| CSRF (Double-Submit Cookie) | The client must first obtain a token via GET /api/csrf-token, which sets an HttpOnly cookie and returns the raw token. All POST requests must include both the cookie and the X-CSRF-Token header — the server validates they match. |
| Honeypot | A hidden website field is included in each form schema. Any submission that populates this field is rejected silently as bot traffic. |
| Turnstile captcha | Each form submission must include a turnstile_token obtained from Cloudflare Turnstile. The server verifies it server-side before processing the request. |
GET /api/csrf-token
Generates a CSRF token and returns it in both the response body and as a cookie. The client should store the raw token and attach it as theX-CSRF-Token header on all subsequent POST requests. The cookie is set automatically by the browser.
Auth required: NoRate limit: 30 requests / hour per IP
Response
trueA cryptographically signed CSRF token. Also set as a cookie named
csrf_token (HttpOnly, SameSite=Strict).csrf_token cookie alongside the JSON response. Both must be present for POST requests to succeed.
Example
POST /api/contact
Company signup request form. Intended for prospective customers filling out the “Request Access” form on the marketing site. Successful submissions are dispatched to the internal email and Discord notification channels. Auth required: NoRate limit: Configurable — set via
RATE_LIMIT_CONTACT environment variable (default varies per deployment)
Headers
| Header | Value |
|---|---|
Content-Type | application/json |
X-CSRF-Token | Token obtained from GET /api/csrf-token |
Request
Name of the prospective company. 1–150 characters. HTML-stripped and sanitised.
Contact email address. Validated and normalised.
ISO 3166-1 alpha-2 country code (e.g.,
ES, MX, US). Must be one of the supported country codes.Phone number. 4–20 characters. Validated against the provided
country_code using E.164 normalisation.Whether the requester is already a Stay Sidekick member.
Optional free-text message. Max 2000 characters. HTML-stripped.
Cloudflare Turnstile verification token from the front-end widget. Max 2048 characters.
Must be
true. The request is rejected if false or absent.Honeypot field. Must be empty or absent. Any non-empty value causes the submission to be rejected.
Response
200 OK
true"Solicitud recibida correctamente."Error Responses
| Status | Cause |
|---|---|
403 Forbidden | Turnstile captcha verification failed. |
422 Unprocessable Entity | Validation errors (missing fields, invalid email, phone mismatch, etc.). |
429 Too Many Requests | Rate limit exceeded. |
Example
POST /api/contacto
General contact form for existing users or visitors reaching out via the/empresa/contacto page. Successful submissions are forwarded to the internal email and Discord channels.
Auth required: NoRate limit: 10 requests / hour per IP
Headers
| Header | Value |
|---|---|
Content-Type | application/json |
X-CSRF-Token | Token obtained from GET /api/csrf-token |
Request
Sender’s full name. 1–100 characters. HTML-stripped and sanitised.
Sender’s email address. Max 254 characters. Validated and normalised.
Optional company name. Max 150 characters.
Message body. 10–2000 characters. HTML-stripped.
Cloudflare Turnstile verification token from the front-end widget. Max 2048 characters.
Honeypot field. Must be empty or absent.
Response
200 OK
true"Mensaje enviado correctamente."Error Responses
| Status | Cause |
|---|---|
403 Forbidden | Turnstile captcha verification failed. |
422 Unprocessable Entity | Validation errors (missing fields, invalid email, message too short, etc.). |
429 Too Many Requests | Rate limit exceeded. |
Example
The two contact endpoints (
/api/contact and /api/contacto) serve different forms with different field schemas. /api/contact is for new company onboarding requests and requires business details. /api/contacto is for general inquiries and only requires a name, email, and message.
