{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/recurly/json-schema/recurly-add-on-create-schema.json",
  "title": "Add-on",
  "description": "Full add-on details.",
  "x-generated": "2026-11-05",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/recurly-openapi.yml#/components/schemas/AddOnCreate",
  "type": "object",
  "properties": {
    "item_code": {
      "type": "string",
      "title": "Item Code",
      "description": "Unique code to identify an item. Available when the `Credit Invoices` feature is enabled. If `item_id` and `item_code` are both present, `item_id` will be used.",
      "pattern": "/^[a-z0-9_+-]+$/",
      "maxLength": 50
    },
    "item_id": {
      "type": "string",
      "title": "Item ID",
      "description": "System-generated unique identifier for an item. Available when the `Credit Invoices` feature is enabled. If `item_id` and `item_code` are both present, `item_id` will be used.",
      "maxLength": 13
    },
    "code": {
      "type": "string",
      "title": "Add-on code",
      "description": "The unique identifier for the add-on within its plan. If `item_code`/`item_id` is part of the request then `code` must be absent. If `item_code`/`item_id` is not present `code` is required.",
      "maxLength": 50
    },
    "name": {
      "type": "string",
      "title": "Name",
      "description": "Describes your add-on and will appear in subscribers' invoices. If `item_code`/`item_id` is part of the request then `name` must be absent. If `item_code`/`item_id` is not present `name` is required.",
      "maxLength": 255
    },
    "add_on_type": {
      "$ref": "#/$defs/AddOnTypeCreateEnum"
    },
    "usage_type": {
      "$ref": "#/$defs/UsageTypeCreateEnum"
    },
    "usage_calculation_type": {
      "$ref": "#/$defs/UsageCalculationTypeEnum"
    },
    "usage_percentage": {
      "type": "number",
      "format": "float",
      "title": "Usage Percentage",
      "description": "The percentage taken of the monetary amount of usage tracked. This can be up to 4 decimal places. A value between 0.0 and 100.0. Required if `add_on_type` is usage, `tier_type` is `flat` and `usage_type` is percentage. Must be omitted otherwise."
    },
    "measured_unit_id": {
      "type": "string",
      "title": "Measured Unit ID",
      "description": "System-generated unique identifier for a measured unit to be associated with the add-on. Either `measured_unit_id` or `measured_unit_name` are required when `add_on_type` is `usage`. If `measured_unit_id` and `measured_unit_name` are both present, `measured_unit_id` will be used.",
      "maxLength": 13
    },
    "measured_unit_name": {
      "type": "string",
      "title": "Measured Unit Name",
      "description": "Name of a measured unit to be associated with the add-on. Either `measured_unit_id` or `measured_unit_name` are required when `add_on_type` is `usage`. If `measured_unit_id` and `measured_unit_name` are both present, `measured_unit_id` will be used."
    },
    "plan_id": {
      "type": "string",
      "title": "Plan ID",
      "maxLength": 13,
      "readOnly": true
    },
    "liability_gl_account_id": {
      "type": "string",
      "title": "General Ledger Account ID",
      "description": "The ID of a general ledger account. General ledger accounts are\nonly accessible as a part of the Recurly RevRec Standard and\nRecurly RevRec Advanced features.\n",
      "maxLength": 13
    },
    "revenue_gl_account_id": {
      "type": "string",
      "title": "General Ledger Account ID",
      "description": "The ID of a general ledger account. General ledger accounts are\nonly accessible as a part of the Recurly RevRec Standard and\nRecurly RevRec Advanced features.\n",
      "maxLength": 13
    },
    "performance_obligation_id": {
      "type": "string",
      "title": "Performance Obligation ID",
      "description": "The ID of a performance obligation. Performance obligations are\nonly accessible as a part of the Recurly RevRec Standard and\nRecurly RevRec Advanced features.\n",
      "maxLength": 13
    },
    "accounting_code": {
      "type": "string",
      "title": "Accounting code",
      "description": "Accounting code for invoice line items for this add-on. If no value is provided, it defaults to add-on's code. If `item_code`/`item_id` is part of the request then `accounting_code` must be absent.",
      "pattern": "/^[a-z0-9_+-]+$/",
      "maxLength": 20
    },
    "revenue_schedule_type": {
      "title": "Revenue schedule type",
      "description": "When this add-on is invoiced, the line item will use this revenue schedule. If `item_code`/`item_id` is part of the request then `revenue_schedule_type` must be absent in the request as the value will be set from the item.",
      "$ref": "#/$defs/RevenueScheduleTypeEnum"
    },
    "display_quantity": {
      "type": "boolean",
      "title": "Display quantity?",
      "description": "Determines if the quantity field is displayed on the hosted pages for the add-on.",
      "default": false
    },
    "default_quantity": {
      "type": "integer",
      "title": "Default quantity",
      "description": "Default quantity for the hosted pages.",
      "default": 1
    },
    "optional": {
      "type": "boolean",
      "title": "Optional",
      "description": "Whether the add-on is optional for the customer to include in their purchase on the hosted payment page. If false, the add-on will be included when a subscription is created through the Recurly UI. However, the add-on will not be included when a subscription is created through the API."
    },
    "avalara_transaction_type": {
      "type": "integer",
      "title": "Avalara Transaction Type",
      "description": "Used by Avalara for Communications taxes. The transaction type in combination with the service type describe how the add-on is taxed. Refer to [the documentation](https://help.avalara.com/AvaTax_for_Communications/Tax_Calculation/AvaTax_for_Communications_Tax_Engine/Mapping_Resources/TM_00115_AFC_Modules_Corresponding_Transaction_Types) for more available t/s types. If an `Item` is associated to the `AddOn`, then the `avalara_transaction_type` must be absent.",
      "minimum": 0
    },
    "avalara_service_type": {
      "type": "integer",
      "title": "Avalara Service Type",
      "description": "Used by Avalara for Communications taxes. The transaction type in combination with the service type describe how the add-on is taxed. Refer to [the documentation](https://help.avalara.com/AvaTax_for_Communications/Tax_Calculation/AvaTax_for_Communications_Tax_Engine/Mapping_Resources/TM_00115_AFC_Modules_Corresponding_Transaction_Types) for more available t/s types. If an `Item` is associated to the `AddOn`, then the `avalara_service_type` must be absent.",
      "minimum": 0
    },
    "tax_code": {
      "type": "string",
      "maxLength": 50,
      "title": "Tax code",
      "description": "Optional field used by Avalara, Vertex, and Recurly's In-the-Box tax solution to determine taxation rules. You can pass in specific tax codes using any of these tax integrations. For Recurly's In-the-Box tax offering you can also choose to instead use simple values of `unknown`, `physical`, or `digital` tax codes. If `item_code`/`item_id` is part of the request then `tax_code` must be absent."
    },
    "harmonized_system_code": {
      "type": "string",
      "title": "Harmonized System code",
      "description": "The Harmonized System (HS) code is an internationally standardized system of names and numbers to classify traded products. The HS code, sometimes called Commodity Code, is used by customs authorities around the world to identify products when assessing duties and taxes. The HS code may also be referred to as the tariff code or customs code. Values should contain only digits and decimals.",
      "pattern": "^\\d+(\\.\\d+)*$",
      "maxLength": 25
    },
    "currencies": {
      "type": "array",
      "title": "Add-on pricing",
      "items": {
        "$ref": "#/$defs/AddOnPricing"
      },
      "minItems": 1,
      "description": "* If `item_code`/`item_id` is part of the request and the item\nhas a default currency, then `currencies` is optional. If the item does\nnot have a default currency, then `currencies` is required. If `item_code`/`item_id`\nis not present `currencies` is required.\n* If the add-on's `tier_type` is `tiered`, `volume`, or `stairstep`,\nthen `currencies` must be absent.\n* Must be absent if `add_on_type` is `usage` and `usage_type` is `percentage`.\n"
    },
    "tier_type": {
      "$ref": "#/$defs/TierTypeEnum"
    },
    "usage_timeframe": {
      "$ref": "#/$defs/UsageTimeframeCreateEnum"
    },
    "tiers": {
      "type": "array",
      "title": "Tiers",
      "items": {
        "$ref": "#/$defs/Tier"
      },
      "description": "If the tier_type is `flat`, then `tiers` must be absent. The `tiers` object\nmust include one to many tiers with `ending_quantity` and `unit_amount` for\nthe desired `currencies`. There must be one tier without an `ending_quantity` value\nwhich represents the final tier.\n"
    },
    "percentage_tiers": {
      "type": "array",
      "title": "Percentage Tiers By Currency",
      "items": {
        "$ref": "#/$defs/PercentageTiersByCurrency"
      },
      "description": "Array of objects which must have at least one set of tiers\nper currency and the currency code. The tier_type must be `volume` or `tiered`,\nif not, it must be absent. There must be one tier without an `ending_amount` value\nwhich represents the final tier. This feature is currently in development and\nrequires approval and enablement, please contact support.\n"
    }
  },
  "required": [
    "code",
    "name"
  ],
  "$defs": {
    "AddOnPricing": {
      "type": "object",
      "properties": {
        "currency": {
          "type": "string",
          "title": "Currency",
          "description": "3-letter ISO 4217 currency code.",
          "maxLength": 3
        },
        "unit_amount": {
          "type": "number",
          "format": "float",
          "title": "Unit price",
          "minimum": 0,
          "maximum": 1000000,
          "description": "Allows up to 2 decimal places. Required unless `unit_amount_decimal` is provided."
        },
        "unit_amount_decimal": {
          "type": "string",
          "title": "Unit Amount Decimal",
          "minimum": 0,
          "maximum": 1000000,
          "description": "Allows up to 9 decimal places.\nIf `unit_amount_decimal` is provided, `unit_amount` cannot be provided.\n"
        },
        "tax_inclusive": {
          "type": "boolean",
          "title": "Tax Inclusive?",
          "default": false,
          "description": "This field is deprecated. Please do not use it.",
          "deprecated": true
        }
      },
      "required": [
        "currency"
      ]
    },
    "AddOnTypeCreateEnum": {
      "type": "string",
      "enum": [
        "fixed",
        "usage"
      ],
      "title": "Add-on Type",
      "description": "Whether the add-on type is fixed, or usage-based.",
      "default": "fixed"
    },
    "PercentageTier": {
      "type": "object",
      "properties": {
        "ending_amount": {
          "type": "number",
          "format": "float",
          "title": "Ending amount",
          "minimum": 0.01,
          "maximum": 9999999999999.99,
          "description": "Ending amount for the tier. Allows up to 2 decimal places. Must be left empty if it is the final tier."
        },
        "usage_percentage": {
          "type": "string",
          "title": "Usage Percentage",
          "minimum": 0,
          "maximum": 100,
          "description": "The percentage taken of the monetary amount of usage tracked.\nThis can be up to 4 decimal places represented as a string.\n"
        }
      }
    },
    "PercentageTiersByCurrency": {
      "type": "object",
      "properties": {
        "currency": {
          "type": "string",
          "title": "Currency",
          "description": "3-letter ISO 4217 currency code.",
          "maxLength": 3
        },
        "tiers": {
          "type": "array",
          "title": "Tiers",
          "items": {
            "$ref": "#/$defs/PercentageTier"
          },
          "minItems": 1
        }
      }
    },
    "RevenueScheduleTypeEnum": {
      "type": "string",
      "enum": [
        "at_range_end",
        "at_range_start",
        "evenly",
        "never"
      ]
    },
    "Tier": {
      "type": "object",
      "properties": {
        "ending_quantity": {
          "type": "integer",
          "title": "Ending quantity",
          "minimum": 1,
          "maximum": 999999999,
          "description": "Ending quantity for the tier.  This represents a unit amount for unit-priced add ons. Must be left empty if it is the final tier."
        },
        "usage_percentage": {
          "type": "string",
          "title": "Usage Percentage",
          "description": "(deprecated) -- Use the percentage_tiers object instead.",
          "deprecated": true
        },
        "currencies": {
          "type": "array",
          "title": "Tier pricing",
          "items": {
            "$ref": "#/$defs/TierPricing"
          },
          "minItems": 1
        }
      }
    },
    "TierPricing": {
      "type": "object",
      "properties": {
        "currency": {
          "type": "string",
          "title": "Currency",
          "description": "3-letter ISO 4217 currency code.",
          "maxLength": 3
        },
        "unit_amount": {
          "type": "number",
          "format": "float",
          "title": "Unit price",
          "minimum": 0,
          "maximum": 1000000,
          "description": "Allows up to 2 decimal places. Required unless `unit_amount_decimal` is provided."
        },
        "unit_amount_decimal": {
          "type": "string",
          "title": "Unit Amount Decimal",
          "minimum": 0,
          "maximum": 1000000,
          "description": "Allows up to 9 decimal places.\nIf `unit_amount_decimal` is provided, `unit_amount` cannot be provided.\n"
        }
      },
      "required": [
        "currency"
      ]
    },
    "TierTypeEnum": {
      "type": "string",
      "title": "Tier type",
      "description": "The pricing model for the add-on.  For more information,\n[click here](https://docs.recurly.com/docs/billing-models#section-quantity-based). See our\n[Guide](https://recurly.com/developers/guides/item-addon-guide.html) for an overview of how\nto configure quantity-based pricing models.\n",
      "default": "flat",
      "enum": [
        "flat",
        "tiered",
        "stairstep",
        "volume"
      ]
    },
    "UsageCalculationTypeEnum": {
      "type": "string",
      "description": "The type of calculation to be employed for an add-on.  Cumulative billing will sum all usage records created in the current billing cycle.  Last-in-period billing will apply only the most recent usage record in the billing period.  If no value is specified, cumulative billing will be used.",
      "enum": [
        "cumulative",
        "last_in_period"
      ]
    },
    "UsageTimeframeCreateEnum": {
      "type": "string",
      "title": "Usage Timeframe",
      "description": "The time at which usage totals are reset for billing purposes.\nAllows for `tiered` add-ons to accumulate usage over the course of multiple\nbilling periods.\n",
      "enum": [
        "billing_period",
        "subscription_term"
      ],
      "default": "billing_period"
    },
    "UsageTypeCreateEnum": {
      "type": "string",
      "enum": [
        "price",
        "percentage"
      ],
      "title": "Usage Type",
      "description": "Type of usage, required if `add_on_type` is `usage`. See our\n[Guide](https://recurly.com/developers/guides/usage-based-billing-guide.html) for an\noverview of how to configure usage add-ons.\n"
    }
  }
}