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

# Model What You Sell

> Begin offering digital goods through Ruba within minutes.

export const RubaSocials = () => {
  if (typeof document === "undefined") {
    return null;
  }
  const inject = () => {
    const footer = document.getElementById("footer");
    if (!footer || document.getElementById("ruba-socials")) {
      return false;
    }
    const isDark = document.querySelector("html.dark") || document.querySelector('html[class*="dark"]');
    const lineColor = isDark ? "#383838" : "#e8e8ed";
    const iconColor = isDark ? "#8e8e93" : "#86868b";
    const markColor = isDark ? "#ffffff" : "#08080c";
    const hoverColor = "#0071e3";
    const div = document.createElement("div");
    div.id = "ruba-socials";
    div.style.cssText = `display:flex;align-items:center;gap:20px;padding-top:20px;margin-top:20px;border-top:1px solid ${lineColor};width:100%`;
    const logo = `<a href="https://getruba.com" style="display:inline-flex;height:24px;align-items:center;gap:8px;text-decoration:none;color:${markColor};line-height:1;"><svg width="24" height="24" viewBox="0 0 120 120" aria-hidden="true" style="display:block;flex:none;"><g transform="translate(2.5 0)"><path d="M19 25h59L65.43 47H19a4 4 0 0 1-4-4V29a4 4 0 0 1 4-4Z" fill="${markColor}"/><path d="M19 73h31.57L38 95H19a4 4 0 0 1-4-4V77a4 4 0 0 1 4-4Z" fill="${markColor}"/><path d="M85 25h25L70 95H45Z" fill="#007AFF"/></g></svg><span style="display:inline-flex;height:24px;align-items:center;font-weight:600;font-size:15px;color:${markColor};letter-spacing:-0.01em;line-height:1;">Ruba</span></a>`;
    const spacer = `<div style="flex:1"></div>`;
    const ig = `<a href="https://instagram.com/getruba" target="_blank" rel="noopener" aria-label="Instagram" style="display:flex;align-items:center;color:${iconColor};transition:color 0.15s ease;" onmouseover="this.style.color='${hoverColor}'" onmouseout="this.style.color='${iconColor}'"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="2" width="20" height="20" rx="5" ry="5"/><path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z"/><line x1="17.5" y1="6.5" x2="17.51" y2="6.5"/></svg></a>`;
    const li = `<a href="https://linkedin.com/company/getruba" target="_blank" rel="noopener" aria-label="LinkedIn" style="display:flex;align-items:center;color:${iconColor};transition:color 0.15s ease;" onmouseover="this.style.color='${hoverColor}'" onmouseout="this.style.color='${iconColor}'"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z"/><rect x="2" y="9" width="4" height="12"/><circle cx="4" cy="4" r="2"/></svg></a>`;
    const x = `<a href="https://x.com/getruba" target="_blank" rel="noopener" aria-label="X" style="display:flex;align-items:center;color:${iconColor};transition:color 0.15s ease;" onmouseover="this.style.color='${hoverColor}'" onmouseout="this.style.color='${iconColor}'"><svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg></a>`;
    const github = `<a href="https://github.com/rubadot" target="_blank" rel="noopener" aria-label="GitHub" style="display:flex;align-items:center;color:${iconColor};transition:color 0.15s ease;" onmouseover="this.style.color='${hoverColor}'" onmouseout="this.style.color='${iconColor}'"><svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M12 .7a11.5 11.5 0 0 0-3.64 22.4c.58.1.79-.25.79-.56v-2.24c-3.22.7-3.9-1.37-3.9-1.37-.53-1.34-1.29-1.7-1.29-1.7-1.05-.72.08-.71.08-.71 1.16.08 1.78 1.2 1.78 1.2 1.04 1.77 2.72 1.26 3.38.96.1-.75.4-1.26.74-1.55-2.57-.3-5.27-1.29-5.27-5.69 0-1.26.45-2.29 1.19-3.09-.12-.29-.52-1.47.11-3.05 0 0 .97-.31 3.16 1.18A10.96 10.96 0 0 1 12 6.09c.98 0 1.94.13 2.86.39 2.2-1.49 3.16-1.18 3.16-1.18.63 1.58.23 2.76.11 3.05.74.8 1.19 1.83 1.19 3.09 0 4.42-2.7 5.39-5.28 5.68.42.36.79 1.06.79 2.14v3.28c0 .31.21.67.8.56A11.5 11.5 0 0 0 12 .7Z"/></svg></a>`;
    div.innerHTML = logo + spacer + ig + li + x + github;
    footer.appendChild(div);
    return true;
  };
  if (!document.documentElement.dataset.rubaSocialsObserver) {
    document.documentElement.dataset.rubaSocialsObserver = "true";
    const observer = new MutationObserver(() => {
      if (!document.getElementById("ruba-socials")) {
        inject();
      }
    });
    observer.observe(document.body, {
      childList: true,
      subtree: true
    });
  }
  setTimeout(() => {
    if (!inject()) {
      const interval = setInterval(() => {
        if (inject()) {
          clearInterval(interval);
        }
      }, 500);
      setTimeout(() => clearInterval(interval), 10000);
    }
  }, 300);
  return null;
};

