> ## Documentation Index
> Fetch the complete documentation index at: https://docs.withorb.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Applying adjustments and discounts

Adjustments are modifications that can alter invoice totals or individual line items to implement pricing strategies like discounts, minimums, and maximums. They provide flexible control over billing calculations and can be applied at different scopes within your pricing structure.

## Types of adjustments

Orb supports several types of adjustments that can be applied to modify billing calculations:

### Discounts

**Amount discounts** subtract a fixed amount from the subtotal. For example, a \$100 discount reduces the charge by exactly \$100.

**Percentage discounts** reduce the subtotal by a percentage. For example, a 20% discount on a \$500 charge results in a \$400 final amount.

**Usage discounts** reduce the billable quantity before applying the pricing function. For example, "100 units off" reduces the billable quantity by 100 units before calculating the charge.

### Minimums and maximums

**Minimums** ensure that the adjusted subtotal doesn't fall below a specified amount. For example, "at least \$50" guarantees that the final charge will be no less than \$50, regardless of usage or other discounts.

<Note>
  **Important**: Minimum adjustments are not applied to invoices that contain
  only fixed fees. This rule ensures that minimums don't inappropriately apply
  to invoices consisting entirely of fixed fees, such as the first in-advance
  invoice for a subscription without usage-based charges.
</Note>

**Maximums** cap the adjusted subtotal at a specified amount. For example, "at most \$1000" ensures that the final charge will not exceed \$1000, even with high usage.

## Use cases for adjustments

Adjustments enable a wide range of billing scenarios:

* **Promotional discounts**: Offer temporary percentage or amount discounts to attract new customers or reward loyalty
* **Volume commitments**: Apply minimums to ensure customers meet spending commitments
* **Usage caps**: Use maximums to provide predictable billing for customers with variable usage
* **Employee discounts**: Create consistent discount structures for internal users
* **Custom pricing**: Implement negotiated terms for enterprise customers
* **Feature add-ons**: Apply targeted discounts to specific services or products
* **Seasonal promotions**: Time-limited discounts for marketing campaigns

## Creating adjustments

Adjustments can be created through several methods:

### Plan-level adjustments

Adjustments can be configured directly on [plans](/product-catalog/build-catalog) and will apply to all subscriptions using that plan. These are useful for standard pricing policies that should apply consistently across customers.

### Subscription-level adjustments

Individual adjustments can be added to specific [subscriptions](/product-catalog/creating-subscriptions) using the [subscription price intervals API](/api-reference/price-interval/add-or-edit-price-intervals). This allows for customer-specific pricing without modifying the underlying plan. See [editing subscriptions](/product-catalog/editing-subscriptions) for more details on how to add, remove, and change adjustments on subscriptions.

### Coupons

[Coupons](/api-reference/coupon/list-coupons) are a special way to create reusable adjustments that come with a redemption code and usage tracking. When a coupon is redeemed, Orb automatically creates the corresponding adjustment and adjustment interval, applying it to the subscription.

Coupons always create **subscription-scoped adjustments**, meaning they apply to all prices on the subscription by default. This means that any new prices added to the subscription (such as through plan changes or add-ons) will automatically be included in the coupon's discount.

**Key differences from direct adjustments:**

* **Redemption code**: Coupons have a unique code that customers can use to apply the discount
* **Usage tracking**: Coupons track how many times they've been redeemed and can have redemption limits
* **Reusability**: The same coupon can be applied to multiple subscriptions until it reaches its redemption limit
* **Duration control**: Coupons can have time-limited effectiveness by creating adjustment intervals with specific start and end dates

Coupons are particularly useful for promotional campaigns, employee discounts, and self-serve signup flows where customers need to apply discounts themselves.

**Redeeming coupons:**

Coupons can be redeemed using the `redemption_code` when:

* [Creating a subscription](/api-reference/subscription/create-subscription) - Apply the coupon from the start of the subscription
* [Scheduling a plan change](/api-reference/subscription/schedule-plan-change) - Apply the coupon when transitioning to a new plan

**Adjustment behavior during subscription changes:**

All adjustments, including those created by coupons, behave differently during mid-cycle changes:

* **Percentage discounts** continue to apply proportionally to new charges
* **Amount discounts** do not apply to mid-cycle upgrade invoices to prevent over-discounting

**Example: Mid-cycle upgrade with adjustment**

A user upgrades their seats with 5 days remaining in a 30-day billing cycle from 1 seat to 2 seats on a plan that costs \$60 per month per seat. A prorated charge of \$10 is added in a new invoice for the upgrade.

*Amount Discount (\$20):*

* Initial invoice: \$40 invoice total = \$60 for the 1 seat - \$20 coupon
* Upgrade invoice: \$10 prorated charge for 5 days with 2 seats. The discount does not apply to the second invoice.
* Total cost: \$50 (\$40 initial + \$10 upgrade).

*Percentage Discount (50%):*

* Initial invoice: \$30 invoice total = \$60 for the 1 seat - 50% discount
* Upgrade invoice: \$5 invoice total = \$10 prorated charge for seat 2 - 50% discount
* Total cost: \$35 (\$30 initial + \$5 upgrade)

