{
  "openapi": "3.1.0",
  "info": {
    "title": "Akkrev agent API",
    "version": "1.2.0",
    "description": "Public venue signup and website tools. Saving venue details does not create an active account. The person must choose a plan and billing period, approve Stripe checkout, verify their email and complete the venue profile. Contact details should be submitted only for a requested action.",
    "contact": {
      "email": "hello@akkrev.com",
      "url": "https://akkrev.com"
    }
  },
  "servers": [
    {
      "url": "https://akkrev.com"
    }
  ],
  "externalDocs": {
    "description": "Agent guide, signup steps and examples",
    "url": "https://akkrev.com/agents/"
  },
  "security": [],
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "ok"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": false
          },
          "error": {
            "type": "string"
          }
        }
      }
    }
  },
  "paths": {
    "/api/signup": {
      "post": {
        "operationId": "start_signup",
        "summary": "Start signing up a hotel, restaurant, café or bar for AI visibility tracking",
        "description": "Saving venue details does not create an active account. The person must choose a plan and billing period, approve Stripe checkout, verify their email and complete the venue profile. Success returns next with available monthly and annual checkout choices, preserving the signup reference. Try your chosen plan free for seven days. Card required. Cancel before the trial ends to avoid the first charge. Your selected monthly or annual plan starts automatically after the trial. Use a server-side HTTP client or the same-origin browser form. Cross-origin browser requests are not supported.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "website",
                  "venue",
                  "email"
                ],
                "properties": {
                  "website": {
                    "type": "string",
                    "format": "uri",
                    "maxLength": 200
                  },
                  "venue": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "maxLength": 200
                  },
                  "name": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "type": {
                    "type": "string",
                    "enum": [
                      "hotel",
                      "restaurant",
                      "cafe",
                      "other"
                    ]
                  }
                }
              },
              "example": {
                "website": "https://example.com",
                "venue": "Example Hotel",
                "type": "hotel",
                "name": "Example Owner",
                "email": "owner@example.com"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Venue details saved, not an active account. Present next.plans checkout choices for the person's approval.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "id"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "const": true
                    },
                    "id": {
                      "type": "string"
                    },
                    "next": {
                      "type": "object",
                      "required": [
                        "requiresUserApproval",
                        "notice",
                        "pricingUrl",
                        "plans"
                      ],
                      "properties": {
                        "requiresUserApproval": {
                          "type": "boolean",
                          "const": true
                        },
                        "notice": {
                          "type": "string"
                        },
                        "pricingUrl": {
                          "type": "string",
                          "format": "uri"
                        },
                        "plans": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "required": [
                              "id",
                              "name",
                              "checkoutOptions"
                            ],
                            "properties": {
                              "id": {
                                "type": "string",
                                "enum": [
                                  "track",
                                  "grow",
                                  "done-for-you"
                                ]
                              },
                              "name": {
                                "type": "string",
                                "description": "Public plan label; done-for-you is displayed as Scale."
                              },
                              "checkoutOptions": {
                                "type": "array",
                                "items": {
                                  "type": "object",
                                  "required": [
                                    "interval",
                                    "url"
                                  ],
                                  "properties": {
                                    "interval": {
                                      "type": "string",
                                      "enum": [
                                        "month",
                                        "year"
                                      ]
                                    },
                                    "url": {
                                      "type": "string",
                                      "format": "uri",
                                      "description": "Give the chosen returned URL to the person. It preserves their signup reference; visiting does not approve checkout."
                                    }
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Unreadable or oversized request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Cross-origin browser request rejected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Missing or invalid fields; JSON error explains what to correct.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many signup requests. Do not retry repeatedly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Details could not be saved. Avoid blindly duplicating an uncertain submission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Signup storage is unavailable; contact Akkrev.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/site-info": {
      "get": {
        "operationId": "guess_venue_details",
        "summary": "Guess a venue's name, town and type from its website",
        "parameters": [
          {
            "name": "url",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri",
              "example": "https://example.com"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Suggested venue details; confirm with the owner.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "website",
                    "name",
                    "guessed"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "const": true
                    },
                    "website": {
                      "type": "string",
                      "format": "uri"
                    },
                    "name": {
                      "type": "string"
                    },
                    "area": {
                      "type": "string"
                    },
                    "type": {
                      "type": "string",
                      "enum": [
                        "hotel",
                        "restaurant",
                        "cafe",
                        "other"
                      ]
                    },
                    "guessed": {
                      "type": "string",
                      "enum": [
                        "domain",
                        "structured data",
                        "page"
                      ],
                      "description": "How the suggestion was inferred; confirm it with the venue owner."
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Invalid public website address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit reached.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/report": {
      "post": {
        "operationId": "report_website_agents_cant_use",
        "summary": "Report a website AI agents can't use",
        "description": "Report a website where an AI agent could not complete a task, such as booking, reserving, buying, paying, signing up or sending an enquiry. Akkrev logs the report and contacts the business to help fix the website for AI agents. Free, no account needed. Do not include payment card numbers, passwords or other people's personal details.",
        "parameters": [
          {
            "name": "Accept",
            "in": "header",
            "required": false,
            "description": "Send application/json for the machine-readable response. Browser form submissions can redirect instead.",
            "schema": {
              "type": "string",
              "default": "application/json"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "website",
                  "task",
                  "reason"
                ],
                "properties": {
                  "website": {
                    "type": "string",
                    "description": "Website that didn't work. The page where the agent got stuck, starting with https://",
                    "maxLength": 500,
                    "format": "uri",
                    "example": "https://www.examplehotel.co.uk/rooms"
                  },
                  "task": {
                    "type": "string",
                    "description": "What were you trying to do?. For example: book a double room for 2 nights from 14 November.",
                    "maxLength": 500,
                    "example": "Book a double room for 2 nights from 14 November for 2 adults"
                  },
                  "reason": {
                    "type": "string",
                    "description": "Where did it go wrong?. Pick the closest one.",
                    "maxLength": 20,
                    "enum": [
                      "blocked",
                      "widget",
                      "not-found",
                      "login",
                      "popup",
                      "payment",
                      "info",
                      "broken",
                      "other"
                    ],
                    "example": "widget"
                  },
                  "details": {
                    "type": "string",
                    "description": "What happened (optional). Error messages, the step that failed, anything that helps us reproduce it.",
                    "maxLength": 2000,
                    "example": "The date picker opened in an iframe and ignored clicks, so no rooms or prices appeared."
                  },
                  "agent": {
                    "type": "string",
                    "description": "Which AI agent or tool (optional). For example: ChatGPT agent, Claude, Gemini, Perplexity, Muse, your own agent.",
                    "maxLength": 100,
                    "example": "ChatGPT agent"
                  },
                  "email": {
                    "type": "string",
                    "description": "Your email (optional). Only if you want us to tell you when it's fixed.",
                    "maxLength": 200,
                    "format": "email"
                  }
                }
              },
              "example": {
                "website": "https://example.com/book",
                "task": "Find a room for two adults; stop before reservation or payment.",
                "reason": "widget",
                "details": "Fictional example: the date picker did not respond."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Requested report received.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "id",
                    "host",
                    "message",
                    "tellYourUser"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "const": true
                    },
                    "id": {
                      "type": "string"
                    },
                    "host": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    },
                    "tellYourUser": {
                      "type": "string",
                      "description": "Confirmation to pass to the person after a successful requested report."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Unreadable request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "A field is missing or invalid; read error before correcting it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many reports from this address this hour.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Could not save the report; avoid duplicate submissions after an uncertain outcome.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Reporting is unavailable; contact Akkrev.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/check": {
      "post": {
        "operationId": "request_free_ai_check",
        "summary": "Request a free agent check for a hotel",
        "description": "Akkrev checks what AI assistants say about the hotel and whether an agent can book it, and emails the result. Send Accept: application/json to get a JSON reply.",
        "parameters": [
          {
            "name": "Accept",
            "in": "header",
            "required": false,
            "description": "Send application/json for the machine-readable response. Browser form submissions can redirect instead.",
            "schema": {
              "type": "string",
              "default": "application/json"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "hotel",
                  "website",
                  "name",
                  "email"
                ],
                "properties": {
                  "hotel": {
                    "type": "string",
                    "description": "Hotel name",
                    "maxLength": 200
                  },
                  "website": {
                    "type": "string",
                    "format": "uri",
                    "description": "Hotel website",
                    "maxLength": 200
                  },
                  "name": {
                    "type": "string",
                    "description": "Contact name",
                    "maxLength": 200
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "description": "Contact email",
                    "maxLength": 200
                  },
                  "phone": {
                    "type": "string",
                    "description": "Phone (optional)",
                    "maxLength": 25
                  }
                }
              },
              "example": {
                "hotel": "Example Hotel",
                "website": "https://example.com",
                "name": "Example Owner",
                "email": "owner@example.com"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Requested hotel check received; the later email is a separate step.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "const": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Unreadable form.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "A field is missing or invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Could not save the request; avoid blind retries.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "The request form is unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/crawler-check": {
      "get": {
        "operationId": "check_ai_crawler_access",
        "summary": "Free AI crawler check",
        "description": "Check your website's AI crawler rules, homepage access and llms.txt status. Free for hotels, restaurants and cafés. No signup required. Reports findings only. Results in a few seconds.",
        "parameters": [
          {
            "name": "url",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri",
              "example": "https://example.com"
            },
            "description": "Public website to check"
          }
        ],
        "responses": {
          "200": {
            "description": "Access findings for the supplied url; these are not a visibility or booking score.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "url",
                    "checkedAt",
                    "robots",
                    "bots",
                    "homepage",
                    "llmsTxt",
                    "summary"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "const": true
                    },
                    "url": {
                      "type": "string",
                      "format": "uri"
                    },
                    "checkedAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "robots": {
                      "type": "object",
                      "required": [
                        "url",
                        "status",
                        "found",
                        "note"
                      ],
                      "properties": {
                        "url": {
                          "type": "string",
                          "format": "uri"
                        },
                        "status": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "found": {
                          "type": "boolean"
                        },
                        "note": {
                          "type": "string"
                        }
                      }
                    },
                    "bots": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "token",
                          "operator",
                          "role",
                          "what",
                          "allowed",
                          "rule"
                        ],
                        "properties": {
                          "token": {
                            "type": "string"
                          },
                          "operator": {
                            "type": "string"
                          },
                          "role": {
                            "type": "string",
                            "enum": [
                              "Training",
                              "Search",
                              "User-triggered",
                              "Search engine"
                            ]
                          },
                          "what": {
                            "type": "string"
                          },
                          "allowed": {
                            "type": "boolean"
                          },
                          "rule": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        }
                      }
                    },
                    "homepage": {
                      "type": "object",
                      "required": [
                        "status",
                        "finalUrl",
                        "challenge",
                        "xRobotsTag",
                        "metaRobots",
                        "note"
                      ],
                      "properties": {
                        "status": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "finalUrl": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "challenge": {
                          "type": "boolean"
                        },
                        "xRobotsTag": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "metaRobots": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "note": {
                          "type": "string"
                        }
                      }
                    },
                    "llmsTxt": {
                      "type": "object",
                      "required": [
                        "url",
                        "found"
                      ],
                      "properties": {
                        "url": {
                          "type": "string",
                          "format": "uri"
                        },
                        "found": {
                          "type": "boolean"
                        }
                      }
                    },
                    "summary": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Not a public website address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many checks from this address this hour.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  }
}