> ## 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.

# Turn Product Activity into a Charge

> Connect application events, meters, product prices, and customer balances

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>Usage-based billing is new. Share implementation feedback with the Ruba team.</Info>

A metered charge starts as activity inside your application. Ruba receives that activity as events, measures matching events with a meter, and applies the meter's price through a subscription product.

## Follow one unit of usage

```text theme={"system"}
Application action → Event → Meter filter and aggregation → Metered price → Customer estimate and invoice
```

Credits can sit between the measured usage and the final charge, allowing prepaid units to be consumed before overage is billed.

## Records in the flow

### What your application sends

An event is one timestamped record of something a buyer consumed inside your application. Your application sends these records to Ruba, and meters turn them into billable quantities. Common examples include tokens processed, video minutes streamed, or storage uploaded.

Send events through the [ingestion endpoint](/api-reference/events/ingest). Each record carries:

* `name`: the activity category, such as `ai_usage` or `file_uploaded`.
* `customer_id` or `external_customer_id`: the buyer responsible for the activity.
* `metadata`: numbers and labels that a meter can filter or aggregate.

For example, this record captures one model request and its token counts:

```json theme={"system"}
{
  "name": "ai_usage",
  "external_customer_id": "cus_123",
  "metadata": {
    "model": "gpt-4.1-nano",
    "requests": 1,
    "total_tokens": 77,
    "request_tokens": 58,
    "response_tokens": 19
  }
}
```

### How Ruba measures it

A meter is the rule that turns raw events into a usage total. It chooses which events count, optionally narrows them through metadata filters, and applies an aggregation such as count or sum.

Examples:

* Match `ai_usage` and sum `total_tokens` to bill for model consumption.
* Match `video_streamed` and sum `duration` to charge by viewing time.
* Match `file_uploaded` and sum `size` to price storage intake.

Create meters from the dashboard. Ruba maintains both organization-wide and per-customer totals, so the same definition can power billing, customer balances, and usage reporting.

### How measured units become money

A metered price converts recorded consumption into an amount due. Ruba first selects the events that match a meter, applies that meter's aggregation rule, and then prices the resulting quantity. Use it whenever the buyer's bill should follow what they actually consumed.

### How prepaid units enter the balance

Meter credits give a buyer a prepaid usage allowance for one meter. Add a **Meter Credits** benefit to a product, choose the meter, and enter the number of units included.

For recurring products, Ruba refreshes that allowance at the start of each billing period. A monthly subscription receives new credits monthly; an annual subscription receives them once per year.

## Build the first meter

<Steps>
  <Step title="Define measurement">
    Create a meter with an event filter and an aggregation function. The filter selects qualifying events; the aggregation converts them into billable usage.

    <img className="block dark:hidden" src="https://mintcdn.com/ruba/JDRjNJtBhntQypch/assets/features/usage/create-meter.light.png?fit=max&auto=format&n=JDRjNJtBhntQypch&q=85&s=7c5565a1e50b9545d145cec4bf1a7d05" width="3598" height="2070" data-path="assets/features/usage/create-meter.light.png" />

    <img className="hidden dark:block" src="https://mintcdn.com/ruba/JDRjNJtBhntQypch/assets/features/usage/create-meter.dark.png?fit=max&auto=format&n=JDRjNJtBhntQypch&q=85&s=30bb75ca82ed7713e6692a72db9615bd" width="3590" height="2066" data-path="assets/features/usage/create-meter.dark.png" />
  </Step>

  <Step title="Price the result">
    Add a metered price that references the meter to a subscription product. Metered prices are not available for one-time products.

    <img className="block dark:hidden" src="https://mintcdn.com/ruba/JDRjNJtBhntQypch/assets/features/usage/product-meter.light.png?fit=max&auto=format&n=JDRjNJtBhntQypch&q=85&s=7325cb0322655011382209d690b86a46" width="2552" height="1600" data-path="assets/features/usage/product-meter.light.png" />

    <img className="hidden dark:block" src="https://mintcdn.com/ruba/JDRjNJtBhntQypch/assets/features/usage/product-meter.dark.png?fit=max&auto=format&n=JDRjNJtBhntQypch&q=85&s=1d50227788e66899b1adeb951ab9e4bc" width="2548" height="1596" data-path="assets/features/usage/product-meter.dark.png" />
  </Step>

  <Step title="Send production events">
    Ingest application events. Events matching the filter increase that customer's measured usage.

    <img className="block dark:hidden" src="https://mintcdn.com/ruba/JDRjNJtBhntQypch/assets/features/usage/ingest.light.png?fit=max&auto=format&n=JDRjNJtBhntQypch&q=85&s=0a276a196bcc82803558d74a3cb81194" width="1572" height="1104" data-path="assets/features/usage/ingest.light.png" />

    <img className="hidden dark:block" src="https://mintcdn.com/ruba/JDRjNJtBhntQypch/assets/features/usage/ingest.dark.png?fit=max&auto=format&n=JDRjNJtBhntQypch&q=85&s=4f060317c83b5f310f61c4a36c1aa3e1" width="1566" height="1102" data-path="assets/features/usage/ingest.dark.png" />
  </Step>

  <Step title="Expose the estimate">
    Customers can inspect estimated charges for each meter in the Customer Portal.

    <img className="block dark:hidden" src="https://mintcdn.com/ruba/JDRjNJtBhntQypch/assets/features/usage/portal.light.png?fit=max&auto=format&n=JDRjNJtBhntQypch&q=85&s=071e3afa00b55c9075eba49bbea15d8c" width="2358" height="1218" data-path="assets/features/usage/portal.light.png" />

    <img className="hidden dark:block" src="https://mintcdn.com/ruba/JDRjNJtBhntQypch/assets/features/usage/portal.dark.png?fit=max&auto=format&n=JDRjNJtBhntQypch&q=85&s=954198bd31a37638bebd646608c68bed" width="2364" height="1214" data-path="assets/features/usage/portal.dark.png" />
  </Step>
</Steps>
