Skip to main content

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.

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:
LayerMechanism
Rate limitingPer-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.
HoneypotA hidden website field is included in each form schema. Any submission that populates this field is rejected silently as bot traffic.
Turnstile captchaEach form submission must include a turnstile_token obtained from Cloudflare Turnstile. The server verifies it server-side before processing the request.
Even though no JWT is required, all POST endpoints in this section require the X-CSRF-Token header and a matching csrf_token cookie. Requests without both will be rejected with 403 Forbidden.

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 the X-CSRF-Token header on all subsequent POST requests. The cookie is set automatically by the browser. Auth required: No
Rate limit: 30 requests / hour per IP

Response

ok
boolean
required
true
csrf_token
string
required
A cryptographically signed CSRF token. Also set as a cookie named csrf_token (HttpOnly, SameSite=Strict).
The server sets a csrf_token cookie alongside the JSON response. Both must be present for POST requests to succeed.

Example

# Fetch a CSRF token and save the cookie
curl -c cookies.txt https://api.example.com/api/csrf-token
{
  "ok": true,
  "csrf_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
In browser environments the csrf_token cookie is set automatically. Extract the csrf_token value from the JSON body and attach it as the X-CSRF-Token header on every subsequent form POST.

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: No
Rate limit: Configurable — set via RATE_LIMIT_CONTACT environment variable (default varies per deployment)

Headers

HeaderValue
Content-Typeapplication/json
X-CSRF-TokenToken obtained from GET /api/csrf-token

Request

company_name
string
required
Name of the prospective company. 1–150 characters. HTML-stripped and sanitised.
company_email
string
required
Contact email address. Validated and normalised.
country_code
string
required
ISO 3166-1 alpha-2 country code (e.g., ES, MX, US). Must be one of the supported country codes.
phone
string
required
Phone number. 4–20 characters. Validated against the provided country_code using E.164 normalisation.
is_member
boolean
required
Whether the requester is already a Stay Sidekick member.
message
string
Optional free-text message. Max 2000 characters. HTML-stripped.
turnstile_token
string
required
Cloudflare Turnstile verification token from the front-end widget. Max 2048 characters.
privacy_accepted
boolean
required
Must be true. The request is rejected if false or absent.
website
string
Honeypot field. Must be empty or absent. Any non-empty value causes the submission to be rejected.

Response

200 OK
ok
boolean
required
true
message
string
required
"Solicitud recibida correctamente."

Error Responses

StatusCause
403 ForbiddenTurnstile captcha verification failed.
422 Unprocessable EntityValidation errors (missing fields, invalid email, phone mismatch, etc.).
429 Too Many RequestsRate limit exceeded.

Example

curl -X POST https://api.example.com/api/contact \
  -b cookies.txt \
  -H "X-CSRF-Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -H "Content-Type: application/json" \
  -d '{
    "company_name": "Mar Rentals SL",
    "company_email": "info@mar-rentals.com",
    "country_code": "ES",
    "phone": "612345678",
    "is_member": false,
    "message": "Interested in the starter plan.",
    "turnstile_token": "<turnstile-response-token>",
    "privacy_accepted": true,
    "website": ""
  }'
{
  "ok": true,
  "message": "Solicitud recibida correctamente."
}

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: No
Rate limit: 10 requests / hour per IP

Headers

HeaderValue
Content-Typeapplication/json
X-CSRF-TokenToken obtained from GET /api/csrf-token

Request

nombre
string
required
Sender’s full name. 1–100 characters. HTML-stripped and sanitised.
email
string
required
Sender’s email address. Max 254 characters. Validated and normalised.
empresa
string
Optional company name. Max 150 characters.
mensaje
string
required
Message body. 10–2000 characters. HTML-stripped.
turnstile_token
string
required
Cloudflare Turnstile verification token from the front-end widget. Max 2048 characters.
website
string
Honeypot field. Must be empty or absent.

Response

200 OK
ok
boolean
required
true
message
string
required
"Mensaje enviado correctamente."

Error Responses

StatusCause
403 ForbiddenTurnstile captcha verification failed.
422 Unprocessable EntityValidation errors (missing fields, invalid email, message too short, etc.).
429 Too Many RequestsRate limit exceeded.

Example

curl -X POST https://api.example.com/api/contacto \
  -b cookies.txt \
  -H "X-CSRF-Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -H "Content-Type: application/json" \
  -d '{
    "nombre": "María García",
    "email": "maria@example.com",
    "empresa": "Sol Rentals",
    "mensaje": "Me gustaría saber más sobre los planes de precios.",
    "turnstile_token": "<turnstile-response-token>",
    "website": ""
  }'
{
  "ok": true,
  "message": "Mensaje enviado correctamente."
}
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.

Build docs developers (and LLMs) love