<link rel="stylesheet" href="/style.css" />

<RubaSocials />

<Info>
  **Every item is a product**

  Recurring and one-off purchases both count as products inside Ruba: they share the same API and data model, differing only in their pricing and billing rules. You manage them side by side on the Products screen, where you can filter by the pricing model in use.
</Info>

## Payment frequency

A product falls into one of two categories: a **single charge** or a **recurring** plan. Single-charge products bill the buyer once and grant access permanently. Recurring products invoice on a chosen cadence, daily, weekly, monthly, or yearly, and you can multiply any unit with an interval count to express schedules such as "every 2 weeks" or "every 3 months".

The billing cadence and recurring interval are fixed at the moment you create a product. Should you need different values later, spin up a new product instead.

## Setting your price

Ruba supports several pricing models, and you choose a single one per product:

* **Fixed price.** Pick an amount and that is the amount buyers pay.
* **Pay what you want.** Buyers decide the amount. You may set both a floor and a pre-filled default shown at checkout.
* **Free.** No charge at all. Handy for lead magnets, free tiers, or gating perks behind a sign-up.
* **Metered pricing.** Invoice based on consumption: bill per API call, per token, per any unit you can count. [Learn more about usage-based billing](/features/usage-based-billing/introduction).
* **Seat-based pricing.** Sell a bundle of seats with optional volume tiers, then let the buyer hand them out to teammates. [Learn more about seat-based billing](/features/seat-based-pricing).

Metered prices layer on top of the other models. You can combine one with a fixed base fee for a classic "base plus usage" plan, and you can attach several metered prices to the same product when you want to bill across more than one dimension at once, for instance per API call *and* per GB of storage.

The pricing model is fixed at creation, though fixed-price products let you adjust the amount whenever you like. Current subscribers are **grandfathered** at the amount they originally signed up for, so a price bump only touches new purchases. When you do want to move someone onto the updated amount, you can do so [per subscription](/features/subscriptions/manage) from the dashboard or the API.

Whether the amount you enter already includes tax or has tax added afterward depends on your tax behavior setting. By default, Ruba applies the convention that fits the buyer's country (inclusive across most of the world, exclusive in the US, Canada, and India). You can set your own default under **Settings**. See [Tax Inclusive Pricing](/features/tax-inclusive-pricing) for how the amount you configure maps to what buyers ultimately pay.

### Pricing across several currencies

Products can carry prices in multiple currencies at once so buyers pay in their local currency. Your organization holds a default payment currency that serves as the fallback, and you can layer additional ones on top. The price structure (price type, metered prices, and so on) must line up across every currency you enable.

Ruba chooses the currency from the buyer's geolocation at checkout. When that currency is not enabled on the product, it falls back to your organization's default.

<Warning>
  **Building checkout sessions from a backend or proxy?** Ruba infers the buyer's geolocation from the IP address of the request that creates the session. When you create sessions server-side (an API, a Cloudflare Worker, and so on), Ruba sees *your server's* IP and may select the wrong currency.

  Forward the buyer's IP as [`customer_ip_address`](/features/checkout/session#customer-ip-address) when creating the session.
</Warning>

