{
  "openapi": "3.1.0",
  "info": {
    "title": "AIpplied Labs API",
    "version": "1.0.0",
    "summary": "Ask AIpplied Labs a question, or match a business to the systems that fit it.",
    "description": "Public endpoints behind www.aippliedlabs.com. Every answer is selected from the company's own written copy by a decision model; nothing is generated. No key is required. An optional anonymous bearer token gives an agent its own rate limit: see https://www.aippliedlabs.com/auth.md.",
    "contact": {
      "name": "AIpplied Labs",
      "url": "https://www.aippliedlabs.com/#start"
    }
  },
  "servers": [
    {
      "url": "https://www.aippliedlabs.com"
    }
  ],
  "externalDocs": {
    "url": "https://www.aippliedlabs.com/docs/api"
  },
  "security": [
    {},
    {
      "agentToken": []
    }
  ],
  "paths": {
    "/api/ask": {
      "post": {
        "operationId": "ask",
        "summary": "Answer a question about AIpplied Labs",
        "description": "Returns the company's own written answer to a question about its services, pricing, process, timelines, data handling, or ownership. Off-topic or hostile questions get a written fallback with matched=false.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "question"
                ],
                "properties": {
                  "question": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 280
                  }
                }
              },
              "example": {
                "question": "How long does a build take?"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "An answer",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "question": {
                      "type": "string"
                    },
                    "matched": {
                      "type": "boolean",
                      "description": "True when a written answer fits the question."
                    },
                    "paragraphs": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "blocks": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "IDs of the written answers used."
                    },
                    "meta": {
                      "type": [
                        "object",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing or malformed question",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited: 12 questions per minute per IP or per agent token",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/check": {
      "post": {
        "operationId": "checkWeek",
        "summary": "Find the first systems for a business",
        "description": "The 'Where does your week go?' check. Returns up to three of the eight systems that fit what the owner described. An empty list means nothing clearly fits.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "business",
                  "team"
                ],
                "properties": {
                  "business": {
                    "type": "string",
                    "enum": [
                      "trades",
                      "pro",
                      "retail",
                      "health",
                      "nonprofit",
                      "other"
                    ],
                    "description": "trades: Home services and trades; pro: Professional services; retail: Retail and food; health: Health and wellness; nonprofit: Nonprofit; other: Something else"
                  },
                  "team": {
                    "type": "string",
                    "enum": [
                      "1",
                      "2-5",
                      "6-20",
                      "21-50"
                    ]
                  },
                  "text": {
                    "type": "string",
                    "maxLength": 400,
                    "description": "In a sentence, what eats the owner's week. Either text or at least one tick is required."
                  },
                  "ticks": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "slow-reply",
                        "quotes-sit",
                        "messy-start",
                        "drift",
                        "same-questions",
                        "job-status",
                        "find-docs",
                        "reports"
                      ]
                    }
                  },
                  "hours": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 40
                  }
                }
              },
              "example": {
                "business": "trades",
                "team": "2-5",
                "text": "Chasing quotes on Sundays",
                "ticks": [
                  "quotes-sit"
                ],
                "hours": 6
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A plan",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "systems": {
                      "type": "array",
                      "maxItems": 3,
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "said": {
                            "type": "string",
                            "description": "Why it was picked, in the owner's words."
                          },
                          "get": {
                            "type": "string"
                          },
                          "live": {
                            "type": "string"
                          },
                          "price": {
                            "type": "array",
                            "description": "Fixed-fee range in US dollars, [low, high]. Equal values mean a single fixed price.",
                            "items": {
                              "type": "integer"
                            },
                            "minItems": 2,
                            "maxItems": 2
                          }
                        }
                      }
                    },
                    "hours": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "business": {
                      "type": "string"
                    },
                    "team": {
                      "type": "string"
                    },
                    "meta": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing answers",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited: 8 checks per minute per IP or per agent token",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/health": {
      "get": {
        "operationId": "health",
        "summary": "Health check",
        "security": [],
        "responses": {
          "200": {
            "description": "Up",
            "content": {
              "application/health+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "const": "ok"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "agentToken": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "Optional anonymous agent token from POST /agent/identity then POST /oauth2/token. See https://www.aippliedlabs.com/auth.md."
      }
    }
  }
}
