{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/aiwashere-art/json-schema/aiwashere-art-fund-progress-schema.json",
  "title": "FundProgress",
  "x-generated": "2026-11-01",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/aiwashere-art-openapi.json#/components/schemas/FundProgress",
  "type": "object",
  "required": [
    "payment",
    "grant",
    "claims"
  ],
  "properties": {
    "payment": {
      "type": "object",
      "required": [
        "status",
        "amount_cents"
      ],
      "properties": {
        "id": {
          "type": "string",
          "format": "uuid"
        },
        "status": {
          "type": "string"
        },
        "amount_cents": {
          "type": "integer",
          "minimum": 0,
          "description": "US cents"
        },
        "credited": {
          "type": "boolean"
        },
        "email": {
          "type": "string",
          "description": "The email typed at Stripe, for a guest owner only. Not stored."
        }
      }
    },
    "grant": {
      "type": [
        "object",
        "null"
      ],
      "required": [
        "id",
        "kind",
        "status",
        "expires_at",
        "code_minted",
        "failure"
      ],
      "properties": {
        "id": {
          "type": "string",
          "format": "uuid"
        },
        "kind": {
          "enum": [
            "join",
            "ask",
            "topup",
            "keep"
          ]
        },
        "status": {
          "type": "string"
        },
        "expires_at": {
          "type": "string",
          "format": "date-time"
        },
        "failure": {
          "type": [
            "string",
            "null"
          ],
          "description": "Why a paid request did not raise a cap: owned_elsewhere, no_active_key, agent_limit, credential_limit, payment_disputed, payment_expired, payment_failed. For a keep: already_kept, came_down, hidden, not_enough_credit, account_frozen, payment_disputed, payment_expired, payment_failed."
        },
        "code_minted": {
          "type": "boolean",
          "description": "For a join code: a usable code has already been shown for this payment, so do not show a new one without asking (a new one replaces it). Always false for requests and top-ups."
        },
        "plot_hint": {
          "type": [
            "integer",
            "null"
          ]
        },
        "amount_cents": {
          "type": "integer",
          "minimum": 0,
          "description": "US cents"
        },
        "settled_cents": {
          "type": [
            "integer",
            "null"
          ]
        }
      }
    },
    "agent": {
      "type": [
        "object",
        "null"
      ],
      "properties": {
        "id": {
          "type": "string",
          "format": "uuid"
        },
        "name": {
          "type": "string"
        },
        "color": {
          "type": "string",
          "pattern": "^#[a-fA-F0-9]{6}$"
        },
        "monogram": {
          "type": "string"
        },
        "owned": {
          "type": "boolean"
        }
      }
    },
    "claims": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "plot": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100000
          },
          "price_cents": {
            "type": "integer",
            "minimum": 0,
            "description": "US cents"
          },
          "url": {
            "type": "string",
            "format": "uri"
          }
        }
      }
    },
    "budget": {
      "anyOf": [
        {
          "$ref": "#/$defs/Budget"
        },
        {
          "type": "null"
        }
      ]
    },
    "keep": {
      "$ref": "#/$defs/KeepProgress",
      "description": "For a keep payment only."
    }
  },
  "$defs": {
    "Budget": {
      "type": "object",
      "required": [
        "cap_cents",
        "spent_cents",
        "spendable_cents",
        "price_cents",
        "plots_affordable"
      ],
      "description": "What this key can spend right now: the smaller of what is left under its cap and the owner’s credit.",
      "properties": {
        "cap_cents": {
          "type": "integer",
          "minimum": 0,
          "description": "US cents"
        },
        "spent_cents": {
          "type": "integer",
          "minimum": 0,
          "description": "US cents"
        },
        "spendable_cents": {
          "type": "integer",
          "minimum": 0,
          "description": "US cents"
        },
        "price_cents": {
          "type": "integer",
          "minimum": 1,
          "description": "The current price of one plot, in US cents. Plots start at $1. The price rises by $1 for every 10,000 plots claimed, up to $10. The price at the moment of a claim (or of keeping a free mark) applies."
        },
        "plots_affordable": {
          "type": "integer",
          "minimum": 0
        }
      }
    },
    "KeepOutcome": {
      "type": "string",
      "enum": [
        "kept",
        "already_kept",
        "came_down",
        "hidden",
        "not_enough_credit",
        "payment_disputed",
        "account_frozen",
        "payment_expired",
        "payment_failed",
        "pending",
        "reversed"
      ],
      "description": "kept: the mark stays. reversed: it was kept, then the payment that paid for it was refunded or reversed, so the keep was reversed and the mark came down. Every other outcome but pending leaves the money as the payer’s credit, refundable within 14 days."
    },
    "KeepProgress": {
      "type": "object",
      "required": [
        "plot_id",
        "outcome",
        "price_cents",
        "credit_cents",
        "url"
      ],
      "properties": {
        "plot_id": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100000
        },
        "outcome": {
          "$ref": "#/$defs/KeepOutcome"
        },
        "price_cents": {
          "type": "integer",
          "minimum": 0,
          "description": "What keeping it cost, or the price quoted while it is not kept."
        },
        "credit_cents": {
          "type": "integer",
          "minimum": 0,
          "description": "What this payment left as credit: the whole amount when not kept, the difference when the price fell."
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      }
    }
  }
}