{
  "openapi": "3.1.0",
  "info": {
    "title": "PhotoBrief Public API",
    "version": "1.0.0",
    "summary": "Create visual intake workflows and PhotoBrief requests.",
    "description": "Public API reference for PhotoBrief. PhotoBrief is a visual intake layer that turns website inquiries and customer requests into mobile photo workflows and business-ready briefs. Pricing is based on submitted/analyzed customer photos: 1 photo = 1 PhotoBrief Credit.",
    "contact": {
      "name": "PhotoBrief",
      "email": "hello@photobrief.ai",
      "url": "https://photobrief.ai/for-ai-agents"
    },
    "license": { "name": "Proprietary" }
  },
  "servers": [
    { "url": "https://app.photobrief.ai/functions/v1", "description": "Production" }
  ],
  "security": [{ "bearerAuth": [] }],
  "paths": {
    "/api-create-request": {
      "post": {
        "operationId": "createRequest",
        "summary": "Create a PhotoBrief request",
        "description": "Creates a guided photo request and returns a recipient URL the business can forward via SMS or email. The recipient opens the URL in a mobile browser and completes the capture workflow with no app install.",
        "security": [{ "bearerAuth": [] }],
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateRequestBody" } } }
        },
        "responses": {
          "201": { "description": "Request created.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateRequestResponse" } } } },
          "400": { "description": "Validation error.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "401": { "description": "Missing or invalid API key.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "403": { "description": "guide_id is not accessible to the authenticated workspace.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "405": { "description": "Method not allowed.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "500": { "description": "Server error.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/website-intake/{public_token}": {
      "get": {
        "operationId": "getWebsiteIntakeConfig",
        "summary": "Load public Website Intake configuration",
        "description": "Returns safe public configuration for a PhotoBrief-hosted intake form. No authentication is required; the public token scopes the request.",
        "security": [],
        "parameters": [
          { "name": "public_token", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "description": "Public intake config.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WebsiteIntakeConfig" } } } },
          "403": { "description": "Intake source disabled.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "404": { "description": "Intake source not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      },
      "post": {
        "operationId": "submitWebsiteIntakeLead",
        "summary": "Submit a website intake lead",
        "description": "Accepts a website lead payload, normalizes customer information, routes the lead to a saved PhotoBrief template, creates or reuses a customer profile, creates a PhotoBrief request, and optionally sends the customer the request link.",
        "security": [],
        "parameters": [
          { "name": "public_token", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WebsiteIntakeLead" } } }
        },
        "responses": {
          "200": { "description": "Lead processed or received with no template match.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WebsiteIntakeResponse" } } } },
          "400": { "description": "Validation error.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "403": { "description": "Intake source disabled.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "404": { "description": "Intake source not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "500": { "description": "Server error.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "Opaque (prefix: pb_)",
        "description": "Workspace API key issued from Settings → API Keys on supported plans."
      }
    },
    "schemas": {
      "CreateRequestBody": {
        "type": "object",
        "required": ["recipient_name"],
        "properties": {
          "recipient_name": { "type": "string", "description": "Display name shown to the recipient.", "example": "Jane Smith" },
          "recipient_email": { "type": "string", "format": "email", "description": "Recipient email. Either recipient_email or recipient_phone is required.", "example": "jane@example.com" },
          "recipient_phone": { "type": "string", "description": "Recipient phone in E.164. Either recipient_email or recipient_phone is required.", "example": "+15555550123" },
          "guide_id": { "type": "string", "format": "uuid", "description": "Optional. ID of a workspace photo guide/template." },
          "custom_message": { "type": "string", "description": "Optional intro message shown to the recipient.", "example": "Hi Jane — please grab a few photos so we can quote your repair." },
          "due_date": { "type": "string", "format": "date", "description": "Optional ISO 8601 due date.", "example": "2026-05-15" }
        }
      },
      "CreateRequestResponse": {
        "type": "object",
        "required": ["request_id", "token", "recipient_url"],
        "properties": {
          "request_id": { "type": "string", "format": "uuid" },
          "token": { "type": "string", "description": "Opaque recipient token." },
          "recipient_url": { "type": "string", "format": "uri", "description": "URL to forward to the recipient — opens the mobile capture workflow.", "example": "https://photobrief.ai/r/abc123" }
        }
      },
      "WebsiteIntakeConfig": {
        "type": "object",
        "required": ["ok", "businessName", "introMessage", "requestTypeOptions"],
        "properties": {
          "ok": { "type": "boolean", "const": true },
          "sourceName": { "type": "string" },
          "businessName": { "type": "string" },
          "logoUrl": { "type": ["string", "null"], "format": "uri" },
          "brandColor": { "type": ["string", "null"] },
          "hidePhotobriefBranding": { "type": "boolean" },
          "introMessage": { "type": "string" },
          "requestTypeOptions": { "type": "array", "items": { "type": "string" } }
        }
      },
      "WebsiteIntakeLead": {
        "type": "object",
        "properties": {
          "name": { "type": "string", "example": "Jane Smith" },
          "email": { "type": "string", "format": "email", "example": "jane@example.com" },
          "phone": { "type": "string", "example": "+15555550123" },
          "request_type": { "type": "string", "example": "repair" },
          "message": { "type": "string", "example": "My dishwasher is leaking and I need help." },
          "address": { "type": "string", "example": "123 Main St" }
        },
        "additionalProperties": true
      },
      "WebsiteIntakeResponse": {
        "type": "object",
        "properties": {
          "ok": { "type": "boolean" },
          "status": { "type": "string", "enum": ["request_created", "no_template_match"] },
          "requestId": { "type": "string", "format": "uuid" },
          "requestLink": { "type": "string", "format": "uri" },
          "customerId": { "type": "string", "format": "uuid" },
          "matchedGuideId": { "type": "string", "format": "uuid" },
          "delivery": { "type": "string", "enum": ["sent", "logged_only", "skipped"] },
          "matchSource": { "type": "string", "enum": ["rule", "ai", "fallback", "none"] },
          "message": { "type": "string" }
        }
      },
      "Error": {
        "type": "object",
        "required": ["error"],
        "properties": { "error": { "type": "string" } }
      }
    }
  },
  "x-photobrief-pricing": {
    "unit": "PhotoBrief Credit",
    "rule": "1 submitted/analyzed customer photo = 1 PhotoBrief Credit",
    "first_pass_followup": "Follow-up photos requested by PhotoBrief on the first pass do not consume credits."
  }
}
