{
  "openapi": "3.0.3",
  "info": {
    "title": "Heartland Vendor Finder",
    "version": "1.1.0"
  },
  "servers": [
    {
      "url": "https://heartland-vendor-finder.vercel.app"
    }
  ],
  "paths": {
    "/api/vendors": {
      "get": {
        "operationId": "findVendors",
        "summary": "Search public vendor listings, eight per page",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Search words, maximum 200 characters"
          },
          {
            "name": "city",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "City name"
          },
          {
            "name": "county",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "County name"
          },
          {
            "name": "subject",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "music",
                "physical",
                "academics",
                "arts",
                "stem",
                "outdoors",
                "programs",
                "life"
              ]
            },
            "description": "Category ID from /api/catalog"
          },
          {
            "name": "activity",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "piano",
                "guitar",
                "voice",
                "strings",
                "drums",
                "ukulele",
                "winds",
                "music-other",
                "pe",
                "gymnastics",
                "martial-arts",
                "swimming",
                "soccer",
                "baseball",
                "basketball",
                "golf",
                "tennis",
                "ninja",
                "yoga",
                "cheer",
                "skating",
                "surfing",
                "climbing",
                "volleyball",
                "fencing",
                "sports-other",
                "math",
                "reading",
                "writing",
                "academic-science",
                "history",
                "test-prep",
                "general-tutoring",
                "dance",
                "theater",
                "art",
                "ceramics",
                "sewing",
                "photography",
                "crafts",
                "arts-other",
                "coding",
                "robotics",
                "science",
                "engineering",
                "technology",
                "horses",
                "nature",
                "farms",
                "animals",
                "outdoors-other",
                "homeschool",
                "spanish",
                "french",
                "asl",
                "languages",
                "cooking",
                "driving",
                "chess",
                "life-other"
              ]
            },
            "description": "Activity ID from /api/catalog"
          },
          {
            "name": "delivery",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "in-person",
                "online",
                "both"
              ]
            },
            "description": "in-person: local In-person/Hybrid. online: Virtual/Hybrid across all areas. both: local in-person plus online across all areas. Confirm each activity delivery."
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            },
            "description": "Positive integer, default 1"
          }
        ],
        "responses": {
          "200": {
            "description": "total, page, pages, pageSize, next URL and results",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "sourceUpdatedAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "attribution": {
                      "type": "string"
                    },
                    "total": {
                      "type": "integer"
                    },
                    "page": {
                      "type": "integer"
                    },
                    "pages": {
                      "type": "integer"
                    },
                    "pageSize": {
                      "type": "integer",
                      "enum": [
                        8
                      ]
                    },
                    "next": {
                      "type": "string",
                      "nullable": true
                    },
                    "results": {
                      "type": "array",
                      "maxItems": 8,
                      "items": {
                        "$ref": "#/components/schemas/Vendor"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid search parameter",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "description": "Read-only public directory. Unknown/repeated parameters, invalid geography, incompatible subject/activity and out-of-range pages return 400. Follow next until null. City/county are case insensitive; taxonomy and delivery use exact lowercase IDs."
      }
    },
    "/api/catalog": {
      "get": {
        "operationId": "getCategories",
        "responses": {
          "200": {
            "description": "Category and activity IDs",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "groups": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "hint": {
                            "type": "string"
                          },
                          "icon": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "activities": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "group": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Vendor": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "contact": {
            "type": "string"
          },
          "summary": {
            "type": "string"
          },
          "aliases": {
            "type": "string"
          },
          "location": {
            "type": "string"
          },
          "services": {
            "type": "string"
          },
          "phone": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "website": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "source": {
            "type": "string"
          },
          "groups": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "activities": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "cities": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "counties": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "statewide": {
            "type": "boolean"
          },
          "featured": {
            "type": "boolean"
          },
          "delivery": {
            "type": "string",
            "enum": [
              "In-person",
              "Virtual",
              "Hybrid"
            ]
          },
          "offeringRules": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true
          }
        },
        "required": [
          "id",
          "name",
          "contact",
          "summary",
          "aliases",
          "location",
          "services",
          "phone",
          "email",
          "website",
          "url",
          "source",
          "groups",
          "activities",
          "cities",
          "counties",
          "statewide",
          "featured",
          "delivery",
          "offeringRules"
        ]
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          }
        },
        "required": [
          "error"
        ]
      }
    }
  }
}
