{
  "openapi": "3.1.0",
  "info": {
    "title": "NoJunk Image",
    "version": "1.0.0",
    "description": "Pay-per-call image intelligence for agents: generate an image from a text prompt (FLUX.1 schnell, PNG bytes or base64 JSON), or describe any image you point at by URL or base64 (LLaVA 1.5 7B, answers your own question about the picture). You are only charged when a valid result is returned.",
    "x-guidance": "Two POST endpoints paid per call in USDC on Base via x402 (you are only charged when a valid result is returned; every 4xx/5xx is free). POST /generate {prompt (3-1500 chars), steps?: 1-8 (default 4), format?: \"png\"|\"json\"} costs $0.01 and runs FLUX.1 schnell; with format=png (default) the 200 response body IS the image (Content-Type image/jpeg or image/png as returned, X-Image-Bytes header), with format=json you get {image_base64, content_type, bytes, prompt_chars, steps, seed (always null), model, generated_at}. Prompts describing sexual content involving minors are refused with 400. POST /describe {image_url} or {image_base64}, question? (default \"Describe this image in detail.\") costs $0.005 and runs LLaVA 1.5 7B (automatic uform-gen2 fallback) -> {description, question, image_bytes, model, generated_at}; image_url must be a public http(s) URL serving image/* up to 10485760 bytes (private/loopback hosts refused, 15 s timeout; non-image -> 415, unreachable -> 502, all unpaid). Request bodies over 8192 bytes (/generate) or 14680064 bytes (/describe) are rejected with 413 before any payment work. Best for: illustrations, thumbnails, product mockups, concept art, social cards; alt-text, captioning, screenshot QA, moderation triage, \"what is in this photo\" questions."
  },
  "servers": [
    {
      "url": "https://nojunk-image.mick8511.workers.dev"
    }
  ],
  "paths": {
    "/generate": {
      "post": {
        "operationId": "generateImage",
        "summary": "Generate an image from a text prompt (FLUX.1 schnell)",
        "tags": [
          "AI",
          "Image",
          "Generation"
        ],
        "x-payment-info": {
          "price": {
            "mode": "fixed",
            "currency": "USD",
            "amount": "0.010000"
          },
          "protocols": [
            {
              "x402": {}
            }
          ]
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "prompt": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 1500,
                    "description": "What to draw. Prompts describing sexual content involving minors are refused with 400 (no charge)."
                  },
                  "steps": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 8,
                    "default": 4,
                    "description": "Diffusion steps; 4 is a good default for FLUX.1 schnell"
                  },
                  "seed": {
                    "type": "integer",
                    "minimum": 0,
                    "deprecated": true,
                    "description": "Deprecated and ignored: FLUX.1 schnell on Workers AI no longer accepts a seed. Still accepted for compatibility; seed is always null in the response."
                  },
                  "format": {
                    "type": "string",
                    "enum": [
                      "png",
                      "json"
                    ],
                    "default": "png",
                    "description": "png: the response body is the image itself (image/png); json: a JSON object with the image as base64"
                  }
                },
                "required": [
                  "prompt"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The generated image. With format=png (default) the body is the raw PNG; with format=json a JSON object carrying the image as base64.",
            "headers": {
              "PAYMENT-RESPONSE": {
                "description": "Base64 x402 settlement receipt",
                "schema": {
                  "type": "string"
                }
              },
              "X-Image-Bytes": {
                "description": "Size of the image in bytes",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Model": {
                "description": "Model that generated the image",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "image_base64": {
                      "type": "string",
                      "description": "The image, base64 encoded"
                    },
                    "content_type": {
                      "type": "string",
                      "description": "MIME type of the decoded image (image/png)"
                    },
                    "bytes": {
                      "type": "integer",
                      "description": "Decoded image size in bytes"
                    },
                    "prompt_chars": {
                      "type": "integer"
                    },
                    "steps": {
                      "type": "integer"
                    },
                    "seed": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "model": {
                      "type": "string"
                    },
                    "generated_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "image_base64",
                    "content_type",
                    "bytes",
                    "prompt_chars",
                    "steps",
                    "seed",
                    "model",
                    "generated_at"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid input, or prompt not allowed (no charge)"
          },
          "402": {
            "description": "Payment Required: the PAYMENT-REQUIRED header carries the base64 x402 requirements; also returned when payment verification or settlement fails (no charge)"
          },
          "413": {
            "description": "Request body larger than 8192 bytes (no charge)"
          },
          "502": {
            "description": "AI model temporarily unavailable or returned an unusable result (no charge)"
          }
        }
      }
    },
    "/describe": {
      "post": {
        "operationId": "describeImage",
        "summary": "Describe or answer a question about an image (LLaVA 1.5 7B)",
        "tags": [
          "AI",
          "Image",
          "Vision",
          "Captioning"
        ],
        "x-payment-info": {
          "price": {
            "mode": "fixed",
            "currency": "USD",
            "amount": "0.005000"
          },
          "protocols": [
            {
              "x402": {}
            }
          ]
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "image_url": {
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2048,
                    "description": "Public http(s) URL of an image (content-type image/*, max 10485760 bytes, 15 s fetch timeout). Private, loopback and internal hosts are refused."
                  },
                  "image_base64": {
                    "type": "string",
                    "description": "Image bytes as base64 (standard or url-safe, data: prefix allowed), max 10485760 decoded bytes; PNG, JPEG, GIF, WebP, BMP, TIFF or HEIC"
                  },
                  "question": {
                    "type": "string",
                    "maxLength": 500,
                    "default": "Describe this image in detail.",
                    "description": "What to answer about the image"
                  }
                },
                "oneOf": [
                  {
                    "required": [
                      "image_url"
                    ]
                  },
                  {
                    "required": [
                      "image_base64"
                    ]
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Result",
            "headers": {
              "PAYMENT-RESPONSE": {
                "description": "Base64 x402 settlement receipt",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "description": {
                      "type": "string",
                      "description": "The model's answer to the question about the image"
                    },
                    "question": {
                      "type": "string"
                    },
                    "image_bytes": {
                      "type": "integer",
                      "description": "Size of the image that was analyzed"
                    },
                    "model": {
                      "type": "string",
                      "description": "Model that produced the answer"
                    },
                    "generated_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "description",
                    "question",
                    "image_bytes",
                    "model",
                    "generated_at"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid input, or prompt not allowed (no charge)"
          },
          "402": {
            "description": "Payment Required: the PAYMENT-REQUIRED header carries the base64 x402 requirements; also returned when payment verification or settlement fails (no charge)"
          },
          "413": {
            "description": "Request body larger than 14680064 bytes, or image larger than 10485760 bytes (no charge)"
          },
          "415": {
            "description": "image_url did not serve an image (content-type not image/*), or image_base64 is not a recognized image format (no charge)"
          },
          "502": {
            "description": "AI model temporarily unavailable or returned an unusable result (no charge)"
          }
        }
      }
    }
  }
}