{
  "openapi": "3.1.0",
  "info": {
    "title": "CinematicCard Agent Commerce API",
    "version": "1.0.0",
    "description": "Programmatic API for AI agents to discover, quote, purchase, and deliver cinematic video greeting cards. No browser or SPA interaction required. Full transaction via JSON over HTTPS.",
    "contact": {
      "name": "CinematicCard Partnerships",
      "email": "partnerships@cinematiccard.com",
      "url": "https://cinematiccard.com/agents"
    }
  },
  "servers": [
    { "url": "https://cinematiccard.com/api/agent/v1", "description": "Production" }
  ],
  "security": [],
  "components": {
    "securitySchemes": {
      "AgentKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Agent-Key",
        "description": "Optional. Higher rate limits. Request at partnerships@cinematiccard.com."
      }
    },
    "headers": {
      "IdempotencyKey": {
        "description": "Stable string for safe retries. Duplicate requests with same key return the original response for 24 hours.",
        "schema": { "type": "string" }
      }
    },
    "schemas": {
      "HealthResponse": {
        "type": "object",
        "properties": {
          "ok":        { "type": "boolean" },
          "service":   { "type": "string" },
          "version":   { "type": "string" },
          "timestamp": { "type": "string", "format": "date-time" },
          "database":  { "type": "string" },
          "stripe":    { "type": "boolean" }
        }
      },
      "Theme": {
        "type": "object",
        "properties": {
          "key":          { "type": "string", "example": "mother" },
          "label":        { "type": "string", "example": "Mother's Day" },
          "occasion":     { "type": "string", "example": "mothers-day" },
          "recipient":    { "type": "string", "example": "mom" },
          "tone":         { "type": "string", "example": "emotional" },
          "previewUrl":   { "type": "string", "format": "uri" },
          "sampleCardUrl":{ "type": ["string", "null"], "format": "uri" }
        },
        "required": ["key", "label", "occasion", "recipient", "tone"]
      },
      "QuoteRequest": {
        "type": "object",
        "properties": {
          "theme":           { "type": "string", "example": "mother", "description": "Card theme key from GET /themes" },
          "photos":          { "type": "integer", "minimum": 0, "maximum": 20, "example": 6 },
          "customMusic":     { "type": "boolean", "example": false },
          "cashGift": {
            "type": "object",
            "properties": {
              "enabled":  { "type": "boolean" },
              "platform": { "type": "string", "enum": ["venmo", "paypal", "cashapp"] },
              "amount":   { "type": "number", "minimum": 1, "maximum": 2000 }
            }
          },
          "scheduled":       { "type": "boolean", "example": false },
          "bulkRecipients":  { "type": "integer", "minimum": 0, "example": 0 }
        }
      },
      "QuoteResponse": {
        "type": "object",
        "properties": {
          "quoteId":     { "type": "string", "format": "uuid" },
          "expiresAt":   { "type": "string", "format": "date-time" },
          "lineItems": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "description": { "type": "string" },
                "cents":       { "type": "integer" }
              }
            }
          },
          "subtotalCents":   { "type": "integer" },
          "totalCents":      { "type": "integer" },
          "currency":        { "type": "string", "example": "USD" },
          "tier":            { "type": "string", "enum": ["classic", "premium", "signature"] },
          "checkoutPayload": { "type": "object", "description": "Pre-filled payload template for POST /checkout" }
        }
      },
      "CheckoutRequest": {
        "type": "object",
        "required": ["cardData", "payment"],
        "properties": {
          "quoteId": {
            "type": "string",
            "format": "uuid",
            "description": "Optional. From POST /quote. Validates price hasn't changed."
          },
          "cardData": {
            "type": "object",
            "required": ["senderEmail"],
            "properties": {
              "theme":          { "type": "string", "example": "mother" },
              "recipientName":  { "type": "string", "maxLength": 50, "example": "Linda" },
              "senderName":     { "type": "string", "maxLength": 50, "example": "Sarah" },
              "senderEmail":    { "type": "string", "format": "email" },
              "recipientEmail": { "type": "string", "format": "email" },
              "greeting":       { "type": "string", "maxLength": 100 },
              "message":        { "type": "string", "maxLength": 2000 },
              "signOff":        { "type": "string", "maxLength": 100 },
              "music":          { "type": "string", "example": "piano" },
              "schedule":       { "type": "string", "format": "date-time", "description": "Requires addons.schedule = true" }
            }
          },
          "addons": {
            "type": "object",
            "properties": {
              "photos":      { "type": "boolean" },
              "customMusic": { "type": "boolean" },
              "schedule":    { "type": "boolean" }
            }
          },
          "cashGift": {
            "type": "object",
            "properties": {
              "enabled":  { "type": "boolean" },
              "platform": { "type": "string", "enum": ["venmo", "paypal", "cashapp"] },
              "amount":   { "type": "number", "minimum": 1, "maximum": 2000, "example": 50 },
              "handle":   { "type": "string", "maxLength": 60, "example": "lindasmith" },
              "note":     { "type": "string", "maxLength": 100 }
            }
          },
          "recipient": {
            "type": "object",
            "properties": {
              "email":     { "type": "string", "format": "email" },
              "deliverAt": { "type": "string", "format": "date-time", "description": "Schedule delivery. Requires addons.schedule = true." }
            }
          },
          "payment": {
            "type": "object",
            "required": ["method"],
            "properties": {
              "method": {
                "type": "string",
                "enum": ["hosted_checkout", "payment_method", "ucp"],
                "description": "hosted_checkout returns a Stripe Checkout URL. payment_method requires a Stripe pm_xxx token. ucp is a stub for Google Universal Commerce Protocol."
              },
              "value": {
                "type": ["string", "null"],
                "description": "Required for payment_method: Stripe payment_method id (pm_xxx). Null for hosted_checkout.",
                "example": "pm_1234567890"
              }
            }
          },
          "agent": {
            "type": "object",
            "properties": {
              "name":           { "type": "string", "example": "ChatGPT" },
              "userConsent":    { "type": "string", "enum": ["acknowledged"] },
              "orderReference": { "type": "string", "description": "Agent-side order ID. Used as idempotency key if Idempotency-Key header not set." }
            }
          }
        }
      },
      "CheckoutResponse": {
        "type": "object",
        "properties": {
          "ok":                { "type": "boolean" },
          "orderId":           { "type": "string", "description": "Stable card/order ID for status polling." },
          "cardUrl":           { "type": "string", "format": "uri", "description": "Permanent card URL. Available once payment completes." },
          "checkoutUrl":       { "type": ["string", "null"], "format": "uri", "description": "Stripe Checkout URL. Present for hosted_checkout flow only." },
          "status":            { "type": "string", "enum": ["pending_payment", "paid", "generated", "delivered", "scheduled"] },
          "amountCharged":     { "type": "integer", "description": "Amount in cents." },
          "currency":          { "type": "string", "example": "USD" },
          "deliveryEta":       { "type": "string", "description": "ISO timestamp or 'immediate' or 'after_payment'." },
          "statusUrl":         { "type": "string", "format": "uri" },
          "receiptUrl":        { "type": "string", "format": "uri" },
          "agentReviewFlagged":{ "type": "boolean", "description": "Present and true when unauthenticated signature-tier order is flagged for human review." }
        }
      },
      "OrderStatus": {
        "type": "object",
        "properties": {
          "orderId":       { "type": "string" },
          "status":        { "type": "string", "enum": ["pending", "pending_payment", "paid", "generated", "delivered", "scheduled", "failed"] },
          "amountCents":   { "type": "integer" },
          "currency":      { "type": "string" },
          "cardUrl":       { "type": ["string", "null"], "format": "uri" },
          "theme":         { "type": "string" },
          "recipientName": { "type": "string" },
          "scheduledFor":  { "type": ["string", "null"], "format": "date-time" },
          "createdAt":     { "type": "string", "format": "date-time" },
          "paidAt":        { "type": ["string", "null"], "format": "date-time" },
          "generatedAt":   { "type": ["string", "null"], "format": "date-time" },
          "deliveredAt":   { "type": ["string", "null"], "format": "date-time" }
        }
      },
      "PhotoUploadResponse": {
        "type": "object",
        "properties": {
          "photoToken":  { "type": "string" },
          "url":         { "type": "string", "format": "uri" },
          "contentType": { "type": "string" },
          "sizeBytes":   { "type": "integer" },
          "usage":       { "type": "string" }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": { "type": "string" }
        },
        "required": ["error"]
      }
    }
  },
  "paths": {
    "/health": {
      "get": {
        "summary": "Health check",
        "operationId": "getHealth",
        "tags": ["Discovery"],
        "responses": {
          "200": { "description": "Service healthy", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HealthResponse" } } } },
          "503": { "description": "Database unavailable", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/manifest": {
      "get": {
        "summary": "Discovery manifest",
        "operationId": "getManifest",
        "description": "Returns everything an agent needs to operate: endpoints, themes count, pricing summary, payment flows, auth and rate limit details.",
        "tags": ["Discovery"],
        "responses": {
          "200": { "description": "Manifest", "content": { "application/json": { "schema": { "type": "object" } } } }
        }
      }
    },
    "/themes": {
      "get": {
        "summary": "List all card themes",
        "operationId": "getThemes",
        "tags": ["Discovery"],
        "responses": {
          "200": {
            "description": "All themes",
            "content": { "application/json": { "schema": {
              "type": "object",
              "properties": {
                "themes": { "type": "array", "items": { "$ref": "#/components/schemas/Theme" } },
                "total":  { "type": "integer" }
              }
            }}}
          }
        }
      }
    },
    "/pricing": {
      "get": {
        "summary": "Full pricing structure",
        "operationId": "getPricing",
        "tags": ["Discovery"],
        "responses": {
          "200": { "description": "Pricing", "content": { "application/json": { "schema": { "type": "object" } } } }
        }
      }
    },
    "/quote": {
      "post": {
        "summary": "Get an itemized price quote",
        "operationId": "createQuote",
        "description": "Returns a firm, itemized price and a quoteId valid for 30 minutes. Pass quoteId to /checkout to validate price hasn't changed.",
        "tags": ["Commerce"],
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/QuoteRequest" } } }
        },
        "responses": {
          "200": { "description": "Quote", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/QuoteResponse" } } } },
          "500": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/checkout": {
      "post": {
        "summary": "Create, pay for, and deliver a card",
        "operationId": "checkout",
        "description": "The primary transaction endpoint. Supports three payment flows: hosted_checkout (returns Stripe URL), payment_method (pm_xxx token, in-process confirmation), and ucp (Google Universal Commerce Protocol stub). Idempotent via Idempotency-Key header or agent.orderReference.",
        "tags": ["Commerce"],
        "security": [{ "AgentKey": [] }, {}],
        "parameters": [
          { "in": "header", "name": "Idempotency-Key", "schema": { "type": "string" }, "description": "Safe retry key — 24-hour cache." }
        ],
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CheckoutRequest" } } }
        },
        "responses": {
          "200": { "description": "Checkout result", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CheckoutResponse" } } } },
          "400": { "description": "Validation error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "402": { "description": "Payment failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "429": { "description": "Rate limit exceeded", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "500": { "description": "Server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "501": { "description": "UCP not yet implemented", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/order/{orderId}": {
      "get": {
        "summary": "Poll order status",
        "operationId": "getOrder",
        "description": "Idempotent status check. Poll after hosted_checkout to detect when payment completes and card is delivered.",
        "tags": ["Commerce"],
        "parameters": [
          { "in": "path", "name": "orderId", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "description": "Order status", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OrderStatus" } } } },
          "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/order/{orderId}/receipt": {
      "get": {
        "summary": "Order receipt",
        "operationId": "getReceipt",
        "tags": ["Commerce"],
        "parameters": [
          { "in": "path", "name": "orderId", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "description": "Receipt", "content": { "application/json": { "schema": { "type": "object" } } } },
          "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/upload/photo": {
      "post": {
        "summary": "Upload a photo by URL",
        "operationId": "uploadPhoto",
        "description": "Agent provides a public image URL. Server fetches, validates, and stores in Cloudflare R2. Returns a token and permanent URL for use in cardData.photos[].",
        "tags": ["Commerce"],
        "security": [{ "AgentKey": [] }, {}],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["url"],
                "properties": {
                  "url": { "type": "string", "format": "uri", "description": "Public URL of the image (jpg, png, webp). Max 10MB." }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Photo uploaded", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PhotoUploadResponse" } } } },
          "400": { "description": "Invalid URL or not an image", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "500": { "description": "Upload failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/ucp": {
      "get": {
        "summary": "Google Universal Commerce Protocol status",
        "operationId": "getUCP",
        "description": "Returns current UCP implementation status. Interface boundary is reserved. Full integration pending Google UCP SDK GA. Spec: https://developers.google.com/commerce/protocol",
        "tags": ["Discovery"],
        "responses": {
          "200": { "description": "UCP status", "content": { "application/json": { "schema": { "type": "object" } } } }
        }
      }
    },
    "/openapi.json": {
      "get": {
        "summary": "This OpenAPI specification",
        "operationId": "getOpenApiSpec",
        "tags": ["Discovery"],
        "responses": {
          "200": { "description": "OpenAPI 3.1 spec", "content": { "application/json": { "schema": { "type": "object" } } } }
        }
      }
    }
  },
  "tags": [
    { "name": "Discovery", "description": "Read-only endpoints for agent onboarding and product discovery" },
    { "name": "Commerce",  "description": "Transaction endpoints — quote, checkout, order tracking" }
  ]
}
