{
  "openapi": "3.1.0",
  "info": {
    "title": "BidGlow Agent Publishing & Quote API",
    "version": "2026-09-06",
    "description": "For personal profiles, company websites, services, portfolios and products that pass content review. Customer-owned agents can discover rules, publish one free listing with explicit user approval, recover a private receipt by replay, and request optional read-only bid quotes. Publication creates a listing and private management capability. No API operation charges a card; the customer confirms payment through Stripe."
  },
  "servers": [
    {
      "url": "https://bidglow.ai"
    }
  ],
  "security": [],
  "components": {
    "securitySchemes": {
      "SubmissionSecret": {
        "type": "apiKey", "in": "header", "name": "X-Submission-Secret",
        "description": "Client-generated cryptographically random 32-byte hex secret for this submission, not a pre-issued account key. Save privately with the Idempotency-Key and exact body BEFORE sending. Never log or publish."
      }
    },
    "schemas": {
      "PublicationReceipt": {
        "type": "object",
        "required": ["requestId", "status", "productUrl", "expiresAt", "chargeCreated", "paidRankingChanged", "ownership", "optionalPaidPlacement", "notice"],
        "properties": {
          "requestId": {"type":"string", "description":"Not sufficient to retrieve private ownership."},
          "status": {"type":"string", "enum":["published","expired","unavailable"]},
          "productUrl": {"type":"string", "format":"uri"},
          "expiresAt": {"type":["integer","null"], "description":"Unix milliseconds; replay never renews the original expiry."},
          "chargeCreated": {"const":false},
          "paidRankingChanged": {"const":false},
          "ownership": {
            "type":"object", "required":["sensitive","domainOwnershipVerified"],
            "properties": {
              "privateRecoveryUrl":{"type":"string","format":"uri","description":"Only while published. Confidential reusable #owner management link; open in the customer's browser before optional upgrade. Never publish or log."},
              "recoveryUnavailable":{"const":true},
              "supportUrl":{"type":"string","format":"uri"},
              "sensitive":{"const":true},
              "domainOwnershipVerified":{"const":false}
            }
          },
          "optionalPaidPlacement":{"type":"object","properties":{"quoteEndpoint":{"type":"string","format":"uri"},"minimumTargetUSD":{"const":5},"humanConfirmationRequired":{"const":true}}},
          "notice":{"type":"string"}
        }
      },
      "PublicationError": {
        "type":"object", "required":["code","error","chargeCreated"],
        "properties":{"code":{"type":"string"},"error":{"type":"string"},"chargeCreated":{"const":false}}
      }
    }
  },
  "paths": {
    "/api/v1/agent/listings": {
      "post": {
        "operationId":"publishBidGlowFreeListing",
        "summary":"Publish one free product after explicit user permission; replay the same request to recover its receipt",
        "description":"Server-to-server only. Screens the public page and atomically creates a listing, claim and receipt. Does not create paid bids, charges or referral credit. Approval is the agent's declaration, not a verified human or domain identity. Existing URLs cannot be taken over; retries never renew expiry or undo moderation. Current limits and offer availability are in capabilities. Save confidential responses safely.",
        "security":[{"SubmissionSecret":[]}],
        "parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"description":"Random UUIDv4 saved BEFORE sending. Reuse with original secret and identical JSON after timeout or an unknown result."}],
        "requestBody": {
          "required":true,
          "content":{"application/json":{"schema":{
            "type":"object","additionalProperties":false,"required":["destination","category","approval"],
            "properties":{
              "destination":{"type":"string","maxLength":500,"description":"Real public HTTP(S) domain on standard port, without credentials, IP literals or reserved hosts. Query and fragment are stripped; metadata is fetched and screened."},
              "category":{"type":"string","description":"English category ID from capabilities."},
              "approval":{"type":"object","additionalProperties":false,"required":["scope","userApproved","rulesVersion"],"properties":{"scope":{"const":"free_listing_publish"},"userApproved":{"const":true},"rulesVersion":{"const":"2026-09-06"}}}
            }
          }}}
        },
        "responses": {
          "201":{"description":"Created one real free listing, not a paid entry. Securely retain ownership.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicationReceipt"}}}},
          "200":{"description":"Matching replay; inspect current published/expired/unavailable status. No renewal.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicationReceipt"}}}},
          "400":{"description":"Invalid fields, URL, category, approval or per-submission credentials."},
          "403":{"description":"Cross-origin browser request rejected."},
          "409":{"description":"Conflicting key, secret, body or existing URL; no ownership granted."},
          "410":{"description":"New free submissions closed. Existing matching replay still works."},
          "413":{"description":"Body exceeds 4 KiB."},
          "415":{"description":"Use application/json."},
          "422":{"description":"Content review rejected. See /rules and /report."},
          "429":{"description":"Quota exceeded. Preserve credentials and respect Retry-After.","headers":{"Retry-After":{"schema":{"type":"string"}}}},
          "503":{"description":"Review unavailable or publication unconfirmed. Retry only with original key, secret and body."},
          "default":{"description":"Structured non-charging error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicationError"}}}}
        }
      }
    },
    "/api/v1/agent/capabilities": {
      "get": {
        "operationId": "getBidGlowCapabilities",
        "summary": "Read supported capabilities and English category IDs",
        "responses": {
          "200": {
            "description": "Current supported contract. unattendedPayments is false.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "version",
                    "capabilities",
                    "categories",
                    "paymentPolicy"
                  ],
                  "properties": {
                    "version": {
                      "type": "string"
                    },
                    "capabilities": {
                      "type": "object",
                      "properties": {
                        "publicQuotes": {
                          "const": true
                        },
                        "freePublishing": {
                          "const": true
                        },
                        "unattendedPayments": {
                          "const": false
                        }
                      }
                    },
                    "categories": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "id",
                          "label"
                        ],
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "label": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "paymentPolicy": {
                      "type": "object"
                    },
                    "endpoints": {
                      "type":"object", "properties":{"capabilities":{"const":"/api/v1/agent/capabilities"},"freePublish":{"const":"/api/v1/agent/listings"},"quote":{"const":"/api/v1/agent/quote"}}
                    },
                    "agentGuide": {"type":"string","format":"uri"},
                    "publishingPolicy": {
                      "type":"object", "properties":{"rulesVersion":{"const":"2026-09-06"},"explicitUserApprovalRequired":{"const":true},"approvalScope":{"const":"free_listing_publish"},"serverToServer":{"const":true},"requestBodyMaxBytes":{"const":4096},"idempotencyHeader":{"const":"Idempotency-Key"},"proofHeader":{"const":"X-Submission-Secret"},"resume":{"type":"string"},"domainOwnershipVerified":{"const":false},"contentReviewRequired":{"const":true},"paidRankingChanged":{"const":false},"limits":{"type":"object","properties":{"requestsPerTenMinutesPerIp":{"const":30},"newAttemptsPerDayPerIp":{"const":4},"newAttemptsPerDayPerHost":{"const":4},"newAttemptsPerDayGlobal":{"const":100}}}}
                    },
                    "discovery": {
                      "type":"object", "properties":{"available":{"type":"boolean"},"submissionEndsAt":{"type":"string","format":"date-time"},"displayDays":{"const":60},"paidRanking":{"const":false}}
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/agent/quote": {
      "post": {
        "operationId": "previewBidGlowQuote",
        "summary": "Preview a bid; does not charge or create an order",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "destination",
                  "category",
                  "board",
                  "targetBid"
                ],
                "properties": {
                  "destination": {
                    "type": "string",
                    "maxLength": 500,
                    "description": "Public website/profile URL. No userinfo credentials."
                  },
                  "category": {
                    "type": "string",
                    "description": "English id from GET /api/v1/agent/capabilities."
                  },
                  "board": {
                    "type": "string",
                    "enum": [
                      "all",
                      "today"
                    ]
                  },
                  "targetBid": {
                    "type": "integer",
                    "minimum": 5,
                    "maximum": 999999,
                    "description": "Desired board total in whole USD, not cents or incremental charge."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Non-binding quote, expires within five minutes or UTC midnight. Price is recalculated at checkout; rank is not reserved.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "kind",
                    "currency",
                    "chargeAmountCents",
                    "expiresAt",
                    "handoffUrl",
                    "humanConfirmationRequired",
                    "chargeCreated"
                  ],
                  "properties": {
                    "kind": {
                      "const": "non_binding_preview"
                    },
                    "currency": {
                      "const": "usd"
                    },
                    "chargeAmountCents": {
                      "type": "integer",
                      "minimum": 100
                    },
                    "expiresAt": {
                      "type": "integer",
                      "description": "Unix timestamp in milliseconds"
                    },
                    "handoffUrl": {
                      "type": "string",
                      "format": "uri",
                      "description": "Public prefill link, not authorization to pay."
                    },
                    "humanConfirmationRequired": {
                      "const": true
                    },
                    "chargeCreated": {
                      "const": false
                    },
                    "estimatedRank": {
                      "type":"integer", "minimum":1, "description":"Non-binding conservative estimate, not a reserved position."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid quote input"
          },
          "413": {
            "description": "Body exceeds 4 KiB"
          },
          "415": {
            "description": "Content-Type must be application/json"
          },
          "503": {
            "description": "Verified payment evidence unavailable; no order or charge created"
          }
        }
      }
    }
  }
}