<Note>
  Amount discounts don't apply to upgrade invoices to prevent scenarios where
  the upgrade would be free or over-discounted.
</Note>

## Adjustment targeting with filters

Orb uses a modern filter-based system to target adjustments precisely. This system consolidates multiple targeting dimensions into a unified model that supports price-, item-, and subscription-level scopes.

### Filter structure

Filters use the following format:

```json theme={null}
{
  "field": "price_id" | "item_id" | "price_type",
  "operator": "includes" | "excludes",
  "values": [...]
}
```

When multiple filters are specified, they are ANDed together, meaning line items must satisfy all filters to be included in the adjustment.

### Targeting options

**Subscription-scoped**: Apply to all prices on a subscription by using an empty filters array or `applies_to_all: true`.

**Item-scoped**: Target specific items using `item_id` filters. This is useful for applying discounts to particular products or services.

**Price-scoped**: Target specific [prices](/product-catalog/price-configuration) using `price_id` filters. This provides granular control over which charges receive adjustments.

**Price type-scoped**: Target prices by type using `price_type` filters with values like:

* `usage`: Any usage-based price attached to a billable metric
* `fixed_in_advance`: Fixed prices that bill in advance
* `fixed_in_arrears`: Fixed prices that bill in arrears

<Note>
  The `price_type` field on an adjustment is a shortcut for creating
  `price_type` filters. You cannot use both the `price_type` field and explicit
  filters on the same adjustment. Additionally, the `fixed` and `in_arrears`
  values are only valid for the `price_type` field (where they resolve to
  exclusion filters) but cannot be used as values in `price_type` filters
  themselves, which only support the inclusion values listed above.
</Note>

### Currency filter requirements

<Note>
  **Currency filter behavior**: For all adjustment types except percentage
  discounts, you must specify a currency filter. How you express it depends on
  your targeting approach: - **Shortcut fields** (`applies_to_item_ids`,
  `applies_to_price_ids`, `applies_to_all`): Use the top-level `currency` field

  * **Full filters**: Include a currency filter in the `filters` array (the
    top-level `currency` field is not allowed)
</Note>

### Filter examples

<Note>
  You should use only one of `applies_to_all`, `applies_to_item_ids`, or
  `applies_to_price_ids` in a single adjustment. Or, use `filters` instead to
  express more complex targeting logic.
</Note>

**Subscription-level discount**:

```json theme={null}
{
  "adjustment": {
    "applies_to_all": true,
    "currency": "USD",
    "is_invoice_level": true,
    "adjustment_type": "percentage_discount",
    "percentage_discount": "0.1"
  }
}
```

**Item-scoped maximum**:

```json theme={null}
{
  "adjustment": {
    "applies_to_item_ids": ["item_storage", "item_compute"],
    "currency": "USD",
    "is_invoice_level": true,
    "adjustment_type": "maximum",
    "maximum_amount": "1000"
  }
}
```

**Advanced filtering**:

```json theme={null}
{
  "adjustment": {
    "filters": [
      {
        "field": "item_id",
        "operator": "includes",
        "values": ["item_premium"]
      },
      {
        "field": "price_type",
        "operator": "includes",
        "values": ["usage"]
      }
    ],
    "is_invoice_level": true,
    "adjustment_type": "percentage_discount",
    "percentage_discount": "0.15"
  }
}
```

### Benefits of filter-based targeting

* **Consolidated targeting**: Express complex targeting rules in a single adjustment object
* **Durability**: Item and subscription scopes persist across [plan migrations](/product-catalog/price-changes), even when price IDs change
* **Flexibility**: Combine multiple targeting dimensions for precise control
* **Backward compatibility**: Legacy `applies_to_price_ids` continues to work alongside the new system

## Modifying adjustments

### Adjustment intervals

Adjustments are applied through adjustment intervals, which define the time period during which an adjustment is active. You can:

* **Add adjustments**: Create new adjustment intervals starting immediately or in the future
* **Remove adjustments**: End existing adjustment intervals at a specified date
* **Modify adjustments**: Replace existing adjustments by ending the current interval and creating a new one

### Timing behavior

Adjustment intervals determine whether adjustments apply to invoices based on the invoice date and the adjustment's time bounds:

* **In-arrears fees**: Adjustment interval is inclusive of its end bound
* **In-advance fees**: Adjustment interval is inclusive of its start bound
* **Mixed fees**: Interval is inclusive on both bounds

**Backdated adjustments and invoice reissuance:**

When you create adjustment intervals with start dates in the past, Orb will automatically reissue any affected invoices to ensure they reflect the correct pricing. This happens because Orb maintains consistency between subscription state and invoice state using its [diff-based billing engine](/architecture/billing-architecture).

For example, if you add a 10% discount effective from the beginning of the current month and invoices have already been issued for that period, Orb will:

1. Calculate what the invoices should have been with the discount applied
2. Void the original invoices
3. Issue new invoices with the correct discounted amounts

