{
  "openapi": "3.1.0",
  "info": {
    "title": "kino402",
    "version": "0.1.0",
    "summary": "Pay-per-call video generation and speech over x402. The unpaid 402 is the quote.",
    "description": "Frontier text-to-video models and TTS, priced per call in USDC on Base. No account and no API key: an unpaid POST answers 402 with the exact price for the body you sent, and paying that 402 is the whole authentication story. Quote and charge come from one function, so the number advertised is the number that settles.",
    "x-guidance": "kino402 sells frontier text-to-video and text-to-speech per call, in USDC on Base over x402. No account, no API key, no minimum.\n\nTHE QUOTE IS THE 402. POST an unpaid request to /v1/generate or /v1/audio/tts and the 402 that comes back carries the exact price for the body you sent — not a rate card, the number for that call. Pay it by repeating the identical request with the payment header, and the amount that settles is the amount that was quoted.\n\nHeaders: send X-PAYMENT for x402 v1, or PAYMENT-SIGNATURE for x402 v2. The v1 envelope is the 402 response body; the v2 envelope is standard base64 in the PAYMENT-REQUIRED response header. Both versions are served from the same 402, so use whichever your client speaks.\n\nPOST is how you buy. A GET or HEAD on a paid route answers a reference 402 so a prober can read the terms without spending, but a payment presented on GET is refused without settling.\n\n/v1/generate is asynchronous. A paid POST returns {job_id, status_url} once the render is accepted upstream. Poll GET /v1/jobs/{id} — free and unauthenticated — until status is \"completed\" (the mp4 is at video_url) or \"failed\". A clip usually takes 1-6 minutes. The video_url expires: download it promptly.\n\n/v1/audio/tts is synchronous. A paid POST returns the mp3 in the response body.\n\nGET /v1/models carries the full rate card: every model id, its parameter ranges, the rate formula it is priced from, and a worked example price. Read it before you pick a model — the cheapest and the most expensive video call in the catalog differ by more than two orders of magnitude.",
    "contact": {
      "email": "support@kino402.com",
      "url": "https://kino402.com"
    }
  },
  "servers": [
    {
      "url": "https://kino402.com"
    }
  ],
  "paths": {
    "/": {
      "get": {
        "operationId": "getLandingPage",
        "summary": "the landing page",
        "description": "The human surface. Rendered from the same catalog as /v1/models, so its prices are the live ones.",
        "security": [],
        "responses": {
          "200": {
            "description": "the page",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/llms.txt": {
      "get": {
        "operationId": "getLlmsTxt",
        "summary": "the same facts, terse, for a machine reader",
        "description": "Endpoints, payment terms and the rate card as plain text. Cheaper to read than this document if you already know x402.",
        "security": [],
        "responses": {
          "200": {
            "description": "plain text",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/v1/models": {
      "get": {
        "operationId": "getModels",
        "summary": "the full rate card",
        "description": "Every model: id, parameter ranges, the rate formula it is priced from, and a worked example price. This is the catalog every other surface — including this document — is rendered from.",
        "security": [],
        "responses": {
          "200": {
            "description": "the catalog",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "service",
                    "x402_versions",
                    "network",
                    "models"
                  ],
                  "properties": {
                    "service": {
                      "type": "string",
                      "const": "kino402"
                    },
                    "x402_versions": {
                      "type": "array",
                      "items": {
                        "type": "integer"
                      },
                      "description": "the protocol versions this seller accepts"
                    },
                    "network": {
                      "type": "object",
                      "properties": {
                        "v1": {
                          "type": "string"
                        },
                        "v2": {
                          "type": "string"
                        },
                        "asset": {
                          "type": "string"
                        },
                        "symbol": {
                          "type": "string"
                        }
                      }
                    },
                    "pricing": {
                      "type": "string"
                    },
                    "failures": {
                      "type": "string"
                    },
                    "models": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "id",
                          "kind",
                          "title",
                          "vendor",
                          "path",
                          "formula",
                          "example"
                        ],
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "kind": {
                            "type": "string",
                            "enum": [
                              "video",
                              "audio"
                            ]
                          },
                          "title": {
                            "type": "string"
                          },
                          "mark": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "vendor": {
                            "type": "string"
                          },
                          "path": {
                            "type": "string"
                          },
                          "good_at": {
                            "type": "string"
                          },
                          "resolutions": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "default_resolution": {
                            "type": "string"
                          },
                          "duration_s": {
                            "type": "object",
                            "description": "min, max, default, and `only` where the upstream takes an exact list"
                          },
                          "audio": {
                            "type": "boolean"
                          },
                          "max_chars": {
                            "type": "integer"
                          },
                          "default_voice": {
                            "type": "string"
                          },
                          "input": {
                            "type": "string"
                          },
                          "formula": {
                            "type": "string"
                          },
                          "example": {
                            "type": "object",
                            "description": "a worked price: the params, and what they cost",
                            "properties": {
                              "params": {
                                "type": "object"
                              },
                              "price": {
                                "type": "string"
                              },
                              "price_atomic_usdc": {
                                "type": "string"
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/openapi.json": {
      "get": {
        "operationId": "getOpenApi",
        "summary": "this document",
        "description": "Rendered from the catalog on each request, so the prices and enums here are the live ones.",
        "security": [],
        "responses": {
          "200": {
            "description": "this document",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/robots.txt": {
      "get": {
        "operationId": "getRobotsTxt",
        "summary": "crawl policy",
        "description": "Everything is allowed.",
        "security": [],
        "responses": {
          "200": {
            "description": "plain text",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/og.svg": {
      "get": {
        "operationId": "getOgCard",
        "summary": "the share card",
        "description": "The social card as SVG.",
        "security": [],
        "responses": {
          "200": {
            "description": "an SVG image",
            "content": {
              "image/svg+xml": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/v1/generate": {
      "post": {
        "operationId": "generateVideo",
        "summary": "buy a video render",
        "description": "Unpaid: 402 carrying the exact quote for this body. Paid: the job is submitted upstream and you get {job_id, status_url} back — poll the status url for the mp4. Payment settles once the job is accepted, not when it finishes; a job that fails is resubmitted once automatically. A GET or HEAD here answers a reference 402 for probing, but the sale happens on POST.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "unknown keys are ignored by the service; they are excluded here so a client can catch its own typos",
                "required": [
                  "model",
                  "prompt"
                ],
                "additionalProperties": false,
                "properties": {
                  "model": {
                    "type": "string",
                    "enum": [
                      "seedance-2.0",
                      "seedance-2.0-mini",
                      "seedance-2.5",
                      "seedance-1.5-pro",
                      "kling-2.5-turbo-pro",
                      "hailuo-02-standard"
                    ],
                    "description": "which video model renders the shot. GET /v1/models for what each one is good at."
                  },
                  "prompt": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 2000,
                    "description": "the shot, in words"
                  },
                  "duration_s": {
                    "type": "integer",
                    "minimum": 4,
                    "maximum": 30,
                    "description": "seconds, whole numbers only, and the range is per model — seedance-2.0 4-15s; seedance-2.0-mini 4-15s; seedance-2.5 4-30s; seedance-1.5-pro 4-12s; kling-2.5-turbo-pro exactly 5 or 10s; hailuo-02-standard exactly 6 or 10s. Omitted: seedance-2.0 5s at 720p; seedance-2.0-mini 5s at 720p; seedance-2.5 5s at 720p; seedance-1.5-pro 5s at 720p; kling-2.5-turbo-pro 5s at 1080p; hailuo-02-standard 6s at 768p."
                  },
                  "resolution": {
                    "type": "string",
                    "enum": [
                      "480p",
                      "720p",
                      "1080p",
                      "768p"
                    ],
                    "description": "not every model takes every resolution — seedance-2.0 480p/720p; seedance-2.0-mini 480p/720p; seedance-2.5 480p/720p; seedance-1.5-pro 480p/720p; kling-2.5-turbo-pro 1080p; hailuo-02-standard 768p. Omitted: the model's default."
                  },
                  "audio": {
                    "type": "boolean",
                    "default": false,
                    "description": "generate a soundtrack. Only seedance-1.5-pro can; asking any other model for audio is a 400."
                  },
                  "image_urls": {
                    "type": "array",
                    "maxItems": 4,
                    "items": {
                      "type": "string",
                      "format": "uri",
                      "pattern": "^https://"
                    },
                    "description": "up to four https reference images for conditioning. They must be publicly fetchable."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "the job was accepted and payment is settling behind this response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "job_id",
                    "status",
                    "status_url",
                    "model",
                    "price"
                  ],
                  "properties": {
                    "job_id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "const": "queued"
                    },
                    "status_url": {
                      "type": "string",
                      "format": "uri",
                      "description": "GET this to collect the video. Free."
                    },
                    "model": {
                      "type": "string"
                    },
                    "params": {
                      "type": "object"
                    },
                    "price": {
                      "type": "object",
                      "description": "the price in words. The same number as the envelope, from the same call to priceFor().",
                      "properties": {
                        "usd": {
                          "type": "string",
                          "examples": [
                            "$0.42"
                          ]
                        },
                        "atomic_usdc": {
                          "type": "string",
                          "description": "the amount that settles, in USDC base units (6 decimals)"
                        },
                        "asset": {
                          "type": "string",
                          "examples": [
                            "USDC on Base"
                          ]
                        },
                        "formula": {
                          "type": "string",
                          "description": "the rate that reproduces the price"
                        }
                      }
                    },
                    "poll": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "the parameters do not price. Nothing was charged, even if a payment was presented.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "what went wrong, in prose"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "402": {
            "description": "Payment Required",
            "headers": {
              "PAYMENT-REQUIRED": {
                "description": "the x402 v2 envelope, standard base64 of JSON. A v1 client ignores it and reads the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "x402Version",
                    "accepts"
                  ],
                  "properties": {
                    "x402Version": {
                      "type": "integer",
                      "const": 1
                    },
                    "error": {
                      "type": "string"
                    },
                    "quote": {
                      "type": "object",
                      "description": "the price in words. The same number as the envelope, from the same call to priceFor().",
                      "properties": {
                        "usd": {
                          "type": "string",
                          "examples": [
                            "$0.42"
                          ]
                        },
                        "atomic_usdc": {
                          "type": "string",
                          "description": "the amount that settles, in USDC base units (6 decimals)"
                        },
                        "asset": {
                          "type": "string",
                          "examples": [
                            "USDC on Base"
                          ]
                        },
                        "formula": {
                          "type": "string",
                          "description": "the rate that reproduces the price"
                        }
                      }
                    },
                    "accepts": {
                      "type": "array",
                      "minItems": 1,
                      "items": {
                        "type": "object",
                        "required": [
                          "scheme",
                          "network",
                          "maxAmountRequired",
                          "resource",
                          "payTo",
                          "asset"
                        ],
                        "properties": {
                          "scheme": {
                            "type": "string",
                            "const": "exact"
                          },
                          "network": {
                            "type": "string",
                            "const": "base"
                          },
                          "maxAmountRequired": {
                            "type": "string",
                            "description": "the quote, in USDC base units. This is the amount that settles."
                          },
                          "resource": {
                            "type": "string",
                            "format": "uri"
                          },
                          "description": {
                            "type": "string"
                          },
                          "mimeType": {
                            "type": "string"
                          },
                          "payTo": {
                            "type": "string",
                            "description": "the receiving address on Base"
                          },
                          "maxTimeoutSeconds": {
                            "type": "integer"
                          },
                          "asset": {
                            "type": "string",
                            "description": "the USDC contract on Base"
                          },
                          "extra": {
                            "type": "object",
                            "description": "the token's EIP-712 domain"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "the request body is larger than the 16 KB limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "what went wrong, in prose"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "503": {
            "description": "payments cannot be verified right now, so nothing was produced and nothing was charged. Retry in a few minutes.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "what went wrong, in prose"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          }
        },
        "x-payment-info": {
          "protocols": [
            {
              "x402": {}
            }
          ],
          "price": {
            "mode": "dynamic",
            "currency": "USD",
            "min": "0.056",
            "max": "16.641"
          }
        }
      }
    },
    "/v1/jobs/{id}": {
      "get": {
        "operationId": "getJob",
        "summary": "poll a render",
        "security": [],
        "description": "Free and unauthenticated — knowing the job id is what entitles you to the result. Poll until status is \"completed\" (video_url is set) or \"failed\". Typically 1-6 minutes. The video_url expires.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "the job_id returned by POST /v1/generate",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9]{8,64}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "the job as it stands",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "job_id",
                    "status",
                    "model",
                    "price",
                    "created_at",
                    "status_url",
                    "retries"
                  ],
                  "properties": {
                    "job_id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "queued",
                        "running",
                        "completed",
                        "failed"
                      ]
                    },
                    "model": {
                      "type": "string"
                    },
                    "params": {
                      "type": "object",
                      "description": "the parameters the price was quoted for"
                    },
                    "price": {
                      "type": "object",
                      "properties": {
                        "usd": {
                          "type": "string"
                        },
                        "atomic_usdc": {
                          "type": "string"
                        }
                      }
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "status_url": {
                      "type": "string",
                      "format": "uri"
                    },
                    "retries": {
                      "type": "integer",
                      "description": "0 if it worked first time, 1 if it was resubmitted automatically"
                    },
                    "video_url": {
                      "type": "string",
                      "format": "uri",
                      "description": "present when status is \"completed\". An expiring link — download it promptly."
                    },
                    "refund_due": {
                      "type": "boolean",
                      "description": "present when status is \"failed\""
                    },
                    "note": {
                      "type": "string",
                      "description": "present when status is \"failed\""
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "no such job",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "what went wrong, in prose"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/tts": {
      "post": {
        "operationId": "synthesizeSpeech",
        "summary": "buy a speech track",
        "description": "Synchronous. Unpaid: 402 carrying the exact quote for the character count of `text`. Paid: the mp3 is the response body, and settlement runs behind it. A GET or HEAD answers a reference 402 for probing; the sale happens on POST.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "text"
                ],
                "additionalProperties": false,
                "properties": {
                  "text": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 5000,
                    "description": "what to say. Priced per character of THIS string — $0.00024 per character."
                  },
                  "voice": {
                    "type": "string",
                    "pattern": "^[A-Za-z0-9_-]{1,64}$",
                    "default": "21m00Tcm4TlvDq8ikWAM",
                    "description": "an ElevenLabs voice id. Omitted: 21m00Tcm4TlvDq8ikWAM."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "the spoken audio",
            "content": {
              "audio/mpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            },
            "headers": {
              "x-kino-price": {
                "description": "what this call cost, in dollars",
                "schema": {
                  "type": "string"
                }
              },
              "x-kino-characters": {
                "description": "the character count it was priced from",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "the parameters do not price. Nothing was charged, even if a payment was presented.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "what went wrong, in prose"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "402": {
            "description": "Payment Required",
            "headers": {
              "PAYMENT-REQUIRED": {
                "description": "the x402 v2 envelope, standard base64 of JSON. A v1 client ignores it and reads the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "x402Version",
                    "accepts"
                  ],
                  "properties": {
                    "x402Version": {
                      "type": "integer",
                      "const": 1
                    },
                    "error": {
                      "type": "string"
                    },
                    "quote": {
                      "type": "object",
                      "description": "the price in words. The same number as the envelope, from the same call to priceFor().",
                      "properties": {
                        "usd": {
                          "type": "string",
                          "examples": [
                            "$0.42"
                          ]
                        },
                        "atomic_usdc": {
                          "type": "string",
                          "description": "the amount that settles, in USDC base units (6 decimals)"
                        },
                        "asset": {
                          "type": "string",
                          "examples": [
                            "USDC on Base"
                          ]
                        },
                        "formula": {
                          "type": "string",
                          "description": "the rate that reproduces the price"
                        }
                      }
                    },
                    "accepts": {
                      "type": "array",
                      "minItems": 1,
                      "items": {
                        "type": "object",
                        "required": [
                          "scheme",
                          "network",
                          "maxAmountRequired",
                          "resource",
                          "payTo",
                          "asset"
                        ],
                        "properties": {
                          "scheme": {
                            "type": "string",
                            "const": "exact"
                          },
                          "network": {
                            "type": "string",
                            "const": "base"
                          },
                          "maxAmountRequired": {
                            "type": "string",
                            "description": "the quote, in USDC base units. This is the amount that settles."
                          },
                          "resource": {
                            "type": "string",
                            "format": "uri"
                          },
                          "description": {
                            "type": "string"
                          },
                          "mimeType": {
                            "type": "string"
                          },
                          "payTo": {
                            "type": "string",
                            "description": "the receiving address on Base"
                          },
                          "maxTimeoutSeconds": {
                            "type": "integer"
                          },
                          "asset": {
                            "type": "string",
                            "description": "the USDC contract on Base"
                          },
                          "extra": {
                            "type": "object",
                            "description": "the token's EIP-712 domain"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "the request body is larger than the 16 KB limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "what went wrong, in prose"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "503": {
            "description": "payments cannot be verified right now, so nothing was produced and nothing was charged. Retry in a few minutes.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "what went wrong, in prose"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          }
        },
        "x-payment-info": {
          "protocols": [
            {
              "x402": {}
            }
          ],
          "price": {
            "mode": "dynamic",
            "currency": "USD",
            "min": "0.001",
            "max": "1.2"
          }
        }
      }
    }
  }
}
