{
  "openapi": "3.1.0",
  "info": {
    "title": "We AI Anything repair requests API",
    "version": "1.0.0",
    "summary": "Read our services and prices, and send a Quick Fix website repair request on behalf of a customer.",
    "description": "For AI assistants and integrations acting for a customer. The €150 Quick Fix covers one agreed issue, capped at two hours of engineering work. An engineer reviews every request and confirms whether it fits before any work starts.\n\nHow a request is sent: check it with /fix-requests/prepare (nothing is saved or sent), show the customer the summary, then call prepare again with customer_confirmed_summary: true. We email the customer a 6-digit code, valid for 30 minutes. When the customer gives you the code, send it to /fix-requests/submit to get a reference number.\n\nNo API key is needed. The emailed code is the approval: it shows the customer saw the request and owns the email address. What a client says it is gets recorded but is never trusted.\n\nRules for assistants:\n- Ask the customer for every detail. Never guess or invent a value; list details they don't know in not_sure.\n- Never ask for or send passwords, logins, hosting credentials, API keys or payment-card details. If access is needed, an engineer arranges it securely.\n- Show the customer the summary and get their explicit approval before asking us to email them a code, and send the request only when they give you that code.\n- Nothing is accepted, scheduled or charged automatically. Do not promise a price, a fix or a completion date on our behalf.\n- We have not looked at the customer's website. Do not say that we have checked, tested or audited it.\n\nLimits: 3 codes per email address per day, 20 per network per hour, 5 tries per code, and a daily cap across the site. The same tools are available over MCP at https://weaianything.com/mcp.",
    "contact": {
      "name": "We AI Anything",
      "email": "info@weaianything.com",
      "url": "https://weaianything.com/ai/"
    },
    "termsOfService": "https://weaianything.com/terms/"
  },
  "servers": [
    {
      "url": "https://weaianything.com"
    }
  ],
  "externalDocs": {
    "description": "Guide for assistants and developers",
    "url": "https://weaianything.com/ai/"
  },
  "paths": {
    "/api/v1/services": {
      "get": {
        "operationId": "getServices",
        "summary": "Services and prices",
        "responses": {
          "200": {
            "description": "Our services, prices in euro and contact details.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Services"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/quick-fix": {
      "get": {
        "operationId": "getQuickFixRequirements",
        "summary": "What the Quick Fix covers, the details a request needs, and how sending works",
        "responses": {
          "200": {
            "description": "The Quick Fix rules and fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuickFix"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/fix-requests/prepare": {
      "post": {
        "operationId": "prepareFixRequest",
        "summary": "Check a request; once the customer confirms it, email them a code",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PrepareInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "needs_details (ask the customer the listed questions) or ready_for_review (show the customer the summary). Nothing saved or sent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Prepare"
                }
              }
            }
          },
          "201": {
            "description": "verification_sent: a draft is saved and the customer has been emailed a code.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Prepare"
                }
              }
            }
          },
          "400": {
            "description": "The body is not a JSON object.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Sent from a web page on another site.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body is too large.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many codes requested. The response gives a website link the customer can use instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Requests from assistants are switched off, or the email could not be sent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/fix-requests/submit": {
      "post": {
        "operationId": "submitFixRequest",
        "summary": "Send a draft with the code from the customer's email",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubmitInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Already sent. Returns the original reference number and status token.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Submit"
                }
              }
            }
          },
          "201": {
            "description": "Sent. Returns the reference number and a status token.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Submit"
                }
              }
            }
          },
          "400": {
            "description": "Missing approval, or a malformed draft_id or code.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such draft, or it has been deleted (after 24 hours).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "410": {
            "description": "The code has expired. Call prepare again.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Wrong code. The response says how many tries are left.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many attempts or requests.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Requests from assistants are switched off.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/fix-requests/{reference}": {
      "get": {
        "operationId": "getRequestStatus",
        "summary": "Progress of a request you sent",
        "security": [
          {
            "statusToken": []
          }
        ],
        "parameters": [
          {
            "name": "reference",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^WAA-[A-Z0-9]{6}$",
              "description": "The reference number, e.g. WAA-7K2M9Q."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The status. No personal details are returned.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Status"
                }
              }
            }
          },
          "404": {
            "description": "No request matches that reference and token.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "statusToken": {
        "type": "http",
        "scheme": "bearer",
        "description": "The status_token returned when the request was sent."
      }
    },
    "schemas": {
      "PrepareInput": {
        "type": "object",
        "properties": {
          "customer_email": {
            "type": "string",
            "description": "The customer's email address. We email them a confirmation code and reply there. (required)",
            "maxLength": 254,
            "format": "email"
          },
          "website_url": {
            "type": "string",
            "description": "The website's address, e.g. example.ie. Ask the customer; never guess it. (required)",
            "maxLength": 300
          },
          "problem": {
            "type": "string",
            "description": "What's going wrong, in the customer's words. (required)",
            "maxLength": 1000
          },
          "affected_area": {
            "type": "string",
            "description": "Which page or feature is affected. (recommended)",
            "maxLength": 1000
          },
          "expected_behaviour": {
            "type": "string",
            "description": "What the customer expected to happen instead. (recommended)",
            "maxLength": 1000
          },
          "devices": {
            "type": "string",
            "description": "Where it happens: mobile, desktop or both. (recommended)",
            "enum": [
              "mobile",
              "desktop",
              "both"
            ]
          },
          "steps_to_reproduce": {
            "type": "string",
            "description": "Steps that make it happen, if the customer knows them. (optional)",
            "maxLength": 1000
          },
          "frequency": {
            "type": "string",
            "description": "Whether it happens every time or only sometimes. (optional)",
            "enum": [
              "every-time",
              "sometimes"
            ]
          },
          "browser": {
            "type": "string",
            "description": "The browser or device, if the customer knows it. (optional)",
            "maxLength": 1000
          },
          "customer_first_name": {
            "type": "string",
            "description": "The customer's first name, if they want to give it. (optional)",
            "maxLength": 100
          },
          "business_name": {
            "type": "string",
            "description": "The business name, if they want to give it. (optional)",
            "maxLength": 120
          },
          "not_sure": {
            "type": "array",
            "description": "Recommended or optional details the customer said they don't know.",
            "items": {
              "type": "string",
              "enum": [
                "affected_area",
                "expected_behaviour",
                "devices",
                "steps_to_reproduce",
                "frequency",
                "browser",
                "business_name"
              ]
            },
            "uniqueItems": true
          },
          "customer_confirmed_summary": {
            "type": "boolean",
            "description": "Leave out or false to check the request and get a summary; nothing is saved or sent. Set true only after showing the customer that summary and hearing that it's correct: we then email them a 6-digit code."
          }
        },
        "additionalProperties": false
      },
      "SubmitInput": {
        "type": "object",
        "properties": {
          "draft_id": {
            "type": "string",
            "pattern": "^[a-f0-9]{32}$",
            "description": "The draft_id returned by prepare_fix_request."
          },
          "verification_code": {
            "type": "string",
            "pattern": "^[0-9]{6}$",
            "description": "The 6-digit code the customer received by email and gave you. Valid for 30 minutes."
          },
          "customer_approved": {
            "type": "boolean",
            "const": true,
            "description": "True only when the customer has asked you to send this request."
          }
        },
        "required": [
          "draft_id",
          "verification_code",
          "customer_approved"
        ],
        "additionalProperties": false
      },
      "Error": {
        "type": "object",
        "properties": {
          "ok": {
            "const": false
          },
          "error": {
            "type": "string",
            "description": "A machine-readable code, e.g. rate_limited."
          },
          "message": {
            "type": "string",
            "description": "What went wrong and what to do next, in plain English."
          }
        },
        "required": [
          "ok",
          "error",
          "message"
        ]
      },
      "Services": {
        "type": "object",
        "properties": {
          "business": {
            "type": "object"
          },
          "currency": {
            "const": "EUR"
          },
          "services": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "price": {
                  "type": "object",
                  "properties": {
                    "type": {
                      "enum": [
                        "fixed",
                        "from",
                        "quote"
                      ]
                    },
                    "amount": {
                      "type": "number"
                    },
                    "currency": {
                      "const": "EUR"
                    },
                    "display": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "display"
                  ]
                },
                "summary": {
                  "type": "string"
                },
                "examples": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "scope": {
                  "type": "string"
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                }
              },
              "required": [
                "id",
                "name",
                "price",
                "summary",
                "url"
              ]
            }
          }
        }
      },
      "QuickFix": {
        "type": "object",
        "properties": {
          "service": {
            "type": "string"
          },
          "price": {
            "type": "object"
          },
          "scope": {
            "type": "string"
          },
          "fields": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "process": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "rules": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "Prepare": {
        "type": "object",
        "properties": {
          "ok": {
            "const": true
          },
          "status": {
            "enum": [
              "needs_details",
              "ready_for_review",
              "verification_sent"
            ],
            "description": "needs_details: ask the customer the questions in missing or fix invalid. ready_for_review: show the customer the summary. verification_sent: ask the customer for the emailed code."
          },
          "missing": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "field": {
                  "type": "string"
                },
                "level": {
                  "type": "string"
                },
                "question": {
                  "type": "string"
                }
              }
            }
          },
          "invalid": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "field": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              }
            }
          },
          "summary": {
            "type": "object",
            "description": "The request as we would send it, field by field."
          },
          "summary_text": {
            "type": "string",
            "description": "The same summary as text, to show the customer."
          },
          "draft_id": {
            "type": "string"
          },
          "sent_to": {
            "type": "string",
            "description": "The email address the code went to, partly hidden."
          },
          "code_expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "next_step": {
            "type": "string"
          }
        },
        "required": [
          "ok",
          "status",
          "next_step"
        ]
      },
      "Submit": {
        "type": "object",
        "properties": {
          "ok": {
            "const": true
          },
          "status": {
            "const": "submitted"
          },
          "reference": {
            "type": "string"
          },
          "status_token": {
            "type": "string",
            "description": "Needed to check the status later. Not shown to us again."
          },
          "request_status": {
            "type": "string"
          },
          "duplicate": {
            "type": "boolean",
            "description": "True when this request was already sent; the original reference is returned."
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "ok",
          "status",
          "reference",
          "status_token",
          "message"
        ]
      },
      "Status": {
        "type": "object",
        "properties": {
          "ok": {
            "const": true
          },
          "reference": {
            "type": "string"
          },
          "status": {
            "enum": [
              "received",
              "in_review",
              "scope_sent",
              "closed"
            ]
          },
          "status_label": {
            "type": "string"
          },
          "submitted_at": {
            "type": "string",
            "format": "date-time"
          },
          "next_step": {
            "type": "string"
          }
        },
        "required": [
          "ok",
          "reference",
          "status",
          "status_label",
          "submitted_at"
        ]
      }
    }
  }
}