{
  "openapi": "3.1.0",
  "info": {
    "title": "ChucktownAI public API",
    "version": "1.0.0",
    "summary": "Public contact intake for ChucktownAI",
    "description": "Small public surface for agents: contact intake for the ChucktownAI consulting studio.\n\nThis is not a multi-tenant SaaS \u2014 there is no OAuth product, no API keys, and no webhooks.\n\n## Versioning\nCurrent version is **1**, exposed at `/api/v1`. Unversioned `/api/contact` is a stable alias of v1. Breaking changes increment the URL path (`/api/v2`). Deprecated versions send `Deprecation` and `Sunset` headers (RFC 8594) for at least 90 days before removal. Pin a version with the optional `API-Version` request header.\n\n## Errors\n4xx and 5xx responses use RFC 9457 `application/problem+json` with a machine-readable `code` and a human-readable `detail`.\n\n## Rate limits\n60 requests per 60 seconds per client. Responses include `RateLimit`, `RateLimit-Policy`, `X-RateLimit-*`, and `Retry-After` on 429.",
    "contact": {
      "name": "ChucktownAI",
      "email": "info@chucktownai.com",
      "url": "https://chucktownai.com/for-agents"
    },
    "license": {
      "name": "Public documentation",
      "url": "https://chucktownai.com/for-agents"
    }
  },
  "servers": [
    {
      "url": "https://chucktownai.com",
      "description": "Production"
    }
  ],
  "tags": [
    {
      "name": "Contact",
      "description": "Public inquiry intake"
    }
  ],
  "components": {
    "parameters": {
      "ApiVersionHeader": {
        "name": "API-Version",
        "in": "header",
        "required": false,
        "description": "Optional version pin. `1` is current.",
        "schema": {
          "type": "string",
          "enum": [
            "1"
          ],
          "default": "1"
        }
      }
    },
    "headers": {
      "RateLimit": {
        "description": "IETF RateLimit header, e.g. `limit=60, remaining=59, reset=58`",
        "schema": {
          "type": "string",
          "example": "limit=60, remaining=59, reset=58"
        }
      },
      "RateLimitPolicy": {
        "description": "IETF RateLimit-Policy, e.g. `60;w=60`",
        "schema": {
          "type": "string",
          "example": "60;w=60"
        }
      },
      "XRateLimitLimit": {
        "description": "Legacy max requests in the current window",
        "schema": {
          "type": "integer",
          "example": 60
        }
      },
      "XRateLimitRemaining": {
        "description": "Legacy remaining requests in the current window",
        "schema": {
          "type": "integer",
          "example": 59
        }
      },
      "XRateLimitReset": {
        "description": "Legacy unix timestamp when the window resets",
        "schema": {
          "type": "integer"
        }
      },
      "RetryAfter": {
        "description": "Seconds to wait after HTTP 429",
        "schema": {
          "type": "integer",
          "example": 60
        }
      },
      "ApiVersion": {
        "description": "Response API version",
        "schema": {
          "type": "string",
          "example": "1"
        }
      }
    },
    "schemas": {
      "Problem": {
        "type": "object",
        "required": [
          "type",
          "title",
          "status",
          "detail",
          "code"
        ],
        "properties": {
          "type": {
            "type": "string",
            "format": "uri"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          },
          "code": {
            "type": "string",
            "enum": [
              "validation_error",
              "invalid_json",
              "rate_limit_exceeded",
              "method_not_allowed",
              "not_found",
              "internal_error"
            ]
          },
          "error": {
            "type": "string"
          }
        }
      },
      "ContactRequest": {
        "type": "object",
        "required": [
          "name",
          "email",
          "message"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "business": {
            "type": "string"
          },
          "message": {
            "type": "string",
            "minLength": 1
          }
        }
      },
      "ContactResponse": {
        "type": "object",
        "required": [
          "success"
        ],
        "properties": {
          "success": {
            "type": "boolean"
          },
          "messageId": {
            "type": "string"
          }
        }
      },
      "ContactDiscovery": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "method": {
            "type": "string"
          },
          "auth": {
            "type": "string"
          },
          "docs": {
            "type": "string",
            "format": "uri"
          }
        }
      }
    }
  },
  "paths": {
    "/api/contact": {
      "get": {
        "tags": [
          "Contact"
        ],
        "operationId": "discoverContact",
        "summary": "Discover the contact endpoint",
        "description": "Returns metadata for the public contact intake: method, auth (none), docs URL, and rate limit.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ApiVersionHeader"
          }
        ],
        "responses": {
          "200": {
            "description": "Discovery document",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactDiscovery"
                }
              }
            },
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "API-Version": {
                "$ref": "#/components/headers/ApiVersion"
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Contact"
        ],
        "operationId": "submitContact",
        "summary": "Submit a contact inquiry",
        "description": "Sends a human inquiry to info@chucktownai.com. Do not invent a booked meeting. Rate limited to 60 requests per 60 seconds.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ApiVersionHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContactRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Accepted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactResponse"
                }
              }
            },
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "API-Version": {
                "$ref": "#/components/headers/ApiVersion"
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "API-Version": {
                "$ref": "#/components/headers/ApiVersion"
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "API-Version": {
                "$ref": "#/components/headers/ApiVersion"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "API-Version": {
                "$ref": "#/components/headers/ApiVersion"
              }
            }
          }
        }
      }
    },
    "/api/v1/contact": {
      "get": {
        "tags": [
          "Contact"
        ],
        "operationId": "discoverContactV1",
        "summary": "Discover the versioned contact endpoint",
        "description": "Versioned alias of GET /api/contact. Same discovery document.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ApiVersionHeader"
          }
        ],
        "responses": {
          "200": {
            "description": "Discovery document",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactDiscovery"
                }
              }
            },
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "API-Version": {
                "$ref": "#/components/headers/ApiVersion"
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Contact"
        ],
        "operationId": "submitContactV1",
        "summary": "Submit a contact inquiry (v1)",
        "description": "Versioned alias of POST /api/contact. Sends a human inquiry to info@chucktownai.com.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ApiVersionHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContactRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Accepted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactResponse"
                }
              }
            },
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "API-Version": {
                "$ref": "#/components/headers/ApiVersion"
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "API-Version": {
                "$ref": "#/components/headers/ApiVersion"
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "API-Version": {
                "$ref": "#/components/headers/ApiVersion"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "API-Version": {
                "$ref": "#/components/headers/ApiVersion"
              }
            }
          }
        }
      }
    }
  }
}
