{
  "openapi": "3.1.1",
  "info": {
    "title": "Escape Mode Travel planning inquiry API",
    "version": "1.0.0",
    "description": "Submit one traveler-confirmed planning inquiry. No booking, payment, reservation, inventory hold, or live quote is performed. Assistant clients must review the exact payload with the traveler, disclose storage and email side effects, obtain explicit final submission confirmation, and keep optional marketing consent separate. No automatic retries or idempotency guarantee."
  },
  "servers": [
    {
      "url": "https://escapemodetravels.com"
    }
  ],
  "externalDocs": {
    "url": "https://escapemodetravels.com/docs/api/",
    "description": "Assistant workflow, consent, side effects, and error handling"
  },
  "paths": {
    "/api/leads": {
      "post": {
        "operationId": "submitTravelPlanningInquiry",
        "summary": "Submit a confirmed travel-planning inquiry",
        "description": "Creates a stored inquiry and lead event; may create or update a marketing subscription only when marketingConsent=true; attempts the traveler snapshot email and schedules advisor notifications. No API key or OAuth token is required. Server-side HTTPS clients are supported; cross-origin browser integration is not enabled. If Origin is present, its hostname must match the API request hostname. Send application/json, never exceed 16,384 UTF-8 bytes, and never include passport, payment, password, or other highly sensitive data. A timeout or 500 can follow storage or email side effects. Do not retry automatically. The server validates consent=true; client-side final confirmation is a workflow obligation, not a signed confirmation token.",
        "security": [],
        "x-openai-isConsequential": true,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "tripType",
                  "timing",
                  "travelers",
                  "budget",
                  "firstName",
                  "email",
                  "consent"
                ],
                "properties": {
                  "tripType": {
                    "type": "string",
                    "enum": [
                      "cruise",
                      "all-inclusive",
                      "bahamas-caribbean",
                      "disney-universal",
                      "europe",
                      "family-group",
                      "not-sure"
                    ],
                    "description": "Trip style chosen by the traveler."
                  },
                  "timing": {
                    "type": "string",
                    "enum": [
                      "0-3",
                      "3-6",
                      "6-12",
                      "12-plus",
                      "exploring"
                    ],
                    "description": "Planning window, not an exact departure date. Put exact dates in notes if known."
                  },
                  "travelers": {
                    "type": "string",
                    "enum": [
                      "1",
                      "2",
                      "3-5",
                      "6-plus"
                    ],
                    "description": "Traveler count range. Put exact traveler and room requirements in notes if known."
                  },
                  "budget": {
                    "type": "string",
                    "enum": [
                      "under-3000",
                      "3000-5000",
                      "5000-8000",
                      "8000-15000",
                      "15000-plus",
                      "not-sure"
                    ],
                    "description": "Comfortable total planning range in USD; not a verified package price."
                  },
                  "firstName": {
                    "type": "string",
                    "maxLength": 80,
                    "minLength": 1,
                    "description": "Traveler's first name; must be nonempty after trimming."
                  },
                  "email": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 254,
                    "format": "email",
                    "description": "Traveler's email; trimmed, lowercased, and checked for a simple local@domain.suffix shape."
                  },
                  "consent": {
                    "type": "boolean",
                    "const": true,
                    "description": "I agree that Selena may contact me by email about this travel request. I can ask to stop at any time. Set true only after explicit permission and final submission confirmation."
                  },
                  "marketingConsent": {
                    "type": "boolean",
                    "default": false,
                    "description": "Also send me occasional Escape Mode travel inspiration and planning updates. I can unsubscribe at any time. Optional, separate opt-in. Omit or send false unless the traveler explicitly chooses it."
                  },
                  "phone": {
                    "type": "string",
                    "maxLength": 40,
                    "description": "Optional phone number. The server does not validate phone format."
                  },
                  "contactPreference": {
                    "type": "string",
                    "enum": [
                      "email",
                      "phone"
                    ],
                    "default": "email",
                    "description": "Use phone only when the traveler requests it and provides a phone number. Otherwise the server uses email."
                  },
                  "destination": {
                    "type": "string",
                    "maxLength": 120,
                    "description": "Destination idea; omit if undecided."
                  },
                  "departureAirport": {
                    "type": "string",
                    "maxLength": 80,
                    "description": "Departure airport or city supplied by the traveler."
                  },
                  "notes": {
                    "type": "string",
                    "maxLength": 1200,
                    "description": "Trip dates, traveler/room configuration, priorities, and other nonsensitive details confirmed by the traveler."
                  },
                  "conciergeContext": {
                    "type": "string",
                    "maxLength": 1200,
                    "description": "Optional short traveler-approved conversation summary. Appended to notes; combined stored notes are limited to 1,200 characters, with notes first."
                  },
                  "referrerName": {
                    "type": "string",
                    "maxLength": 100,
                    "description": "Optional referral name supplied by the traveler."
                  },
                  "offer": {
                    "type": "string",
                    "maxLength": 120,
                    "description": "Optional real site offer identifier; do not invent a promotion or price."
                  },
                  "sessionId": {
                    "type": "string",
                    "maxLength": 80,
                    "description": "Optional session identifier. Omission creates a UUID. This is not an idempotency key."
                  },
                  "source": {
                    "type": "string",
                    "maxLength": 100,
                    "description": "Optional source label, such as assistant. Omission or empty text becomes direct."
                  },
                  "utmSource": {
                    "type": "string",
                    "maxLength": 120,
                    "description": "Optional known campaign source."
                  },
                  "utmMedium": {
                    "type": "string",
                    "maxLength": 120,
                    "description": "Optional known campaign medium."
                  },
                  "utmCampaign": {
                    "type": "string",
                    "maxLength": 160,
                    "description": "Optional known campaign name."
                  },
                  "utmContent": {
                    "type": "string",
                    "maxLength": 160,
                    "description": "Optional known campaign content identifier."
                  },
                  "referrer": {
                    "type": "string",
                    "maxLength": 500,
                    "description": "Optional actual referring page URL. Do not invent attribution."
                  }
                }
              },
              "example": {
                "tripType": "cruise",
                "timing": "exploring",
                "travelers": "2",
                "budget": "3000-5000",
                "firstName": "Example Traveler",
                "email": "traveler@example.com",
                "consent": true,
                "marketingConsent": false,
                "contactPreference": "email",
                "source": "assistant",
                "notes": "Example only. Replace with the traveler's confirmed trip details before submitting."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Unexpected non-created response. Do not interpret this as a stored inquiry; only 201 is documented creation success. Do not retry automatically.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "leadId",
                    "emailSent"
                  ],
                  "additionalProperties": false,
                  "properties": {
                    "leadId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "emailSent": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "201": {
            "description": "Inquiry stored. Returns leadId and emailSent. emailSent=true means the email service accepted the traveler snapshot, not that it reached the inbox. Advisor notifications run separately and are not confirmed by this flag.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "leadId",
                    "emailSent"
                  ],
                  "additionalProperties": false,
                  "properties": {
                    "leadId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "emailSent": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "The request was not valid. Malformed JSON, a non-object JSON body, or a body over 16,384 UTF-8 bytes.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Invalid request origin. A supplied Origin header has an invalid or different hostname.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Please complete the required trip and contact fields. Missing or invalid required fields, option values, email, or literal boolean consent=true.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "This request has already been received. Selena will follow up soon. At least three inquiries for this normalized email have been stored in the preceding ten minutes. This is a rate limit, not a lookup or idempotency guarantee.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong. Please try again. Persistence or other server processing failed. Some side effects may already have occurred; do not automatically retry.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
