{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/getoneprofile-ai/json-schema/getoneprofile-ai-affiliate-performance-read-schema-schema.json",
  "title": "AffiliatePerformanceReadSchema",
  "description": "Everything the affiliate overview measures over one window.",
  "x-generated": "2026-11-10",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/getoneprofile-ai-affiliate-api-openapi.yml#/components/schemas/AffiliatePerformanceReadSchema",
  "properties": {
    "active_count": {
      "description": "Referrals still inside their commission window.",
      "title": "Active Count",
      "type": "integer"
    },
    "average_commission_cents": {
      "anyOf": [
        {
          "type": "integer"
        },
        {
          "type": "null"
        }
      ],
      "description": "Lifetime gross commission per paying referral. Null with none yet.",
      "title": "Average Commission Cents"
    },
    "clears_minimum_on": {
      "anyOf": [
        {
          "format": "date",
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "description": "The day the payable balance first clears the payout minimum on that schedule. Null when it already has, or when it never does.",
      "title": "Clears Minimum On"
    },
    "clicks": {
      "$ref": "#/$defs/AffiliateTrendReadSchema"
    },
    "conversion_rate": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "null"
        }
      ],
      "description": "Paying referrals per signup, lifetime, 0-1. Null below the honesty floor.",
      "title": "Conversion Rate"
    },
    "conversions": {
      "$ref": "#/$defs/AffiliateTrendReadSchema"
    },
    "days": {
      "description": "The window length these figures cover.",
      "title": "Days",
      "type": "integer"
    },
    "earned_cents": {
      "$ref": "#/$defs/AffiliateTrendReadSchema"
    },
    "epc_cents": {
      "anyOf": [
        {
          "type": "integer"
        },
        {
          "type": "null"
        }
      ],
      "description": "Commission earned per click over the window. Null below the honesty floor.",
      "title": "Epc Cents"
    },
    "held_cents": {
      "description": "Money in a payout waiting on human review. Still counted in the available balance until it is released.",
      "title": "Held Cents",
      "type": "integer"
    },
    "last_commission_at": {
      "anyOf": [
        {
          "format": "date-time",
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Last Commission At"
    },
    "last_conversion_at": {
      "anyOf": [
        {
          "format": "date-time",
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Last Conversion At"
    },
    "last_signup_at": {
      "anyOf": [
        {
          "format": "date-time",
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Last Signup At"
    },
    "lifetime_clawed_back_cents": {
      "description": "What refunds and disputes took back, as a positive magnitude.",
      "title": "Lifetime Clawed Back Cents",
      "type": "integer"
    },
    "lifetime_gross_cents": {
      "title": "Lifetime Gross Cents",
      "type": "integer"
    },
    "lifetime_net_cents": {
      "title": "Lifetime Net Cents",
      "type": "integer"
    },
    "never_paid_count": {
      "description": "Referrals that have not started a paid plan.",
      "title": "Never Paid Count",
      "type": "integer"
    },
    "next_payout_blocker": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "description": "When blocked, which gate: identity_not_verified, no_payout_email or destination_hold.",
      "title": "Next Payout Blocker"
    },
    "next_payout_cents": {
      "description": "What that run would send on today's numbers plus what matures before it.",
      "title": "Next Payout Cents",
      "type": "integer"
    },
    "next_payout_on": {
      "description": "The date of the next monthly payout run.",
      "format": "date",
      "title": "Next Payout On",
      "type": "string"
    },
    "next_payout_status": {
      "$ref": "#/$defs/AffiliateNextPayoutStatus",
      "description": "Whether that run will actually send anything: scheduled, below the minimum, blocked on a step the affiliate can take, under human review, paused program-wide, or unavailable to this account."
    },
    "signup_rate": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "null"
        }
      ],
      "description": "Signups per click over the window, 0-1. Null when there were too few clicks for the figure to mean anything.",
      "title": "Signup Rate"
    },
    "signups": {
      "$ref": "#/$defs/AffiliateTrendReadSchema"
    },
    "upcoming_maturities": {
      "description": "The next days pending commission becomes payable on, soonest first.",
      "items": {
        "$ref": "#/$defs/AffiliateMaturityReadSchema"
      },
      "title": "Upcoming Maturities",
      "type": "array"
    },
    "window_closed_count": {
      "description": "Referrals whose commission window has ended.",
      "title": "Window Closed Count",
      "type": "integer"
    }
  },
  "required": [
    "days",
    "clicks",
    "signups",
    "conversions",
    "earned_cents",
    "signup_rate",
    "conversion_rate",
    "epc_cents",
    "average_commission_cents",
    "lifetime_gross_cents",
    "lifetime_clawed_back_cents",
    "lifetime_net_cents",
    "never_paid_count",
    "active_count",
    "window_closed_count",
    "upcoming_maturities",
    "clears_minimum_on",
    "next_payout_on",
    "next_payout_cents",
    "next_payout_status",
    "next_payout_blocker",
    "held_cents",
    "last_signup_at",
    "last_conversion_at",
    "last_commission_at"
  ],
  "type": "object",
  "$defs": {
    "AffiliateMaturityReadSchema": {
      "description": "One future day on which pending commission becomes payable.",
      "properties": {
        "amount_cents": {
          "title": "Amount Cents",
          "type": "integer"
        },
        "day": {
          "format": "date",
          "title": "Day",
          "type": "string"
        },
        "running_available_cents": {
          "description": "The payable balance once this day has matured, absent clawbacks and payouts.",
          "title": "Running Available Cents",
          "type": "integer"
        }
      },
      "required": [
        "day",
        "amount_cents",
        "running_available_cents"
      ],
      "title": "AffiliateMaturityReadSchema",
      "type": "object"
    },
    "AffiliateNextPayoutStatus": {
      "description": "What the next monthly run will do with this affiliate's balance.\n\nDerived from the same gates the payout engine applies, so the sentence the\ndashboard prints and the decision the run makes cannot disagree. Every\n\"your payout goes out on the 1st\" used to be unconditional, which made it\nfalse for a first payout (held for a human), a blocked affiliate (no\nidentity check, no PayPal address, a fresh address inside its hold), a\nsuspended or banned account, a balance under the minimum, and the whole\nperiod the program ships with payouts switched off.",
      "enum": [
        "paused",
        "unavailable",
        "under_review",
        "blocked",
        "below_minimum",
        "scheduled"
      ],
      "title": "AffiliateNextPayoutStatus",
      "type": "string"
    },
    "AffiliateTrendReadSchema": {
      "description": "One metric over a window, against the window immediately before it.",
      "properties": {
        "current": {
          "title": "Current",
          "type": "integer"
        },
        "previous": {
          "title": "Previous",
          "type": "integer"
        }
      },
      "required": [
        "current",
        "previous"
      ],
      "title": "AffiliateTrendReadSchema",
      "type": "object"
    }
  }
}