{
  "openapi": "3.1.0",
  "info": {
    "title": "Climb Site API",
    "version": "1.0.0",
    "description": "Public form endpoints for the climb.ai marketing site. Both accept HTML form encodings (multipart/form-data or application/x-www-form-urlencoded). For an agent-callable JSON interface, use the MCP server at https://climb.ai/mcp (see /.well-known/mcp/server-card.json)."
  },
  "servers": [{ "url": "https://climb.ai" }],
  "paths": {
    "/api/contact": {
      "post": {
        "operationId": "submitContact",
        "summary": "Submit a contact / discovery-call request",
        "description": "Sends a message to the Climb team. Responds with an HTTP 303 redirect back to the contact page (?sent=1 on success, ?error=... on failure), which is how the browser form is wired.",
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": { "$ref": "#/components/schemas/ContactForm" }
            },
            "multipart/form-data": {
              "schema": { "$ref": "#/components/schemas/ContactForm" }
            }
          }
        },
        "responses": {
          "303": {
            "description": "Redirect to /contact?sent=1 on success or /contact?error=<reason> on validation/send failure.",
            "headers": {
              "Location": { "schema": { "type": "string" } }
            }
          }
        }
      }
    },
    "/api/newsletter": {
      "post": {
        "operationId": "subscribeNewsletter",
        "summary": "Subscribe to the Climb newsletter",
        "description": "Adds the email to Climb's newsletter (proxied to HubSpot). Responds with JSON.",
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": { "$ref": "#/components/schemas/NewsletterForm" }
            },
            "multipart/form-data": {
              "schema": { "$ref": "#/components/schemas/NewsletterForm" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Subscribed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": { "ok": { "type": "boolean", "const": true } }
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid email.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": { "type": "boolean", "const": false },
                    "reason": {
                      "type": "string",
                      "enum": ["missing_email", "invalid_email"]
                    }
                  }
                }
              }
            }
          },
          "502": { "description": "Upstream subscription provider failed." },
          "503": { "description": "Subscription provider not configured." }
        }
      }
    },
    "/api/hls-signup": {
      "post": {
        "operationId": "requestHlsMcpAccess",
        "summary": "Register for Climb Labs MCP Service for HLS access",
        "description": "Registers a person for the Climb Labs MCP Service for HLS (ten biomedical/regulatory data sources for Databricks agents). On success, a bearer token and connection details are issued out of band to the submitted email — this endpoint never returns the token. Requires a corporate email (free-mail domains are rejected) and a Cloudflare Turnstile token, so unattended agents cannot call it directly; a human completes the form at https://climb.ai/labs/hls-mcp. Rate limited per IP.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/HlsSignupForm" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Registered. Token and Databricks Marketplace connection details follow by email.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": { "ok": { "type": "boolean", "const": true } }
                }
              }
            }
          },
          "400": {
            "description": "Missing/invalid fields, free-mail domain, or rejected by the signup service (e.g. already registered). `message` carries the human-readable reason when present.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": { "type": "boolean", "const": false },
                    "reason": {
                      "type": "string",
                      "enum": [
                        "bad_request",
                        "missing_fields",
                        "invalid_email",
                        "free_email",
                        "rejected"
                      ]
                    },
                    "message": { "type": "string" }
                  }
                }
              }
            }
          },
          "403": { "description": "Turnstile verification failed." },
          "429": { "description": "Rate limited; retry later." },
          "502": { "description": "Upstream signup service failed." },
          "503": { "description": "Turnstile verification unavailable." }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ContactForm": {
        "type": "object",
        "required": ["name", "email"],
        "properties": {
          "name": { "type": "string", "description": "Sender's name." },
          "email": {
            "type": "string",
            "format": "email",
            "description": "Sender's email; used as reply-to."
          },
          "company": {
            "type": "string",
            "description": "Company name (optional)."
          },
          "jobTitle": {
            "type": "string",
            "description": "Sender's role (optional)."
          },
          "startTimeline": {
            "type": "string",
            "description": "Desired start timeline (optional)."
          },
          "message": {
            "type": "string",
            "description": "Brief context on the AI system they want to ship (optional)."
          }
        }
      },
      "NewsletterForm": {
        "type": "object",
        "required": ["email"],
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "description": "Email to subscribe."
          }
        }
      },
      "HlsSignupForm": {
        "type": "object",
        "required": [
          "email",
          "first_name",
          "last_name",
          "organization",
          "cf-turnstile-response"
        ],
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "description": "Corporate email; the bearer token is delivered here. Free-mail domains are rejected."
          },
          "first_name": { "type": "string" },
          "last_name": { "type": "string" },
          "organization": { "type": "string", "description": "Company name." },
          "cf-turnstile-response": {
            "type": "string",
            "description": "Cloudflare Turnstile token from the browser widget."
          }
        }
      }
    }
  }
}