<Accordion title="Supported currencies">
  Ruba supports 130+ currencies for product pricing:

  | Code  | Currency                            |
  | ----- | ----------------------------------- |
  | `AED` | United Arab Emirates Dirham         |
  | `ALL` | Albanian Lek                        |
  | `AMD` | Armenian Dram                       |
  | `AOA` | Angolan Kwanza                      |
  | `ARS` | Argentine Peso                      |
  | `AUD` | Australian Dollar                   |
  | `AWG` | Aruban Florin                       |
  | `AZN` | Azerbaijani Manat                   |
  | `BAM` | Bosnia-Herzegovina Convertible Mark |
  | `BBD` | Barbadian Dollar                    |
  | `BDT` | Bangladeshi Taka                    |
  | `BIF` | Burundian Franc                     |
  | `BMD` | Bermudan Dollar                     |
  | `BND` | Brunei Dollar                       |
  | `BOB` | Bolivian Boliviano                  |
  | `BRL` | Brazilian Real                      |
  | `BSD` | Bahamian Dollar                     |
  | `BWP` | Botswanan Pula                      |
  | `BZD` | Belize Dollar                       |
  | `CAD` | Canadian Dollar                     |
  | `CDF` | Congolese Franc                     |
  | `CHF` | Swiss Franc                         |
  | `CLP` | Chilean Peso                        |
  | `CNY` | Chinese Yuan                        |
  | `COP` | Colombian Peso                      |
  | `CRC` | Costa Rican Colón                   |
  | `CVE` | Cape Verdean Escudo                 |
  | `CZK` | Czech Koruna                        |
  | `DJF` | Djiboutian Franc                    |
  | `DKK` | Danish Krone                        |
  | `DOP` | Dominican Peso                      |
  | `DZD` | Algerian Dinar                      |
  | `EGP` | Egyptian Pound                      |
  | `ETB` | Ethiopian Birr                      |
  | `EUR` | Euro                                |
  | `FJD` | Fijian Dollar                       |
  | `FKP` | Falkland Islands Pound              |
  | `GBP` | British Pound                       |
  | `GEL` | Georgian Lari                       |
  | `GIP` | Gibraltar Pound                     |
  | `GMD` | Gambian Dalasi                      |
  | `GNF` | Guinean Franc                       |
  | `GTQ` | Guatemalan Quetzal                  |
  | `GYD` | Guyanaese Dollar                    |
  | `HKD` | Hong Kong Dollar                    |
  | `HNL` | Honduran Lempira                    |
  | `HTG` | Haitian Gourde                      |
  | `HUF` | Hungarian Forint                    |
  | `IDR` | Indonesian Rupiah                   |
  | `ILS` | Israeli New Shekel                  |
  | `INR` | Indian Rupee                        |
  | `ISK` | Icelandic Króna                     |
  | `JMD` | Jamaican Dollar                     |
  | `JPY` | Japanese Yen                        |
  | `KES` | Kenyan Shilling                     |
  | `KGS` | Kyrgystani Som                      |
  | `KHR` | Cambodian Riel                      |
  | `KMF` | Comorian Franc                      |
  | `KRW` | South Korean Won                    |
  | `KYD` | Cayman Islands Dollar               |
  | `KZT` | Kazakhstani Tenge                   |
  | `LAK` | Laotian Kip                         |
  | `LKR` | Sri Lankan Rupee                    |
  | `LRD` | Liberian Dollar                     |
  | `LSL` | Lesotho Loti                        |
  | `MAD` | Moroccan Dirham                     |
  | `MDL` | Moldovan Leu                        |
  | `MGA` | Malagasy Ariary                     |
  | `MKD` | Macedonian Denar                    |
  | `MNT` | Mongolian Tugrik                    |
  | `MOP` | Macanese Pataca                     |
  | `MUR` | Mauritian Rupee                     |
  | `MVR` | Maldivian Rufiyaa                   |
  | `MWK` | Malawian Kwacha                     |
  | `MXN` | Mexican Peso                        |
  | `MYR` | Malaysian Ringgit                   |
  | `MZN` | Mozambican Metical                  |
  | `NAD` | Namibian Dollar                     |
  | `NGN` | Nigerian Naira                      |
  | `NIO` | Nicaraguan Córdoba                  |
  | `NOK` | Norwegian Krone                     |
  | `NPR` | Nepalese Rupee                      |
  | `NZD` | New Zealand Dollar                  |
  | `PAB` | Panamanian Balboa                   |
  | `PEN` | Peruvian Sol                        |
  | `PGK` | Papua New Guinean Kina              |
  | `PHP` | Philippine Peso                     |
  | `PKR` | Pakistani Rupee                     |
  | `PLN` | Polish Zloty                        |
  | `PYG` | Paraguayan Guarani                  |
  | `QAR` | Qatari Riyal                        |
  | `RON` | Romanian Leu                        |
  | `RSD` | Serbian Dinar                       |
  | `RWF` | Rwandan Franc                       |
  | `SAR` | Saudi Riyal                         |
  | `SBD` | Solomon Islands Dollar              |
  | `SCR` | Seychellois Rupee                   |
  | `SEK` | Swedish Krona                       |
  | `SGD` | Singapore Dollar                    |
  | `SHP` | St. Helena Pound                    |
  | `SOS` | Somali Shilling                     |
  | `SRD` | Surinamese Dollar                   |
  | `SZL` | Swazi Lilangeni                     |
  | `THB` | Thai Baht                           |
  | `TJS` | Tajikistani Somoni                  |
  | `TOP` | Tongan Paʻanga                      |
  | `TRY` | Turkish Lira                        |
  | `TTD` | Trinidad & Tobago Dollar            |
  | `TWD` | New Taiwan Dollar                   |
  | `TZS` | Tanzanian Shilling                  |
  | `UAH` | Ukrainian Hryvnia                   |
  | `UGX` | Ugandan Shilling                    |
  | `USD` | US Dollar                           |
  | `UYU` | Uruguayan Peso                      |
  | `UZS` | Uzbekistani Som                     |
  | `VND` | Vietnamese Dong                     |
  | `VUV` | Vanuatu Vatu                        |
  | `WST` | Samoan Tala                         |
  | `XAF` | Central African CFA Franc           |
  | `XCD` | East Caribbean Dollar               |
  | `XCG` | Caribbean Guilder                   |
  | `XOF` | West African CFA Franc              |
  | `XPF` | CFP Franc                           |
  | `YER` | Yemeni Rial                         |
  | `ZAR` | South African Rand                  |
  | `ZMW` | Zambian Kwacha                      |
