{
  "openapi": "3.1.0",
  "info": {
    "title": "Twin Agent API",
    "version": "1.0.0",
    "description": "REST interface to Twin profiles for AI agents and integrations. Every endpoint mirrors an MCP tool (MCP endpoint: https://twin.aiapps.fyi/api/mcp). Authenticate with `Authorization: Bearer <api key>`. Read endpoints work without a key (read-only, rate-limited). Scopes: profile:read, profile:ask, booking:create, payment:request, lead:submit, profile:draft, profile:edit, docs:write, leads:read, publish:request. Agents can never publish or move money directly: those create approvals for the human owner."
  },
  "servers": [
    {
      "url": "https://twin.aiapps.fyi"
    }
  ],
  "tags": [
    {
      "name": "Profiles"
    },
    {
      "name": "Visitor tools"
    },
    {
      "name": "Admin tools"
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key created in Dashboard → Agents & API"
      }
    },
    "responses": {
      "Error": {
        "description": "Error",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  },
  "paths": {
    "/api/v1/profiles": {
      "get": {
        "operationId": "searchProfiles",
        "tags": [
          "Profiles"
        ],
        "summary": "Search published profiles",
        "security": [
          {},
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "city",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "language",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Results"
          }
        }
      }
    },
    "/api/v1/profiles/{handle}": {
      "get": {
        "operationId": "getProfile",
        "tags": [
          "Profiles"
        ],
        "summary": "Structured profile (services, prices, hours, links)",
        "security": [
          {},
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "handle",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "amelia-physio"
          }
        ],
        "responses": {
          "200": {
            "description": "Profile"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/profiles/{handle}/ask": {
      "post": {
        "operationId": "askProfile",
        "tags": [
          "Profiles"
        ],
        "summary": "Grounded answer with sources and confidence",
        "security": [
          {},
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "handle",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "amelia-physio"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "question"
                ],
                "properties": {
                  "question": {
                    "type": "string"
                  },
                  "conversation_id": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Answer"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/profiles/{handle}/availability": {
      "get": {
        "operationId": "checkAvailability",
        "tags": [
          "Profiles"
        ],
        "summary": "Open slots",
        "security": [
          {},
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "handle",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "amelia-physio"
          },
          {
            "name": "service_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Slots"
          }
        }
      }
    },
    "/api/v1/profiles/{handle}/bookings": {
      "post": {
        "operationId": "createBooking",
        "tags": [
          "Profiles"
        ],
        "summary": "Request a booking (scope booking:create)",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "handle",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "amelia-physio"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "handle": {
                    "type": "string"
                  },
                  "service_id": {
                    "type": "string"
                  },
                  "slot": {
                    "type": "string",
                    "description": "ISO 8601 start time"
                  },
                  "contact": {
                    "type": "object",
                    "properties": {
                      "name": {
                        "type": "string"
                      },
                      "email": {
                        "type": "string"
                      },
                      "phone": {
                        "type": "string"
                      }
                    },
                    "additionalProperties": false,
                    "description": "At least an email or phone"
                  },
                  "note": {
                    "type": "string"
                  }
                },
                "required": [
                  "handle",
                  "service_id",
                  "slot",
                  "contact"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Booking (pending_human)"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/profiles/{handle}/leads": {
      "post": {
        "operationId": "submitLead",
        "tags": [
          "Profiles"
        ],
        "summary": "Submit a lead (scope lead:submit)",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "handle",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "amelia-physio"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "handle": {
                    "type": "string"
                  },
                  "contact": {
                    "type": "object",
                    "properties": {
                      "name": {
                        "type": "string"
                      },
                      "email": {
                        "type": "string"
                      },
                      "phone": {
                        "type": "string"
                      }
                    },
                    "additionalProperties": false,
                    "description": "At least an email or phone"
                  },
                  "note": {
                    "type": "string",
                    "maxLength": 2000
                  }
                },
                "required": [
                  "handle",
                  "contact"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Lead"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/profiles/{handle}/payment-links": {
      "post": {
        "operationId": "requestPaymentLink",
        "tags": [
          "Profiles"
        ],
        "summary": "Request a payment link (scope payment:request; needs owner approval for agents)",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "handle",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "amelia-physio"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "handle": {
                    "type": "string"
                  },
                  "service_id": {
                    "type": "string"
                  },
                  "contact": {
                    "type": "object",
                    "properties": {
                      "name": {
                        "type": "string"
                      },
                      "email": {
                        "type": "string"
                      },
                      "phone": {
                        "type": "string"
                      }
                    },
                    "additionalProperties": false,
                    "description": "At least an email or phone"
                  }
                },
                "required": [
                  "handle",
                  "service_id",
                  "contact"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Payment request"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/tools/search_profiles": {
      "post": {
        "operationId": "tool_search_profiles",
        "summary": "Search profiles",
        "description": "Search the public directory of published profiles (professionals and businesses). Filter by city, category, language (ISO code, e.g. 'de').\n\nRequired scope: `profile:read`. Same contract as the MCP tool `search_profiles`.",
        "tags": [
          "Visitor tools"
        ],
        "security": [
          {},
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "query": {
                    "description": "Free text, e.g. 'sports physio running injuries'",
                    "type": "string"
                  },
                  "city": {
                    "type": "string"
                  },
                  "category": {
                    "type": "string"
                  },
                  "language": {
                    "type": "string"
                  },
                  "limit": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 50
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/tools/get_profile": {
      "post": {
        "operationId": "tool_get_profile",
        "summary": "Get profile",
        "description": "Structured public data for one profile: services with prices and durations, hours, location, languages, links.\n\nRequired scope: `profile:read`. Same contract as the MCP tool `get_profile`.",
        "tags": [
          "Visitor tools"
        ],
        "security": [
          {},
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "handle": {
                    "type": "string",
                    "description": "Profile handle, e.g. 'amelia-physio'"
                  }
                },
                "required": [
                  "handle"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/tools/ask_profile": {
      "post": {
        "operationId": "tool_ask_profile",
        "summary": "Ask a profile",
        "description": "Ask a question; returns an answer grounded ONLY in the profile's published documents, with sources and a confidence score. Low confidence means the profile does not say.\n\nRequired scope: `profile:ask`. Same contract as the MCP tool `ask_profile`.",
        "tags": [
          "Visitor tools"
        ],
        "security": [
          {},
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "handle": {
                    "type": "string"
                  },
                  "question": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 2000
                  },
                  "conversation_id": {
                    "description": "Continue a previous conversation",
                    "type": "string"
                  }
                },
                "required": [
                  "handle",
                  "question"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/tools/check_availability": {
      "post": {
        "operationId": "tool_check_availability",
        "summary": "Check availability",
        "description": "List open booking slots (ISO start/end + local label) for a service in a date range (max 14 days).\n\nRequired scope: `profile:read`. Same contract as the MCP tool `check_availability`.",
        "tags": [
          "Visitor tools"
        ],
        "security": [
          {},
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "handle": {
                    "type": "string"
                  },
                  "service_id": {
                    "type": "string"
                  },
                  "from": {
                    "description": "ISO date, default now",
                    "type": "string"
                  },
                  "to": {
                    "description": "ISO date, default +7 days",
                    "type": "string"
                  }
                },
                "required": [
                  "handle"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/tools/create_booking": {
      "post": {
        "operationId": "tool_create_booking",
        "summary": "Create booking",
        "description": "Request a booking for a service at a slot from check_availability. Returns status 'pending_human' — the owner confirms.\n\nRequired scope: `booking:create`. Same contract as the MCP tool `create_booking`.",
        "tags": [
          "Visitor tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "handle": {
                    "type": "string"
                  },
                  "service_id": {
                    "type": "string"
                  },
                  "slot": {
                    "type": "string",
                    "description": "ISO 8601 start time"
                  },
                  "contact": {
                    "type": "object",
                    "properties": {
                      "name": {
                        "type": "string"
                      },
                      "email": {
                        "type": "string"
                      },
                      "phone": {
                        "type": "string"
                      }
                    },
                    "additionalProperties": false,
                    "description": "At least an email or phone"
                  },
                  "note": {
                    "type": "string"
                  }
                },
                "required": [
                  "handle",
                  "service_id",
                  "slot",
                  "contact"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/tools/request_payment_link": {
      "post": {
        "operationId": "tool_request_payment_link",
        "summary": "Request payment link",
        "description": "Create a payment request for a priced service. Agent requests need the profile owner's approval before a checkout link is issued.\n\nRequired scope: `payment:request`. Same contract as the MCP tool `request_payment_link`.",
        "tags": [
          "Visitor tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "handle": {
                    "type": "string"
                  },
                  "service_id": {
                    "type": "string"
                  },
                  "contact": {
                    "type": "object",
                    "properties": {
                      "name": {
                        "type": "string"
                      },
                      "email": {
                        "type": "string"
                      },
                      "phone": {
                        "type": "string"
                      }
                    },
                    "additionalProperties": false,
                    "description": "At least an email or phone"
                  }
                },
                "required": [
                  "handle",
                  "service_id",
                  "contact"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/tools/submit_lead": {
      "post": {
        "operationId": "tool_submit_lead",
        "summary": "Submit lead",
        "description": "Send the profile owner your human's contact details and a note so they can follow up.\n\nRequired scope: `lead:submit`. Same contract as the MCP tool `submit_lead`.",
        "tags": [
          "Visitor tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "handle": {
                    "type": "string"
                  },
                  "contact": {
                    "type": "object",
                    "properties": {
                      "name": {
                        "type": "string"
                      },
                      "email": {
                        "type": "string"
                      },
                      "phone": {
                        "type": "string"
                      }
                    },
                    "additionalProperties": false,
                    "description": "At least an email or phone"
                  },
                  "note": {
                    "type": "string",
                    "maxLength": 2000
                  }
                },
                "required": [
                  "handle",
                  "contact"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/tools/list_my_profiles": {
      "post": {
        "operationId": "tool_list_my_profiles",
        "summary": "List my profiles",
        "description": "List profiles owned by the human who issued this API key (id, handle, status).\n\nRequired scope: `profile:draft`. Same contract as the MCP tool `list_my_profiles`.",
        "tags": [
          "Admin tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {},
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/tools/create_profile_draft": {
      "post": {
        "operationId": "tool_create_profile_draft",
        "summary": "Create profile draft",
        "description": "Create a new DRAFT profile for your human. Content is marked unverified until the human approves a publish request.\n\nRequired scope: `profile:draft`. Same contract as the MCP tool `create_profile_draft`.",
        "tags": [
          "Admin tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "handle": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "headline": {
                    "type": "string"
                  },
                  "bio": {
                    "type": "string"
                  },
                  "category": {
                    "type": "string"
                  },
                  "city": {
                    "type": "string"
                  },
                  "country": {
                    "type": "string"
                  },
                  "languages": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "contact_email": {
                    "type": "string"
                  },
                  "links": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "title": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 80
                        },
                        "url": {},
                        "icon": {
                          "anyOf": [
                            {
                              "type": "string",
                              "maxLength": 40
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      },
                      "required": [
                        "title",
                        "url"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "services": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 120
                        },
                        "description": {
                          "default": "",
                          "type": "string",
                          "maxLength": 1000
                        },
                        "price": {
                          "anyOf": [
                            {
                              "type": "number",
                              "minimum": 0,
                              "maximum": 10000000
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "currency": {
                          "default": "USD",
                          "type": "string",
                          "minLength": 3,
                          "maxLength": 3
                        },
                        "duration_min": {
                          "anyOf": [
                            {
                              "type": "integer",
                              "minimum": 5,
                              "maximum": 1440
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      },
                      "required": [
                        "name",
                        "description",
                        "currency"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "required": [
                  "handle",
                  "name"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/tools/upload_document": {
      "post": {
        "operationId": "tool_upload_document",
        "summary": "Upload document",
        "description": "Add knowledge to a profile from a public URL or plain text. Ingestion is async: status queued -> processing -> ready|failed.\n\nRequired scope: `docs:write`. Same contract as the MCP tool `upload_document`.",
        "tags": [
          "Admin tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "profile_id": {
                    "type": "string",
                    "description": "Profile id or handle"
                  },
                  "url": {
                    "type": "string"
                  },
                  "text": {
                    "type": "string",
                    "maxLength": 200000
                  },
                  "title": {
                    "type": "string"
                  }
                },
                "required": [
                  "profile_id"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/tools/update_services": {
      "post": {
        "operationId": "tool_update_services",
        "summary": "Update services",
        "description": "Replace a profile's services (name, description, price, currency, duration_min). Agent edits stay unverified/hidden until the owner approves.\n\nRequired scope: `profile:edit`. Same contract as the MCP tool `update_services`.",
        "tags": [
          "Admin tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "profile_id": {
                    "type": "string"
                  },
                  "services": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 120
                        },
                        "description": {
                          "default": "",
                          "type": "string",
                          "maxLength": 1000
                        },
                        "price": {
                          "anyOf": [
                            {
                              "type": "number",
                              "minimum": 0,
                              "maximum": 10000000
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "currency": {
                          "default": "USD",
                          "type": "string",
                          "minLength": 3,
                          "maxLength": 3
                        },
                        "duration_min": {
                          "anyOf": [
                            {
                              "type": "integer",
                              "minimum": 5,
                              "maximum": 1440
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      },
                      "required": [
                        "name",
                        "description",
                        "currency"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "required": [
                  "profile_id",
                  "services"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/tools/list_leads": {
      "post": {
        "operationId": "tool_list_leads",
        "summary": "List leads",
        "description": "Leads and handoff requests for a profile, newest first.\n\nRequired scope: `leads:read`. Same contract as the MCP tool `list_leads`.",
        "tags": [
          "Admin tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "profile_id": {
                    "type": "string"
                  },
                  "since": {
                    "description": "ISO date",
                    "type": "string"
                  }
                },
                "required": [
                  "profile_id"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/tools/get_analytics": {
      "post": {
        "operationId": "tool_get_analytics",
        "summary": "Get analytics",
        "description": "Visits, chats, human vs agent traffic, top questions for a profile.\n\nRequired scope: `leads:read`. Same contract as the MCP tool `get_analytics`.",
        "tags": [
          "Admin tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "profile_id": {
                    "type": "string"
                  },
                  "range_days": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 365
                  }
                },
                "required": [
                  "profile_id"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/tools/request_publish": {
      "post": {
        "operationId": "tool_request_publish",
        "summary": "Request publish",
        "description": "Ask the human owner to approve publishing (agents can never publish directly).\n\nRequired scope: `publish:request`. Same contract as the MCP tool `request_publish`.",
        "tags": [
          "Admin tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "profile_id": {
                    "type": "string"
                  },
                  "note": {
                    "type": "string"
                  }
                },
                "required": [
                  "profile_id"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    }
  }
}