{
  "openapi": "3.1.0",
  "info": {
    "title": "agentstock.dev public API",
    "version": "1.2.0",
    "description": "Free semantic search over AI-generated images and videos, and paid downloads of originals with x402 v2 (scheme \"exact\", USDC). Assets can also be bought together as sets at one set price, which is never more than the items cost separately. Every asset is release-safe and sold under the Agent Stock License (commercial use allowed, no attribution required, no resale of the raw file as stock); each item carries license, release_safe, has_text, ai_generated, and ai_disclosure fields. Rate limits per IP: searches with a query 20/min, listings and detail 120/min, downloads 20/min. Over a limit, or when search is busy, responses are 429 with Retry-After.",
    "license": { "name": "Agent Stock License", "url": "https://agentstock.dev/license" }
  },
  "servers": [{ "url": "https://agentstock.dev" }],
  "paths": {
    "/api/v1/search": {
      "get": {
        "operationId": "searchAssets",
        "summary": "Semantic search, or newest assets when q is empty",
        "parameters": [
          { "name": "q", "in": "query", "schema": { "type": "string", "maxLength": 200 }, "description": "Natural-language description of the media you need." },
          { "name": "type", "in": "query", "schema": { "type": "string", "enum": ["image", "video"] } },
          { "name": "aspect_ratio", "in": "query", "schema": { "type": "string", "examples": ["16:9", "1:1", "9:16"] } },
          { "name": "page", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 20, "default": 1 } },
          { "name": "per_page", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 48, "default": 24 } }
        ],
        "responses": {
          "200": { "description": "Results", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SearchResponse" } } } },
          "400": { "$ref": "#/components/responses/Error" },
          "429": { "$ref": "#/components/responses/RateLimited" },
          "503": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/api/v1/assets/{id}": {
      "get": {
        "operationId": "getAsset",
        "summary": "One published asset with purchase instructions",
        "parameters": [{ "$ref": "#/components/parameters/AssetId" }],
        "responses": {
          "200": {
            "description": "Asset",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "item": { "$ref": "#/components/schemas/Asset" },
                    "purchase": { "type": "object" },
                    "notice": { "$ref": "#/components/schemas/Notice" }
                  }
                }
              }
            }
          },
          "404": { "$ref": "#/components/responses/Error" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/api/v1/assets/{id}/download": {
      "get": {
        "operationId": "downloadAsset",
        "summary": "Paid download of the original file (x402)",
        "description": "Without PAYMENT-SIGNATURE the response is 402 with a base64 JSON PAYMENT-REQUIRED header. Retry with a signed PAYMENT-SIGNATURE header. On settlement the response contains a signed URL valid for 5 minutes and a PAYMENT-RESPONSE header. Each signed payment can be used once.",
        "parameters": [
          { "$ref": "#/components/parameters/AssetId" },
          { "name": "PAYMENT-SIGNATURE", "in": "header", "schema": { "type": "string" }, "description": "Base64-encoded x402 v2 PaymentPayload." }
        ],
        "responses": {
          "200": {
            "description": "Payment settled",
            "headers": { "PAYMENT-RESPONSE": { "schema": { "type": "string" }, "description": "Base64-encoded settlement response." } },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "asset": { "$ref": "#/components/schemas/Asset" },
                    "download": {
                      "type": "object",
                      "properties": {
                        "url": { "type": "string", "format": "uri" },
                        "expires_in": { "type": "integer" },
                        "expires_at": { "type": "string", "format": "date-time" }
                      }
                    },
                    "payment": { "type": "object" },
                    "notice": { "$ref": "#/components/schemas/Notice" }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required",
            "headers": { "PAYMENT-REQUIRED": { "schema": { "type": "string" }, "description": "Base64-encoded x402 v2 PaymentRequired." } },
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PaymentRequired" } } }
          },
          "404": { "$ref": "#/components/responses/Error" },
          "429": { "$ref": "#/components/responses/RateLimited" },
          "503": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/api/v1/sets": {
      "get": {
        "operationId": "listSets",
        "summary": "Published sets of assets that are sold together, newest first",
        "parameters": [
          { "name": "page", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 20, "default": 1 } },
          { "name": "per_page", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 24, "default": 12 } }
        ],
        "responses": {
          "200": { "description": "Sets", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SetListResponse" } } } },
          "400": { "$ref": "#/components/responses/Error" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/api/v1/sets/{id}": {
      "get": {
        "operationId": "getSet",
        "summary": "One published set with its items and purchase instructions",
        "description": "A set is only available while every asset in it is published; otherwise this returns 404.",
        "parameters": [{ "$ref": "#/components/parameters/SetId" }],
        "responses": {
          "200": {
            "description": "Set",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "item": { "$ref": "#/components/schemas/AssetSet" },
                    "purchase": { "type": "object" },
                    "notice": { "$ref": "#/components/schemas/Notice" }
                  }
                }
              }
            }
          },
          "404": { "$ref": "#/components/responses/Error" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/api/v1/sets/{id}/download": {
      "get": {
        "operationId": "downloadSet",
        "summary": "Paid download of every original in a set, in one payment (x402)",
        "description": "Same flow as an asset download, at the set price. On settlement the response lists one signed URL per asset in the set, each valid for 30 minutes, and a PAYMENT-RESPONSE header. Each signed payment can be used once.",
        "parameters": [
          { "$ref": "#/components/parameters/SetId" },
          { "name": "PAYMENT-SIGNATURE", "in": "header", "schema": { "type": "string" }, "description": "Base64-encoded x402 v2 PaymentPayload." }
        ],
        "responses": {
          "200": {
            "description": "Payment settled",
            "headers": { "PAYMENT-RESPONSE": { "schema": { "type": "string" }, "description": "Base64-encoded settlement response." } },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "set": { "$ref": "#/components/schemas/AssetSet" },
                    "downloads": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": { "type": "string", "description": "Asset id." },
                          "url": { "type": "string", "format": "uri" },
                          "expires_in": { "type": "integer" },
                          "expires_at": { "type": "string", "format": "date-time" }
                        }
                      }
                    },
                    "payment": { "type": "object" },
                    "notice": { "$ref": "#/components/schemas/Notice" }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required",
            "headers": { "PAYMENT-REQUIRED": { "schema": { "type": "string" }, "description": "Base64-encoded x402 v2 PaymentRequired." } },
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PaymentRequired" } } }
          },
          "404": { "$ref": "#/components/responses/Error" },
          "429": { "$ref": "#/components/responses/RateLimited" },
          "503": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/api/v1/notice": {
      "get": {
        "operationId": "getNotice",
        "summary": "Current buyer notice: the Agent Stock License text and version. Add format=text for plain text.",
        "parameters": [{ "name": "format", "in": "query", "schema": { "type": "string", "enum": ["json", "text"] } }],
        "responses": { "200": { "description": "Notice", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Notice" } }, "text/plain": {} } } }
      }
    },
    "/license": {
      "get": {
        "operationId": "getLicensePage",
        "summary": "The Agent Stock License as an HTML page: summary of what is allowed and the full current text.",
        "responses": { "200": { "description": "License page", "content": { "text/html": {} } } }
      }
    },
    "/pricing": {
      "get": {
        "operationId": "getPricingPage",
        "summary": "Pricing as an HTML page. The authoritative price of an asset is its price field and the 402 challenge.",
        "responses": { "200": { "description": "Pricing page", "content": { "text/html": {} } } }
      }
    },
    "/agents.txt": {
      "get": {
        "operationId": "getAgentsTxt",
        "summary": "agents.txt (agents-txt.com v1.0) capability declaration. Structured companion at /agents.json.",
        "responses": { "200": { "description": "agents.txt", "content": { "text/plain": {} } } }
      }
    }
  },
  "components": {
    "parameters": {
      "AssetId": { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "pattern": "^[a-f0-9]{16}$" } },
      "SetId": { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "pattern": "^[a-f0-9]{16}$" } }
    },
    "responses": {
      "Error": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "RateLimited": {
        "description": "Rate limited or search busy",
        "headers": { "Retry-After": { "schema": { "type": "integer" } } },
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      }
    },
    "schemas": {
      "Price": {
        "type": "object",
        "properties": {
          "amount": { "type": "string", "description": "Atomic units (6 decimals). 10000 = 0.01 USDC." },
          "currency": { "type": "string", "const": "USDC" },
          "decimals": { "type": "integer", "const": 6 },
          "display": { "type": "string", "examples": ["0.01 USDC"] }
        }
      },
      "Asset": {
        "type": "object",
        "properties": {
          "score": { "type": "number", "description": "Cosine similarity, semantic search only." },
          "id": { "type": "string" },
          "type": { "type": "string", "enum": ["image", "video"] },
          "title": { "type": "string" },
          "caption": { "type": "string" },
          "tags": { "type": "array", "items": { "type": "string" } },
          "mime_type": { "type": "string" },
          "width": { "type": ["integer", "null"] },
          "height": { "type": ["integer", "null"] },
          "aspect_ratio": { "type": ["string", "null"] },
          "duration_seconds": { "type": ["number", "null"] },
          "thumbnail": {
            "type": "object",
            "properties": {
              "url": { "type": ["string", "null"], "format": "uri" },
              "width": { "type": ["integer", "null"] },
              "height": { "type": ["integer", "null"] }
            }
          },
          "preview": {
            "type": ["object", "null"],
            "description": "Free 360-pixel-wide MP4 for a video, watermarked with agentstock.dev. Null for images and for videos that have not been encoded yet. The paid original stays on download_url.",
            "properties": {
              "url": { "type": "string", "format": "uri" },
              "width": { "type": "integer" },
              "height": { "type": "integer" },
              "mime_type": { "type": "string", "const": "video/mp4" }
            }
          },
          "price": { "$ref": "#/components/schemas/Price" },
          "detail_url": { "type": "string", "format": "uri" },
          "download_url": { "type": "string", "format": "uri" },
          "sets": { "type": "array", "description": "Published sets that include this asset. Empty when it is in none.", "items": { "$ref": "#/components/schemas/SetRef" } },
          "published_at": { "type": ["string", "null"], "format": "date-time" },
          "license": { "$ref": "#/components/schemas/License" },
          "release_safe": { "type": "boolean", "description": "True: AI-generated and not created to depict any real person, trademark, logo, or private property. No model or property release is needed." },
          "has_text": { "type": ["boolean", "null"], "description": "True when visible letters, numbers, signage, logos, or watermarks were detected. Null when the asset has not been checked yet." },
          "ai_generated": { "type": "boolean", "const": true },
          "ai_disclosure": { "type": "string", "description": "A sentence you can use where AI-generated content must be disclosed.", "examples": ["This image was generated with AI."] }
        }
      },
      "SetRef": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "title": { "type": "string" },
          "detail_url": { "type": "string", "format": "uri" }
        }
      },
      "AssetSet": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "title": { "type": "string" },
          "description": { "type": "string" },
          "item_count": { "type": "integer" },
          "price": { "$ref": "#/components/schemas/Price", "description": "What the whole set costs in one purchase. Never more than items_price." },
          "items_price": { "$ref": "#/components/schemas/Price", "description": "What the items cost bought one by one." },
          "savings": { "$ref": "#/components/schemas/Price", "description": "items_price minus price." },
          "detail_url": { "type": "string", "format": "uri" },
          "download_url": { "type": "string", "format": "uri", "description": "Paid x402 download of every original in the set." },
          "published_at": { "type": ["string", "null"], "format": "date-time" },
          "license": { "$ref": "#/components/schemas/License" },
          "release_safe": { "type": "boolean" },
          "ai_generated": { "type": "boolean", "const": true },
          "items": { "type": "array", "items": { "$ref": "#/components/schemas/Asset" } }
        }
      },
      "SetListResponse": {
        "type": "object",
        "properties": {
          "page": { "type": "integer" },
          "per_page": { "type": "integer" },
          "total": { "type": "integer" },
          "page_count": { "type": "integer" },
          "next": { "type": ["string", "null"], "format": "uri" },
          "previous": { "type": ["string", "null"], "format": "uri" },
          "items": { "type": "array", "items": { "$ref": "#/components/schemas/AssetSet" } },
          "notice": { "$ref": "#/components/schemas/Notice" }
        }
      },
      "License": {
        "type": "object",
        "properties": {
          "name": { "type": "string", "const": "Agent Stock License" },
          "url": { "type": "string", "format": "uri", "examples": ["https://agentstock.dev/license"] },
          "commercial_use": { "type": "boolean" },
          "attribution_required": { "type": "boolean" }
        }
      },
      "SearchResponse": {
        "type": "object",
        "properties": {
          "query": { "type": "string" },
          "mode": { "type": "string", "enum": ["semantic", "latest"] },
          "filters": { "type": "object" },
          "page": { "type": "integer" },
          "per_page": { "type": "integer" },
          "total": { "type": "integer" },
          "page_count": { "type": "integer" },
          "next": { "type": ["string", "null"], "format": "uri" },
          "previous": { "type": ["string", "null"], "format": "uri" },
          "items": { "type": "array", "items": { "$ref": "#/components/schemas/Asset" } },
          "notice": { "$ref": "#/components/schemas/Notice" }
        }
      },
      "Notice": {
        "type": "object",
        "properties": {
          "version": { "type": "string" },
          "title": { "type": "string" },
          "summary": { "type": "string", "description": "One-line statement of the license grant and the AI disclosure." },
          "url": { "type": "string", "format": "uri", "description": "This notice as JSON (/api/v1/notice)." },
          "license_url": { "type": "string", "format": "uri", "description": "The license as an HTML page (/license)." },
          "body": { "type": "string", "description": "Full license text. Only on /api/v1/notice." }
        }
      },
      "PaymentRequired": {
        "type": "object",
        "properties": {
          "x402Version": { "type": "integer", "const": 2 },
          "error": { "type": "string" },
          "resource": { "type": "object" },
          "accepts": { "type": "array", "items": { "type": "object" } },
          "notice": { "$ref": "#/components/schemas/Notice" }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": { "type": "string" },
              "message": { "type": "string" },
              "retry_after": { "type": "integer" }
            }
          }
        }
      }
    }
  }
}