</Accordion>

## Free trial windows

For recurring products, flip on **Enable trial period** to give buyers a stretch where they are not billed. Choose a number and a unit (days, weeks, months, or years) and Ruba takes care of everything else.

[Learn more about trials](/features/subscriptions/trials).

## Checkout experience

How your product shows up during checkout.

### Checkout description

Optional copy that shows on the checkout page. Use it to pitch the offering, list what is included, or anything else that nudges the buyer to commit. Markdown is supported.

### Product imagery

Upload images to surface on the checkout page. Each image can be up to 10MB, and you can re-order or delete them whenever you like.

### Checkout form fields

Gather extra details from buyers at checkout: phone numbers, terms-of-service agreements, custom data you need for fulfillment, anything you want.

Fields are defined once at the organization level and then switched on per product, where you also decide whether each one is mandatory. Supported field types: text, number, date, checkbox, and select.

<Info>
  A required checkbox holds back confirmation until the buyer ticks it. Useful for legal terms.
</Info>

The captured values appear on the resulting order or subscription.

## Automatic benefit delivery

Benefits are the actual entitlements your buyers receive when they pay: license keys, Discord roles, GitHub repository access, file downloads, feature flags, or a custom benefit you wire up yourself.

Ruba grants and revokes benefits on its own as buyers purchase, renew, or cancel. [Learn more about benefits](/features/benefits/introduction).

## Custom metadata

You can attach arbitrary key-value metadata to a product. It stays hidden from buyers, but it rides along on every order, subscription, and webhook connected to the product, which makes it handy for tracking internal IDs or categories that live outside Ruba.

## Editing a product

Most things on a product can be edited afterward, save for the billing cadence and pricing model, which are fixed at creation. To change either, build a new product.

A few things worth knowing:

* **Current subscribers keep their original amount.** Adjusting a fixed price only impacts new purchases.
* **Benefit changes ripple through.** Add a benefit and existing buyers get it automatically. Remove one and they lose access.
* **Need a similar product?** Pick **Duplicate Product** from the product menu to clone an existing one as a starting point, handy for standing up a yearly variant of a monthly plan, or for A/B testing pricing.

## Archiving a product

Products can be archived but not permanently deleted. Click **Archive** from the product menu and the product drops out of new checkouts.

Existing buyers retain their access, and active subscriptions keep renewing. You can unarchive whenever you like from the same menu to make the product purchasable again.

## Decisions and edge cases

<AccordionGroup>
  <Accordion title="What about variants? Can I sell a monthly and a yearly version of the same product?">
    Ruba takes a different approach to what the industry typically calls **variants**. Each product carries a single pricing model, and rather than bolting variants onto one product, you build one product per pricing model and present them side by side at checkout.

    So a "monthly" and "yearly" plan are two products, each with its own pricing and benefits, shown side by side via [Checkout Links](/features/checkout/links) or the [Checkout Session API](/features/checkout/session). It keeps the API and the data model clean, and gives you full freedom over what each option includes.
  </Accordion>

  <Accordion title="Can I change the price of a product after publishing it?">
    Yes, for fixed-price products. Current subscribers are grandfathered at their original amount and only new purchases see the updated figure, but you can shift individual subscribers onto the new amount [per subscription](/features/subscriptions/manage) if you wish. Billing cadence and pricing model can't change.
  </Accordion>

  <Accordion title="Can I sell usage-based or metered products?">
    Yes. Set the price type to **Metered** and link it to a meter that tracks the events you care about. Full walkthrough in the [usage-based billing guide](/features/usage-based-billing/introduction).
  </Accordion>

  <Accordion title="Can I sell team or per-seat plans?">
    Yes, via [seat-based pricing](/features/seat-based-pricing). The buyer pays for a number of seats and assigns them to teammates, who each receive the product's benefits.
  </Accordion>

  <Accordion title="Will buyers see prices in their local currency?">
    If you have enabled extra payment currencies on the product, yes: Ruba matches the buyer's geolocation to one of the enabled currencies. When there is no match, it falls back to your organization's default. See [Pricing across several currencies](#pricing-across-several-currencies) above.
  </Accordion>

  <Accordion title="Can I duplicate a product?">
    Yes. From the product list or the product menu, pick **Duplicate Product** to clone all the settings into a new draft you can tweak before saving.
  </Accordion>
</AccordionGroup>