This automatic correction ensures that your billing records always accurately reflect your intended pricing policies, even when adjustments are applied retroactively.

### API operations

Use the [subscription price intervals API](/api-reference/price-interval/add-or-edit-price-intervals) to:

```json theme={null}
{
  "add_adjustments": [
    {
      "adjustment": {
        "applies_to_all": true,
        "adjustment_type": "percentage_discount",
        "percentage_discount": "0.2"
      },
      "start_date": "2024-01-01",
      "end_date": "2024-03-31"
    }
  ]
}
```

## Adjustments and plan version migrations

When you perform [plan version migrations](/product-catalog/price-changes#migrating-subscriptions-to-a-new-version), adjustments behave differently depending on how they were originally configured. Understanding this behavior is crucial for maintaining consistent pricing policies across plan changes.

### Plan-level adjustments

**Automatic remapping**: Adjustments configured at the plan level automatically adapt to plan version changes. When a price is edited in a new plan version (creating a new price ID), Orb automatically remaps the adjustment to apply to the replacement price.

**Example**: If you have a plan-level 10% discount that applies to all prices, and you edit a usage-based price in a new plan version, the discount will automatically apply to the new price ID without any manual intervention.

### Subscription-level adjustments with price IDs

**No automatic remapping**: Adjustments added directly to subscriptions using `applies_to_price_ids` cannot be automatically remapped during migrations. Since these adjustments target specific price IDs, they become "orphaned" when those prices are replaced with new IDs.

**Migration protection**: To prevent unintended consequences, Orb will fail the migration for subscriptions that have ad-hoc adjustments targeting prices that are being modified. This ensures you don't accidentally lose discount policies or create billing inconsistencies.

**Manual intervention required**: You'll need to manually update these adjustments before or after the migration to target the new price IDs.

### Filter-based adjustments advantage

Filter-based adjustments provide superior durability during plan migrations because they express intent rather than targeting specific price IDs:

**Subscription-scoped filters** (`applies_to_all: true` or empty `filters` array):

* Continue to apply to all prices on the subscription, including new ones added during migration
* No manual intervention required

**Item-scoped filters** (`item_id` targeting):

* Continue to apply to prices associated with the same items, even when price IDs change
* Automatically include new prices for the same items

**Price type-scoped filters** (`price_type` targeting):

* Continue to apply to prices of the same type (e.g., all usage-based prices)
* Automatically include new prices of the matching type

**Example of filter durability**:

```json theme={null}
{
  "filters": [
    {
      "field": "item_id",
      "operator": "includes",
      "values": ["storage_item"]
    }
  ]
}
```

This adjustment will continue to apply to all storage-related prices, regardless of plan version changes or new price IDs.

### Best practices for migrations

1. **Use filter-based targeting** for new adjustments to ensure they survive plan migrations
2. **Review subscription-level adjustments** before performing migrations to identify potential conflicts
3. **Consider converting legacy price ID-based adjustments** to filter-based ones before major plan changes
4. **Test migrations on a small subset** of subscriptions to verify adjustment behavior

<Note>
  For advanced functionality to automatically apply existing adjustments to
  replacement prices during migrations, please reach out to Orb support for
  access to private preview features.
</Note>

## Invoice calculations

Adjustments are applied during invoice calculation in a specific order to ensure consistent and predictable results. The calculation process follows these steps:

1. **Determine Line Item Quantity**
2. **Apply the Pricing Function** - Calculates the subtotal based on the quantity
3. **Apply Line Item Level Adjustments** in order: usage discounts, amount discounts, percentage discounts, minimums, maximums
4. **Apply Multi-Price/Invoice Level Adjustments** in the same order
5. **Apply Prepaid Credits** (in-arrears charges only)
6. **Apply Overage Conversion** (if applicable)
7. **Subtract Previously Invoiced Amounts** (for threshold billing)
8. **Apply Line Item Tax**

### Adjustments and custom currencies

For prices configured with custom currencies (virtual pricing units), adjustments are applied in the price's original currency before any overage conversion takes place. This means:

* **Adjustments operate in the custom currency**: A discount on a price denominated in "API credits" will reduce the credit amount before conversion to real currency
* **No adjustments on overage charges**: You cannot apply adjustments specifically to the overage portion after prepaid credits are exhausted
* **Conversion happens after adjustments**: The adjusted amount is then converted to the real-world currency using the configured conversion rate

**Example**: If you have a price in "Database credits" with a 10% discount and the customer uses 1000 credits:

1. Base charge: 1000 Database credits
2. Apply 10% discount: 900 Database credits
3. Apply prepaid credits: Subtract available credits from the 900
4. Convert overage: Any remaining credits convert to USD at the configured rate

### Adjustment distribution

When adjustments apply to multiple prices, they are distributed proportionally based on each line item's share of the total subtotal, except for minimums which are distributed evenly.

For detailed information about how adjustments factor into invoice calculations, including examples and edge cases, see the [Invoice calculations](/invoicing/invoice-calculations) documentation.
