{
  "components": {
    "securitySchemes": {
      "adminSession": {
        "description": "Internal admin session cookie (separate secret and origin).",
        "in": "cookie",
        "name": "mha_session",
        "type": "apiKey"
      },
      "bearerAuth": {
        "bearerFormat": "mh_live_<32 base62> | mh_test_<32 base62>",
        "description": "An API key from the dashboard. The prefix selects live or test mode.",
        "scheme": "bearer",
        "type": "http"
      },
      "dashboardSession": {
        "description": "Partner dashboard session cookie, set by the sign-in routes.",
        "in": "cookie",
        "name": "mh_session",
        "type": "apiKey"
      }
    },
    "schemas": {
      "ErrorCode": {
        "description": "Public error codes. Serialised as the `ErrorCode` schema in the contract.",
        "enum": [
          "invalid_request",
          "route_not_found",
          "invalid_api_key",
          "api_key_expired",
          "api_key_revoked",
          "api_key_disabled",
          "insufficient_scope",
          "account_pending_review",
          "account_suspended",
          "insufficient_balance",
          "rate_limited",
          "queue_full",
          "effect_not_found",
          "effect_disabled",
          "variant_unavailable",
          "invalid_input",
          "file_not_found",
          "image_unreadable",
          "image_too_large",
          "unsupported_media_type",
          "input_rejected",
          "webhook_url_rejected",
          "idempotency_key_required",
          "idempotency_key_mismatch",
          "idempotency_in_progress",
          "generation_not_found",
          "generation_not_cancelable",
          "upstream_unavailable",
          "internal_error"
        ],
        "type": "string"
      },
      "PriceChangedEvent": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/PriceChangedData"
          },
          "mode": {
            "anyOf": [
              {
                "enum": [
                  "live",
                  "test"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "sequence": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Per-object monotonic counter; drop an event whose sequence is lower than one you processed."
          },
          "timestamp": {
            "description": "When the event happened (not the attempt).",
            "format": "date-time",
            "type": "string"
          },
          "type": {
            "const": "price.changed",
            "type": "string"
          }
        },
        "required": [
          "type",
          "timestamp",
          "data"
        ],
        "type": "object"
      },
      "PriceChangedData": {
        "properties": {
          "changes": {
            "items": {
              "$ref": "#/components/schemas/PriceChange"
            },
            "type": "array"
          },
          "effective_at": {
            "format": "date-time",
            "type": "string"
          },
          "version": {
            "type": "integer"
          }
        },
        "required": [
          "version",
          "effective_at",
          "changes"
        ],
        "type": "object"
      },
      "PriceChange": {
        "properties": {
          "effect": {
            "type": "string"
          },
          "new_price_micros": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "old_price_micros": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "variant_key": {
            "type": "string"
          }
        },
        "required": [
          "effect",
          "variant_key",
          "old_price_micros",
          "new_price_micros"
        ],
        "type": "object"
      },
      "GenerationEvent": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Generation"
          },
          "mode": {
            "anyOf": [
              {
                "enum": [
                  "live",
                  "test"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "sequence": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Per-object monotonic counter; drop an event whose sequence is lower than one you processed."
          },
          "timestamp": {
            "description": "When the event happened (not the attempt).",
            "format": "date-time",
            "type": "string"
          },
          "type": {
            "enum": [
              "generation.queued",
              "generation.started",
              "generation.succeeded",
              "generation.failed",
              "generation.canceled"
            ],
            "type": "string"
          }
        },
        "required": [
          "type",
          "timestamp",
          "data"
        ],
        "type": "object"
      },
      "Generation": {
        "properties": {
          "api_key_prefix": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "examples": [
              "mh_live_4Hk2"
            ]
          },
          "charged_micros": {
            "description": "0 until captured; equals price_micros after success (or a cancel after start).",
            "format": "int64",
            "type": "integer"
          },
          "client_reference_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "created_at": {
            "format": "date-time",
            "type": "string"
          },
          "effect": {
            "type": "string"
          },
          "error": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/GenerationError"
              },
              {
                "type": "null"
              }
            ]
          },
          "execution_seconds": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ]
          },
          "expires_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "When outputs are deleted (30 days after finish)."
          },
          "finished_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "id": {
            "examples": [
              "gen_7c2x9q0k3m1z8b4v6n5p2r0t"
            ],
            "type": "string"
          },
          "metadata": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ]
          },
          "mode": {
            "enum": [
              "live",
              "test"
            ],
            "type": "string"
          },
          "object": {
            "const": "generation",
            "type": "string"
          },
          "outputs": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/GenerationOutput"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ]
          },
          "price_list_version": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "price_micros": {
            "description": "Held at create.",
            "format": "int64",
            "type": "integer"
          },
          "queue_seconds": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ]
          },
          "started_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "status": {
            "$ref": "#/components/schemas/GenerationStatus"
          },
          "type": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/EffectType"
              },
              {
                "type": "null"
              }
            ]
          },
          "variant": {
            "$ref": "#/components/schemas/Variant"
          },
          "variant_key": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "id",
          "object",
          "status",
          "mode",
          "effect",
          "variant",
          "price_micros",
          "charged_micros",
          "created_at"
        ],
        "type": "object"
      },
      "Variant": {
        "description": "One priced combination. Video uses all four axes; image uses\n`resolution` only (`1mp`/`2mp`); storyboard uses `location` and\n`resolution` (`432p`/`576p`/`720p`).",
        "properties": {
          "audio": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ]
          },
          "duration": {
            "anyOf": [
              {
                "enum": [
                  "5s",
                  "10s",
                  "15s",
                  "30s",
                  "60s"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "location": {
            "anyOf": [
              {
                "maxLength": 64,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Storyboards: the key of the location this variant renders."
          },
          "prep": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "description": "Frame preparation before animation."
          },
          "resolution": {
            "anyOf": [
              {
                "enum": [
                  "432p",
                  "512p",
                  "576p",
                  "640p",
                  "720p",
                  "768p",
                  "1mp",
                  "2mp"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "type": "object"
      },
      "EffectType": {
        "enum": [
          "video",
          "image",
          "storyboard"
        ],
        "type": "string"
      },
      "GenerationStatus": {
        "enum": [
          "queued",
          "processing",
          "succeeded",
          "failed",
          "canceled"
        ],
        "type": "string"
      },
      "GenerationOutput": {
        "properties": {
          "bytes": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "duration_seconds": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ]
          },
          "expires_at": {
            "format": "date-time",
            "type": "string"
          },
          "height": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "kind": {
            "enum": [
              "video",
              "image",
              "thumbnail"
            ],
            "type": "string"
          },
          "mime_type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "url": {
            "description": "Signed; valid 1 h.",
            "format": "uri",
            "type": "string"
          },
          "width": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "kind",
          "url",
          "expires_at"
        ],
        "type": "object"
      },
      "GenerationError": {
        "properties": {
          "code": {
            "enum": [
              "input_rejected",
              "gpu_failure",
              "timeout",
              "upstream_unavailable",
              "internal_error",
              "effect_retired"
            ],
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "code",
          "message"
        ],
        "type": "object"
      },
      "EffectEvent": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Effect"
          },
          "mode": {
            "anyOf": [
              {
                "enum": [
                  "live",
                  "test"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "sequence": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Per-object monotonic counter; drop an event whose sequence is lower than one you processed."
          },
          "timestamp": {
            "description": "When the event happened (not the attempt).",
            "format": "date-time",
            "type": "string"
          },
          "type": {
            "enum": [
              "effect.published",
              "effect.retired"
            ],
            "type": "string"
          }
        },
        "required": [
          "type",
          "timestamp",
          "data"
        ],
        "type": "object"
      },
      "Effect": {
        "properties": {
          "assets": {
            "$ref": "#/components/schemas/EffectAssets"
          },
          "blend": {
            "default": false,
            "description": "Two input photos, two people, one video.",
            "type": "boolean"
          },
          "category": {
            "description": "One of the production categories (sex, oral, cum, solo, group, fetish).",
            "type": "string"
          },
          "description": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LocalizedText"
              },
              {
                "type": "null"
              }
            ]
          },
          "enabled": {
            "description": "Enabled for the calling tenant.",
            "type": "boolean"
          },
          "id": {
            "examples": [
              "eff_01hx2c9q7f3k"
            ],
            "type": "string"
          },
          "inputs": {
            "items": {
              "$ref": "#/components/schemas/InputSlot"
            },
            "type": "array"
          },
          "locations": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/EffectLocation"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Storyboards: the locations a variant can render."
          },
          "name": {
            "$ref": "#/components/schemas/LocalizedText"
          },
          "orientation": {
            "$ref": "#/components/schemas/Orientation"
          },
          "popularity_tier": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PopularityTier"
              },
              {
                "type": "null"
              }
            ]
          },
          "published_at": {
            "format": "date-time",
            "type": "string"
          },
          "retires_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "slug": {
            "type": "string"
          },
          "success_rate": {
            "anyOf": [
              {
                "maximum": 1,
                "minimum": 0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ]
          },
          "type": {
            "$ref": "#/components/schemas/EffectType"
          },
          "variants": {
            "items": {
              "$ref": "#/components/schemas/PricedVariant"
            },
            "type": "array"
          }
        },
        "required": [
          "id",
          "slug",
          "type",
          "name",
          "category",
          "orientation",
          "inputs",
          "variants",
          "assets",
          "enabled",
          "published_at"
        ],
        "type": "object"
      },
      "PricedVariant": {
        "properties": {
          "audio": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ]
          },
          "duration": {
            "anyOf": [
              {
                "enum": [
                  "5s",
                  "10s",
                  "15s",
                  "30s",
                  "60s"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "location": {
            "anyOf": [
              {
                "maxLength": 64,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Storyboards: the key of the location this variant renders."
          },
          "prep": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "description": "Frame preparation before animation."
          },
          "price_micros": {
            "format": "int64",
            "minimum": 0,
            "type": "integer"
          },
          "resolution": {
            "anyOf": [
              {
                "enum": [
                  "432p",
                  "512p",
                  "576p",
                  "640p",
                  "720p",
                  "768p",
                  "1mp",
                  "2mp"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "typical_seconds": {
            "description": "p50 request-to-result over the last 30 days.",
            "type": "integer"
          },
          "variant_key": {
            "description": "Canonical key, e.g. `5s.640p.audio.noprep`.",
            "type": "string"
          }
        },
        "required": [
          "variant_key",
          "price_micros",
          "typical_seconds"
        ],
        "type": "object"
      },
      "PopularityTier": {
        "enum": [
          "top10",
          "trending",
          "new"
        ],
        "type": "string"
      },
      "Orientation": {
        "enum": [
          "straight",
          "gay"
        ],
        "type": "string"
      },
      "EffectLocation": {
        "properties": {
          "key": {
            "examples": [
              "beach"
            ],
            "type": "string"
          },
          "name": {
            "$ref": "#/components/schemas/LocalizedText"
          },
          "poster_url": {
            "anyOf": [
              {
                "format": "uri",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "preview_mp4_url": {
            "anyOf": [
              {
                "format": "uri",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "key",
          "name"
        ],
        "type": "object"
      },
      "LocalizedText": {
        "properties": {
          "de": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "en": {
            "type": "string"
          },
          "es": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "ru": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "en"
        ],
        "type": "object"
      },
      "InputSlot": {
        "properties": {
          "description": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LocalizedText"
              },
              {
                "type": "null"
              }
            ]
          },
          "kind": {
            "const": "image",
            "type": "string"
          },
          "min_short_side_px": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "name": {
            "examples": [
              "image"
            ],
            "type": "string"
          },
          "required": {
            "type": "boolean"
          }
        },
        "required": [
          "name",
          "kind",
          "required"
        ],
        "type": "object"
      },
      "EffectAssets": {
        "properties": {
          "example_inputs": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/EffectExampleInput"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Sample input photos, so input and output can be shown side by side."
          },
          "poster_sfw_url": {
            "anyOf": [
              {
                "format": "uri",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "poster_url": {
            "format": "uri",
            "type": "string"
          },
          "preview_mp4_url": {
            "anyOf": [
              {
                "format": "uri",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "preview_webp_url": {
            "anyOf": [
              {
                "format": "uri",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "renditions": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/EffectRendition"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "poster_url"
        ],
        "type": "object"
      },
      "EffectRendition": {
        "properties": {
          "format": {
            "enum": [
              "mp4",
              "webm",
              "webp",
              "jpg"
            ],
            "type": "string"
          },
          "height": {
            "type": "integer"
          },
          "url": {
            "format": "uri",
            "type": "string"
          },
          "width": {
            "type": "integer"
          }
        },
        "required": [
          "url",
          "width",
          "height",
          "format"
        ],
        "type": "object"
      },
      "EffectExampleInput": {
        "properties": {
          "position": {
            "description": "The input it shows: 1, or 2 on a blend.",
            "maximum": 2,
            "minimum": 1,
            "type": "integer"
          },
          "url": {
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "position",
          "url"
        ],
        "type": "object"
      },
      "BalanceEvent": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/BalanceEventData"
          },
          "mode": {
            "anyOf": [
              {
                "enum": [
                  "live",
                  "test"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "sequence": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Per-object monotonic counter; drop an event whose sequence is lower than one you processed."
          },
          "timestamp": {
            "description": "When the event happened (not the attempt).",
            "format": "date-time",
            "type": "string"
          },
          "type": {
            "enum": [
              "balance.low",
              "balance.topped_up"
            ],
            "type": "string"
          }
        },
        "required": [
          "type",
          "timestamp",
          "data"
        ],
        "type": "object"
      },
      "BalanceEventData": {
        "properties": {
          "available_micros": {
            "format": "int64",
            "type": "integer"
          },
          "balance_micros": {
            "format": "int64",
            "type": "integer"
          },
          "threshold_micros": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "topup": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/BalanceTopup"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "balance_micros",
          "available_micros"
        ],
        "type": "object"
      },
      "BalanceTopup": {
        "properties": {
          "amount_micros": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "currency_paid": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "examples": [
              "USDTTRC20"
            ]
          },
          "invoice_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "type": "object"
      },
      "Usage": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/UsageBucket"
            },
            "type": "array"
          },
          "end": {
            "format": "date-time",
            "type": "string"
          },
          "granularity": {
            "enum": [
              "hour",
              "day"
            ],
            "type": "string"
          },
          "object": {
            "const": "usage",
            "type": "string"
          },
          "start": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "object",
          "start",
          "end",
          "granularity",
          "data"
        ],
        "type": "object"
      },
      "UsageBucket": {
        "properties": {
          "canceled": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "failed": {
            "type": "integer"
          },
          "generations": {
            "type": "integer"
          },
          "group": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The group_by value, or null."
          },
          "p50_seconds": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ]
          },
          "p95_seconds": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ]
          },
          "spend_micros": {
            "format": "int64",
            "type": "integer"
          },
          "start": {
            "format": "date-time",
            "type": "string"
          },
          "succeeded": {
            "type": "integer"
          }
        },
        "required": [
          "start",
          "spend_micros",
          "generations",
          "succeeded",
          "failed"
        ],
        "type": "object"
      },
      "PriceList": {
        "properties": {
          "currency": {
            "const": "USD",
            "type": "string"
          },
          "data": {
            "items": {
              "$ref": "#/components/schemas/Price"
            },
            "type": "array"
          },
          "effective_at": {
            "format": "date-time",
            "type": "string"
          },
          "next": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PriceListNext"
              },
              {
                "type": "null"
              }
            ],
            "description": "A scheduled next version, if one is announced."
          },
          "object": {
            "const": "price_list",
            "type": "string"
          },
          "version": {
            "type": "integer"
          }
        },
        "required": [
          "object",
          "version",
          "effective_at",
          "currency",
          "data"
        ],
        "type": "object"
      },
      "PriceListNext": {
        "properties": {
          "effective_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "version": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "type": "object"
      },
      "Price": {
        "properties": {
          "effect": {
            "description": "Effect slug.",
            "type": "string"
          },
          "price_micros": {
            "format": "int64",
            "type": "integer"
          },
          "variant_key": {
            "type": "string"
          }
        },
        "required": [
          "effect",
          "variant_key",
          "price_micros"
        ],
        "type": "object"
      },
      "Problem": {
        "additionalProperties": true,
        "description": "RFC 9457 problem details, extended.",
        "properties": {
          "code": {
            "$ref": "#/components/schemas/ErrorCode"
          },
          "detail": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Human-readable; may change. Never parse it."
          },
          "errors": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/ProblemFieldError"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Field-level details on `invalid_input`."
          },
          "instance": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The request path."
          },
          "param": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Dotted path of the offending field, e.g. `variant.duration`."
          },
          "reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Sub-reason, where a code defines one. Not set on `input_rejected`."
          },
          "request_id": {
            "type": "string"
          },
          "status": {
            "maximum": 599,
            "minimum": 400,
            "type": "integer"
          },
          "title": {
            "description": "Stable per code.",
            "type": "string"
          },
          "type": {
            "description": "`https://api.moan.hot/docs/errors#{code}`.",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "type",
          "title",
          "status",
          "code",
          "request_id"
        ],
        "type": "object"
      },
      "ProblemFieldError": {
        "properties": {
          "message": {
            "type": "string"
          },
          "param": {
            "type": "string"
          }
        },
        "required": [
          "param",
          "message"
        ],
        "type": "object"
      },
      "GenerationCreate": {
        "additionalProperties": false,
        "properties": {
          "client_reference_id": {
            "anyOf": [
              {
                "maxLength": 128,
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "effect": {
            "description": "Effect slug.",
            "type": "string"
          },
          "inputs": {
            "additionalProperties": {
              "$ref": "#/components/schemas/ImageInput"
            },
            "description": "Keyed by input slot name.",
            "minProperties": 1,
            "type": "object"
          },
          "metadata": {
            "anyOf": [
              {
                "additionalProperties": {
                  "maxLength": 500,
                  "type": "string"
                },
                "maxProperties": 20,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Up to 20 string pairs, keys ≤ 40 chars, values ≤ 500 chars. Echoed back."
          },
          "variant": {
            "$ref": "#/components/schemas/Variant"
          },
          "webhook_url": {
            "anyOf": [
              {
                "format": "uri",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Extra https destination for this generation's `generation.*` events only, signed with the account's ad-hoc secret. Registered endpoints still receive their subscribed events."
          }
        },
        "required": [
          "effect",
          "variant",
          "inputs"
        ],
        "type": "object"
      },
      "ImageInput": {
        "description": "A `file_` id from `POST /files`, or an https URL we fetch once (SSRF-guarded, 20 MB cap).",
        "examples": [
          "file_3kq9c0m2x7z1b8v4n6p5r2t0",
          "https://cdn.example.com/u/123.jpg"
        ],
        "type": "string"
      },
      "GenerationList": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/Generation"
            },
            "type": "array"
          },
          "has_more": {
            "type": "boolean"
          },
          "object": {
            "const": "list",
            "type": "string"
          }
        },
        "required": [
          "object",
          "data",
          "has_more"
        ],
        "type": "object"
      },
      "File": {
        "properties": {
          "bytes": {
            "type": "integer"
          },
          "created_at": {
            "format": "date-time",
            "type": "string"
          },
          "expires_at": {
            "format": "date-time",
            "type": "string"
          },
          "height": {
            "type": "integer"
          },
          "id": {
            "examples": [
              "file_3kq9c0m2x7z1b8v4n6p5r2t0"
            ],
            "type": "string"
          },
          "mime_type": {
            "enum": [
              "image/jpeg",
              "image/png",
              "image/webp"
            ],
            "type": "string"
          },
          "object": {
            "const": "file",
            "type": "string"
          },
          "sha256": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "width": {
            "type": "integer"
          }
        },
        "required": [
          "id",
          "object",
          "bytes",
          "mime_type",
          "width",
          "height",
          "created_at",
          "expires_at"
        ],
        "type": "object"
      },
      "Body_uploadFile": {
        "properties": {
          "file": {
            "contentMediaType": "application/octet-stream",
            "description": "The image bytes.",
            "type": "string"
          },
          "purpose": {
            "const": "generation_input",
            "default": "generation_input",
            "type": "string"
          }
        },
        "required": [
          "file"
        ],
        "type": "object"
      },
      "EffectList": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/Effect"
            },
            "type": "array"
          },
          "has_more": {
            "type": "boolean"
          },
          "object": {
            "const": "list",
            "type": "string"
          }
        },
        "required": [
          "object",
          "data",
          "has_more"
        ],
        "type": "object"
      },
      "Account": {
        "properties": {
          "available_micros": {
            "description": "balance minus held.",
            "format": "int64",
            "type": "integer"
          },
          "balance_micros": {
            "description": "Sum of ledger entries.",
            "format": "int64",
            "type": "integer"
          },
          "held_micros": {
            "format": "int64",
            "type": "integer"
          },
          "id": {
            "examples": [
              "ten_01hx2c9q7f3k"
            ],
            "type": "string"
          },
          "limits": {
            "$ref": "#/components/schemas/AccountLimits"
          },
          "low_balance_threshold_micros": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "mode": {
            "description": "The calling key's mode.",
            "enum": [
              "live",
              "test"
            ],
            "type": "string"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "object": {
            "const": "account",
            "type": "string"
          },
          "status": {
            "enum": [
              "pending",
              "active",
              "suspended",
              "rejected"
            ],
            "type": "string"
          }
        },
        "required": [
          "id",
          "object",
          "status",
          "mode",
          "balance_micros",
          "held_micros",
          "available_micros",
          "limits"
        ],
        "type": "object"
      },
      "AccountLimits": {
        "properties": {
          "max_concurrent": {
            "description": "Equals the account's RunPod worker cap.",
            "type": "integer"
          },
          "queue_cap": {
            "type": "integer"
          },
          "queued": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "requests_per_minute": {
            "type": "integer"
          },
          "running": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "requests_per_minute",
          "max_concurrent",
          "queue_cap"
        ],
        "type": "object"
      }
    },
    "responses": {
      "ServiceUnavailable": {
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        },
        "description": "`upstream_unavailable` (storage or GPU control plane down).",
        "headers": {
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          }
        }
      },
      "Conflict": {
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        },
        "description": "Idempotency conflict or a state that forbids the operation."
      },
      "PaymentRequired": {
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        },
        "description": "The balance cannot cover the hold (`insufficient_balance`)."
      },
      "UnsupportedMediaType": {
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        },
        "description": "`unsupported_media_type`."
      },
      "PayloadTooLarge": {
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        },
        "description": "`image_too_large`."
      },
      "BadRequest": {
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        },
        "description": "Malformed request (`invalid_request`, `idempotency_key_required`)."
      },
      "NotFound": {
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        },
        "description": "The effect, file or generation does not exist for this tenant and mode."
      },
      "UnprocessableEntity": {
        "content": {
          "application/problem+json": {
            "example": {
              "code": "input_rejected",
              "detail": "The input could not be processed. You were not charged.",
              "param": "inputs.image",
              "request_id": "req_2b7xk1v0p9q3s4",
              "status": 422,
              "title": "Input rejected",
              "type": "https://api.moan.hot/docs/errors#input_rejected"
            },
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        },
        "description": "Well-formed but invalid (`invalid_input`, `variant_unavailable`, `image_unreadable`, `input_rejected`, `webhook_url_rejected`)."
      },
      "InternalError": {
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        },
        "description": "`internal_error`. Retry with backoff and the same Idempotency-Key."
      },
      "TooManyRequests": {
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        },
        "description": "`rate_limited` or `queue_full`.",
        "headers": {
          "RateLimit": {
            "$ref": "#/components/headers/RateLimit"
          },
          "RateLimit-Policy": {
            "$ref": "#/components/headers/RateLimitPolicy"
          },
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          }
        }
      },
      "Forbidden": {
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        },
        "description": "Scope, account state or disabled effect."
      },
      "Unauthorized": {
        "content": {
          "application/problem+json": {
            "example": {
              "code": "invalid_api_key",
              "detail": "The API key is missing or not recognised.",
              "request_id": "req_8f3kq0c2m1x9z7",
              "status": 401,
              "title": "Invalid API key",
              "type": "https://api.moan.hot/docs/errors#invalid_api_key"
            },
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        },
        "description": "Missing, unknown, expired or revoked key."
      }
    },
    "headers": {
      "RetryAfter": {
        "description": "Seconds to wait before retrying.",
        "schema": {
          "minimum": 1,
          "type": "integer"
        }
      },
      "IdempotentReplayed": {
        "description": "`true` when this response is the stored answer to an earlier request with the same key.",
        "schema": {
          "enum": [
            "true",
            "false"
          ],
          "type": "string"
        }
      },
      "RequestId": {
        "description": "Our id for this request; quote it to support. Also in every Problem body.",
        "schema": {
          "examples": [
            "req_8f3kq0c2m1x9z7"
          ],
          "type": "string"
        }
      },
      "RateLimitPolicy": {
        "description": "e.g. `\"default\";q=60;w=60` (60 requests per 60 s per key).",
        "schema": {
          "type": "string"
        }
      },
      "RateLimit": {
        "description": "IETF draft-ietf-httpapi-ratelimit-headers, e.g. `\"default\";r=57;t=31`.",
        "schema": {
          "type": "string"
        }
      }
    }
  },
  "info": {
    "contact": {
      "name": "moan.hot API support",
      "url": "https://api.moan.hot/contact"
    },
    "description": "The public `/v1` API of moan.hot API. Every operation lists the error codes\nit can return in `x-error-codes`, and each code is documented on the Errors\npage.\n\nConventions:\n- Money is integer **micro-USD** (`1_000_000` = 1.00 USD) in every field\n  named `*_micros`.\n- Timestamps are RFC 3339 UTC strings.\n- Ids are prefixed strings: `gen_`, `file_`, `eff_`, `evt_`, `price_`.\n- Errors are RFC 9457 `application/problem+json` extended with `code`,\n  `request_id` and `param`.\n- Lists use cursor pagination: `limit`, `starting_after`, `ending_before`,\n  and a `has_more` flag in the response.\n- Test keys (`mh_test_`) and live keys (`mh_live_`) see separate data.\n  Test mode returns fixture outputs, charges nothing and fires real\n  webhooks.\n\nWebhook endpoints are managed in the dashboard, not through this API.\n",
    "summary": "Ready-to-sell video, image and storyboard effects over plain HTTP.",
    "termsOfService": "https://api.moan.hot/legal/terms",
    "title": "moan.hot API",
    "version": "1.0.0"
  },
  "openapi": "3.1.0",
  "paths": {
    "/v1/account": {
      "get": {
        "operationId": "getAccount",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Account"
                }
              }
            },
            "description": "Balance, status, mode and limits."
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "Get the calling account",
        "tags": [
          "Account"
        ],
        "x-error-codes": [
          "invalid_api_key",
          "api_key_expired",
          "api_key_revoked",
          "api_key_disabled",
          "insufficient_scope",
          "rate_limited",
          "internal_error"
        ]
      }
    },
    "/v1/effects": {
      "get": {
        "description": "Effects enabled for the calling tenant (or all B2B effects with\n`enabled=false`), with variants, prices and presentation assets.",
        "operationId": "listEffects",
        "parameters": [
          {
            "in": "query",
            "name": "type",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/EffectType"
            }
          },
          {
            "in": "query",
            "name": "category",
            "required": false,
            "schema": {
              "examples": [
                "oral"
              ],
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "orientation",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/Orientation"
            }
          },
          {
            "description": "true (default) returns only effects this tenant has enabled.",
            "in": "query",
            "name": "enabled",
            "required": false,
            "schema": {
              "default": true,
              "description": "true (default) returns only effects this tenant has enabled.",
              "type": "boolean"
            }
          },
          {
            "in": "query",
            "name": "published_after",
            "required": false,
            "schema": {
              "format": "date-time",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 20,
              "maximum": 100,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "An object id; returns the page after it. Mutually exclusive with `ending_before`.",
            "in": "query",
            "name": "starting_after",
            "required": false,
            "schema": {
              "description": "An object id; returns the page after it. Mutually exclusive with `ending_before`.",
              "type": "string"
            }
          },
          {
            "description": "An object id; returns the page before it.",
            "in": "query",
            "name": "ending_before",
            "required": false,
            "schema": {
              "description": "An object id; returns the page before it.",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EffectList"
                }
              }
            },
            "description": "A page of effects.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "List effects",
        "tags": [
          "Effects"
        ],
        "x-error-codes": [
          "invalid_api_key",
          "api_key_expired",
          "api_key_revoked",
          "api_key_disabled",
          "insufficient_scope",
          "account_suspended",
          "invalid_input",
          "rate_limited",
          "internal_error"
        ]
      }
    },
    "/v1/effects/{slug}": {
      "get": {
        "operationId": "getEffect",
        "parameters": [
          {
            "in": "path",
            "name": "slug",
            "required": true,
            "schema": {
              "examples": [
                "cowgirl-pov"
              ],
              "pattern": "^[a-z0-9][a-z0-9-]{1,63}$",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Effect"
                }
              }
            },
            "description": "The effect.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "Get one effect",
        "tags": [
          "Effects"
        ],
        "x-error-codes": [
          "invalid_api_key",
          "api_key_expired",
          "api_key_revoked",
          "api_key_disabled",
          "insufficient_scope",
          "account_suspended",
          "effect_not_found",
          "rate_limited",
          "internal_error"
        ]
      }
    },
    "/v1/files": {
      "post": {
        "description": "Multipart upload of one JPEG, PNG or WebP image, at most 20 MB and\n8192 px on the long side. Input checks that need the full request run at\ngeneration create. The file expires 24 hours after upload.",
        "operationId": "uploadFile",
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/Body_uploadFile"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/File"
                }
              }
            },
            "description": "Stored.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "Upload an input image",
        "tags": [
          "Files"
        ],
        "x-error-codes": [
          "invalid_api_key",
          "api_key_expired",
          "api_key_revoked",
          "api_key_disabled",
          "insufficient_scope",
          "account_suspended",
          "invalid_request",
          "image_too_large",
          "unsupported_media_type",
          "image_unreadable",
          "rate_limited",
          "internal_error"
        ]
      }
    },
    "/v1/files/{file_id}": {
      "get": {
        "operationId": "getFile",
        "parameters": [
          {
            "in": "path",
            "name": "file_id",
            "required": true,
            "schema": {
              "pattern": "^file_[A-Za-z0-9]{24}$",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/File"
                }
              }
            },
            "description": "The file."
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "Get an uploaded file's metadata",
        "tags": [
          "Files"
        ],
        "x-error-codes": [
          "invalid_api_key",
          "api_key_expired",
          "api_key_revoked",
          "api_key_disabled",
          "insufficient_scope",
          "account_suspended",
          "file_not_found",
          "rate_limited",
          "internal_error"
        ]
      }
    },
    "/v1/generations": {
      "get": {
        "description": "Newest first. Filters combine with AND.",
        "operationId": "listGenerations",
        "parameters": [
          {
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/GenerationStatus"
            }
          },
          {
            "in": "query",
            "name": "effect",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "client_reference_id",
            "required": false,
            "schema": {
              "maxLength": 128,
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "created_gte",
            "required": false,
            "schema": {
              "format": "date-time",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "created_lt",
            "required": false,
            "schema": {
              "format": "date-time",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 20,
              "maximum": 100,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "An object id; returns the page after it. Mutually exclusive with `ending_before`.",
            "in": "query",
            "name": "starting_after",
            "required": false,
            "schema": {
              "description": "An object id; returns the page after it. Mutually exclusive with `ending_before`.",
              "type": "string"
            }
          },
          {
            "description": "An object id; returns the page before it.",
            "in": "query",
            "name": "ending_before",
            "required": false,
            "schema": {
              "description": "An object id; returns the page before it.",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenerationList"
                }
              }
            },
            "description": "A page of generations."
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "List generations",
        "tags": [
          "Generations"
        ],
        "x-error-codes": [
          "invalid_api_key",
          "api_key_expired",
          "api_key_revoked",
          "api_key_disabled",
          "insufficient_scope",
          "account_suspended",
          "invalid_input",
          "rate_limited",
          "internal_error"
        ]
      },
      "post": {
        "description": "Holds the variant's price on the balance, validates every\ninput image and queues the generation. Answers `202` with the\ngeneration in `queued`. A replay with the same `Idempotency-Key` and\nthe same body answers the first response again with\n`Idempotent-Replayed: true`.",
        "operationId": "createGeneration",
        "parameters": [
          {
            "description": "Required on `POST /generations`. 1-255 printable ASCII characters (a\nUUID v4 is recommended). Scoped to the tenant and mode, stored 24 h,\nbound to a SHA-256 of the canonical request body.\n",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "description": "Required on `POST /generations`. 1-255 printable ASCII characters (a\nUUID v4 is recommended). Scoped to the tenant and mode, stored 24 h,\nbound to a SHA-256 of the canonical request body.\n",
              "maxLength": 255,
              "minLength": 1,
              "pattern": "^[\\x21-\\x7E]+$",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GenerationCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Generation"
                }
              }
            },
            "description": "Accepted and queued (or replayed).",
            "headers": {
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/IdempotentReplayed"
              },
              "Location": {
                "description": "URL of the new generation.",
                "schema": {
                  "format": "uri",
                  "type": "string"
                }
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "Create a generation",
        "tags": [
          "Generations"
        ],
        "x-error-codes": [
          "invalid_api_key",
          "api_key_expired",
          "api_key_revoked",
          "api_key_disabled",
          "insufficient_scope",
          "account_pending_review",
          "account_suspended",
          "invalid_request",
          "invalid_input",
          "idempotency_key_required",
          "idempotency_key_mismatch",
          "idempotency_in_progress",
          "effect_not_found",
          "effect_disabled",
          "variant_unavailable",
          "file_not_found",
          "image_unreadable",
          "image_too_large",
          "unsupported_media_type",
          "input_rejected",
          "webhook_url_rejected",
          "insufficient_balance",
          "rate_limited",
          "queue_full",
          "upstream_unavailable",
          "internal_error"
        ]
      }
    },
    "/v1/generations/{generation_id}": {
      "get": {
        "description": "Output URLs are signed, valid one hour, and re-issued on every read.",
        "operationId": "getGeneration",
        "parameters": [
          {
            "in": "path",
            "name": "generation_id",
            "required": true,
            "schema": {
              "pattern": "^gen_[A-Za-z0-9]{24}$",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Generation"
                }
              }
            },
            "description": "The generation."
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "Get a generation",
        "tags": [
          "Generations"
        ],
        "x-error-codes": [
          "invalid_api_key",
          "api_key_expired",
          "api_key_revoked",
          "api_key_disabled",
          "insufficient_scope",
          "account_suspended",
          "generation_not_found",
          "rate_limited",
          "internal_error"
        ]
      }
    },
    "/v1/generations/{generation_id}/cancel": {
      "post": {
        "description": "A `queued` generation is canceled and its hold released (no charge).\nA `processing` generation is canceled best-effort; if the GPU job had\nalready started, the price is captured (see the ledger rules). A\nterminal generation answers `409 generation_not_cancelable`. Repeating\na cancel on an already canceled generation answers 200 with it.",
        "operationId": "cancelGeneration",
        "parameters": [
          {
            "in": "path",
            "name": "generation_id",
            "required": true,
            "schema": {
              "pattern": "^gen_[A-Za-z0-9]{24}$",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Generation"
                }
              }
            },
            "description": "The generation after the cancel."
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "Cancel a generation",
        "tags": [
          "Generations"
        ],
        "x-error-codes": [
          "invalid_api_key",
          "api_key_expired",
          "api_key_revoked",
          "api_key_disabled",
          "insufficient_scope",
          "account_suspended",
          "generation_not_found",
          "generation_not_cancelable",
          "rate_limited",
          "internal_error"
        ]
      }
    },
    "/v1/prices": {
      "get": {
        "description": "Every effect × variant price in the current price-list version.",
        "operationId": "listPrices",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PriceList"
                }
              }
            },
            "description": "The current price list.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "Full price list",
        "tags": [
          "Effects"
        ],
        "x-error-codes": [
          "invalid_api_key",
          "api_key_expired",
          "api_key_revoked",
          "api_key_disabled",
          "insufficient_scope",
          "account_suspended",
          "rate_limited",
          "internal_error"
        ]
      }
    },
    "/v1/usage": {
      "get": {
        "description": "Daily (or hourly) buckets of spend, counts and latency.",
        "operationId": "getUsage",
        "parameters": [
          {
            "in": "query",
            "name": "start",
            "required": true,
            "schema": {
              "format": "date-time",
              "type": "string"
            }
          },
          {
            "description": "Exclusive. At most 92 days after start.",
            "in": "query",
            "name": "end",
            "required": true,
            "schema": {
              "description": "Exclusive. At most 92 days after start.",
              "format": "date-time",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "granularity",
            "required": false,
            "schema": {
              "default": "day",
              "enum": [
                "hour",
                "day"
              ],
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "group_by",
            "required": false,
            "schema": {
              "default": "none",
              "enum": [
                "none",
                "type",
                "effect",
                "api_key"
              ],
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Usage"
                }
              }
            },
            "description": "Usage buckets."
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "Usage over a range",
        "tags": [
          "Account"
        ],
        "x-error-codes": [
          "invalid_api_key",
          "api_key_expired",
          "api_key_revoked",
          "api_key_disabled",
          "insufficient_scope",
          "account_suspended",
          "invalid_input",
          "rate_limited",
          "internal_error"
        ]
      }
    }
  },
  "servers": [
    {
      "description": "Production (test and live mode are selected by the key)",
      "url": "https://api.moan.hot"
    }
  ],
  "tags": [
    {
      "description": "The catalogue of effects, their variants, prices and sell-ready assets.",
      "name": "Effects"
    },
    {
      "description": "Input image uploads, kept 24 hours.",
      "name": "Files"
    },
    {
      "description": "Create, read, list and cancel generations.",
      "name": "Generations"
    },
    {
      "description": "Balance, limits and usage of the calling tenant.",
      "name": "Account"
    }
  ],
  "webhooks": {
    "balance.low": {
      "post": {
        "operationId": "webhookBalanceLow",
        "parameters": [
          {
            "description": "The event id (`evt_...`), identical across retries. Deduplicate on it.",
            "in": "header",
            "name": "webhook-id",
            "required": true,
            "schema": {
              "description": "The event id (`evt_...`), identical across retries. Deduplicate on it.",
              "type": "string"
            }
          },
          {
            "description": "Unix seconds of this attempt. Reject if more than 5 minutes from now.",
            "in": "header",
            "name": "webhook-timestamp",
            "required": true,
            "schema": {
              "description": "Unix seconds of this attempt. Reject if more than 5 minutes from now.",
              "pattern": "^[0-9]+$",
              "type": "string"
            }
          },
          {
            "description": "Space-separated `v1,<base64 HMAC-SHA256>` signatures of\n`{webhook-id}.{webhook-timestamp}.{raw body}` keyed by the base64 part\nof the `whsec_` secret. Two appear during a secret rotation.\n",
            "in": "header",
            "name": "webhook-signature",
            "required": true,
            "schema": {
              "description": "Space-separated `v1,<base64 HMAC-SHA256>` signatures of\n`{webhook-id}.{webhook-timestamp}.{raw body}` keyed by the base64 part\nof the `whsec_` secret. Two appear during a secret rotation.\n",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BalanceEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx within 15 s acknowledges the delivery. Anything else is retried."
          }
        },
        "summary": "The balance fell below the tenant's alert threshold"
      }
    },
    "balance.topped_up": {
      "post": {
        "operationId": "webhookBalanceToppedUp",
        "parameters": [
          {
            "description": "The event id (`evt_...`), identical across retries. Deduplicate on it.",
            "in": "header",
            "name": "webhook-id",
            "required": true,
            "schema": {
              "description": "The event id (`evt_...`), identical across retries. Deduplicate on it.",
              "type": "string"
            }
          },
          {
            "description": "Unix seconds of this attempt. Reject if more than 5 minutes from now.",
            "in": "header",
            "name": "webhook-timestamp",
            "required": true,
            "schema": {
              "description": "Unix seconds of this attempt. Reject if more than 5 minutes from now.",
              "pattern": "^[0-9]+$",
              "type": "string"
            }
          },
          {
            "description": "Space-separated `v1,<base64 HMAC-SHA256>` signatures of\n`{webhook-id}.{webhook-timestamp}.{raw body}` keyed by the base64 part\nof the `whsec_` secret. Two appear during a secret rotation.\n",
            "in": "header",
            "name": "webhook-signature",
            "required": true,
            "schema": {
              "description": "Space-separated `v1,<base64 HMAC-SHA256>` signatures of\n`{webhook-id}.{webhook-timestamp}.{raw body}` keyed by the base64 part\nof the `whsec_` secret. Two appear during a secret rotation.\n",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BalanceEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx within 15 s acknowledges the delivery. Anything else is retried."
          }
        },
        "summary": "A top-up was confirmed and credited"
      }
    },
    "effect.published": {
      "post": {
        "operationId": "webhookEffectPublished",
        "parameters": [
          {
            "description": "The event id (`evt_...`), identical across retries. Deduplicate on it.",
            "in": "header",
            "name": "webhook-id",
            "required": true,
            "schema": {
              "description": "The event id (`evt_...`), identical across retries. Deduplicate on it.",
              "type": "string"
            }
          },
          {
            "description": "Unix seconds of this attempt. Reject if more than 5 minutes from now.",
            "in": "header",
            "name": "webhook-timestamp",
            "required": true,
            "schema": {
              "description": "Unix seconds of this attempt. Reject if more than 5 minutes from now.",
              "pattern": "^[0-9]+$",
              "type": "string"
            }
          },
          {
            "description": "Space-separated `v1,<base64 HMAC-SHA256>` signatures of\n`{webhook-id}.{webhook-timestamp}.{raw body}` keyed by the base64 part\nof the `whsec_` secret. Two appear during a secret rotation.\n",
            "in": "header",
            "name": "webhook-signature",
            "required": true,
            "schema": {
              "description": "Space-separated `v1,<base64 HMAC-SHA256>` signatures of\n`{webhook-id}.{webhook-timestamp}.{raw body}` keyed by the base64 part\nof the `whsec_` secret. Two appear during a secret rotation.\n",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EffectEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx within 15 s acknowledges the delivery. Anything else is retried."
          }
        },
        "summary": "A new effect joined the B2B catalogue"
      }
    },
    "effect.retired": {
      "post": {
        "operationId": "webhookEffectRetired",
        "parameters": [
          {
            "description": "The event id (`evt_...`), identical across retries. Deduplicate on it.",
            "in": "header",
            "name": "webhook-id",
            "required": true,
            "schema": {
              "description": "The event id (`evt_...`), identical across retries. Deduplicate on it.",
              "type": "string"
            }
          },
          {
            "description": "Unix seconds of this attempt. Reject if more than 5 minutes from now.",
            "in": "header",
            "name": "webhook-timestamp",
            "required": true,
            "schema": {
              "description": "Unix seconds of this attempt. Reject if more than 5 minutes from now.",
              "pattern": "^[0-9]+$",
              "type": "string"
            }
          },
          {
            "description": "Space-separated `v1,<base64 HMAC-SHA256>` signatures of\n`{webhook-id}.{webhook-timestamp}.{raw body}` keyed by the base64 part\nof the `whsec_` secret. Two appear during a secret rotation.\n",
            "in": "header",
            "name": "webhook-signature",
            "required": true,
            "schema": {
              "description": "Space-separated `v1,<base64 HMAC-SHA256>` signatures of\n`{webhook-id}.{webhook-timestamp}.{raw body}` keyed by the base64 part\nof the `whsec_` secret. Two appear during a secret rotation.\n",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EffectEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx within 15 s acknowledges the delivery. Anything else is retried."
          }
        },
        "summary": "An effect will stop accepting generations at `retires_at`"
      }
    },
    "generation.canceled": {
      "post": {
        "operationId": "webhookGenerationCanceled",
        "parameters": [
          {
            "description": "The event id (`evt_...`), identical across retries. Deduplicate on it.",
            "in": "header",
            "name": "webhook-id",
            "required": true,
            "schema": {
              "description": "The event id (`evt_...`), identical across retries. Deduplicate on it.",
              "type": "string"
            }
          },
          {
            "description": "Unix seconds of this attempt. Reject if more than 5 minutes from now.",
            "in": "header",
            "name": "webhook-timestamp",
            "required": true,
            "schema": {
              "description": "Unix seconds of this attempt. Reject if more than 5 minutes from now.",
              "pattern": "^[0-9]+$",
              "type": "string"
            }
          },
          {
            "description": "Space-separated `v1,<base64 HMAC-SHA256>` signatures of\n`{webhook-id}.{webhook-timestamp}.{raw body}` keyed by the base64 part\nof the `whsec_` secret. Two appear during a secret rotation.\n",
            "in": "header",
            "name": "webhook-signature",
            "required": true,
            "schema": {
              "description": "Space-separated `v1,<base64 HMAC-SHA256>` signatures of\n`{webhook-id}.{webhook-timestamp}.{raw body}` keyed by the base64 part\nof the `whsec_` secret. Two appear during a secret rotation.\n",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GenerationEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx within 15 s acknowledges the delivery. Anything else is retried."
          }
        },
        "summary": "The generation was canceled"
      }
    },
    "generation.failed": {
      "post": {
        "operationId": "webhookGenerationFailed",
        "parameters": [
          {
            "description": "The event id (`evt_...`), identical across retries. Deduplicate on it.",
            "in": "header",
            "name": "webhook-id",
            "required": true,
            "schema": {
              "description": "The event id (`evt_...`), identical across retries. Deduplicate on it.",
              "type": "string"
            }
          },
          {
            "description": "Unix seconds of this attempt. Reject if more than 5 minutes from now.",
            "in": "header",
            "name": "webhook-timestamp",
            "required": true,
            "schema": {
              "description": "Unix seconds of this attempt. Reject if more than 5 minutes from now.",
              "pattern": "^[0-9]+$",
              "type": "string"
            }
          },
          {
            "description": "Space-separated `v1,<base64 HMAC-SHA256>` signatures of\n`{webhook-id}.{webhook-timestamp}.{raw body}` keyed by the base64 part\nof the `whsec_` secret. Two appear during a secret rotation.\n",
            "in": "header",
            "name": "webhook-signature",
            "required": true,
            "schema": {
              "description": "Space-separated `v1,<base64 HMAC-SHA256>` signatures of\n`{webhook-id}.{webhook-timestamp}.{raw body}` keyed by the base64 part\nof the `whsec_` secret. Two appear during a secret rotation.\n",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GenerationEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx within 15 s acknowledges the delivery. Anything else is retried."
          }
        },
        "summary": "The generation failed; the hold was released"
      }
    },
    "generation.queued": {
      "post": {
        "operationId": "webhookGenerationQueued",
        "parameters": [
          {
            "description": "The event id (`evt_...`), identical across retries. Deduplicate on it.",
            "in": "header",
            "name": "webhook-id",
            "required": true,
            "schema": {
              "description": "The event id (`evt_...`), identical across retries. Deduplicate on it.",
              "type": "string"
            }
          },
          {
            "description": "Unix seconds of this attempt. Reject if more than 5 minutes from now.",
            "in": "header",
            "name": "webhook-timestamp",
            "required": true,
            "schema": {
              "description": "Unix seconds of this attempt. Reject if more than 5 minutes from now.",
              "pattern": "^[0-9]+$",
              "type": "string"
            }
          },
          {
            "description": "Space-separated `v1,<base64 HMAC-SHA256>` signatures of\n`{webhook-id}.{webhook-timestamp}.{raw body}` keyed by the base64 part\nof the `whsec_` secret. Two appear during a secret rotation.\n",
            "in": "header",
            "name": "webhook-signature",
            "required": true,
            "schema": {
              "description": "Space-separated `v1,<base64 HMAC-SHA256>` signatures of\n`{webhook-id}.{webhook-timestamp}.{raw body}` keyed by the base64 part\nof the `whsec_` secret. Two appear during a secret rotation.\n",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GenerationEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx within 15 s acknowledges the delivery. Anything else is retried."
          }
        },
        "summary": "A generation was accepted and queued"
      }
    },
    "generation.started": {
      "post": {
        "operationId": "webhookGenerationStarted",
        "parameters": [
          {
            "description": "The event id (`evt_...`), identical across retries. Deduplicate on it.",
            "in": "header",
            "name": "webhook-id",
            "required": true,
            "schema": {
              "description": "The event id (`evt_...`), identical across retries. Deduplicate on it.",
              "type": "string"
            }
          },
          {
            "description": "Unix seconds of this attempt. Reject if more than 5 minutes from now.",
            "in": "header",
            "name": "webhook-timestamp",
            "required": true,
            "schema": {
              "description": "Unix seconds of this attempt. Reject if more than 5 minutes from now.",
              "pattern": "^[0-9]+$",
              "type": "string"
            }
          },
          {
            "description": "Space-separated `v1,<base64 HMAC-SHA256>` signatures of\n`{webhook-id}.{webhook-timestamp}.{raw body}` keyed by the base64 part\nof the `whsec_` secret. Two appear during a secret rotation.\n",
            "in": "header",
            "name": "webhook-signature",
            "required": true,
            "schema": {
              "description": "Space-separated `v1,<base64 HMAC-SHA256>` signatures of\n`{webhook-id}.{webhook-timestamp}.{raw body}` keyed by the base64 part\nof the `whsec_` secret. Two appear during a secret rotation.\n",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GenerationEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx within 15 s acknowledges the delivery. Anything else is retried."
          }
        },
        "summary": "A GPU worker started the generation"
      }
    },
    "generation.succeeded": {
      "post": {
        "operationId": "webhookGenerationSucceeded",
        "parameters": [
          {
            "description": "The event id (`evt_...`), identical across retries. Deduplicate on it.",
            "in": "header",
            "name": "webhook-id",
            "required": true,
            "schema": {
              "description": "The event id (`evt_...`), identical across retries. Deduplicate on it.",
              "type": "string"
            }
          },
          {
            "description": "Unix seconds of this attempt. Reject if more than 5 minutes from now.",
            "in": "header",
            "name": "webhook-timestamp",
            "required": true,
            "schema": {
              "description": "Unix seconds of this attempt. Reject if more than 5 minutes from now.",
              "pattern": "^[0-9]+$",
              "type": "string"
            }
          },
          {
            "description": "Space-separated `v1,<base64 HMAC-SHA256>` signatures of\n`{webhook-id}.{webhook-timestamp}.{raw body}` keyed by the base64 part\nof the `whsec_` secret. Two appear during a secret rotation.\n",
            "in": "header",
            "name": "webhook-signature",
            "required": true,
            "schema": {
              "description": "Space-separated `v1,<base64 HMAC-SHA256>` signatures of\n`{webhook-id}.{webhook-timestamp}.{raw body}` keyed by the base64 part\nof the `whsec_` secret. Two appear during a secret rotation.\n",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GenerationEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx within 15 s acknowledges the delivery. Anything else is retried."
          }
        },
        "summary": "The generation succeeded and was charged"
      }
    },
    "price.changed": {
      "post": {
        "operationId": "webhookPriceChanged",
        "parameters": [
          {
            "description": "The event id (`evt_...`), identical across retries. Deduplicate on it.",
            "in": "header",
            "name": "webhook-id",
            "required": true,
            "schema": {
              "description": "The event id (`evt_...`), identical across retries. Deduplicate on it.",
              "type": "string"
            }
          },
          {
            "description": "Unix seconds of this attempt. Reject if more than 5 minutes from now.",
            "in": "header",
            "name": "webhook-timestamp",
            "required": true,
            "schema": {
              "description": "Unix seconds of this attempt. Reject if more than 5 minutes from now.",
              "pattern": "^[0-9]+$",
              "type": "string"
            }
          },
          {
            "description": "Space-separated `v1,<base64 HMAC-SHA256>` signatures of\n`{webhook-id}.{webhook-timestamp}.{raw body}` keyed by the base64 part\nof the `whsec_` secret. Two appear during a secret rotation.\n",
            "in": "header",
            "name": "webhook-signature",
            "required": true,
            "schema": {
              "description": "Space-separated `v1,<base64 HMAC-SHA256>` signatures of\n`{webhook-id}.{webhook-timestamp}.{raw body}` keyed by the base64 part\nof the `whsec_` secret. Two appear during a secret rotation.\n",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PriceChangedEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx within 15 s acknowledges the delivery. Anything else is retried."
          }
        },
        "summary": "A new price-list version takes effect at `effective_at`"
      }
    }
  }
}
