# Usage Metering

:::note
**Usage metering is enabled** (as of August 2026). Fours aggregates each entitlement's pending usage and
submits it to Oracle Cloud Infrastructure hourly. Metered usage bills **in addition to** the offer's
contract value, not instead of it.
:::

## Overview

For usage-based products, Fours reports metered usage back to Oracle Cloud Marketplace (OCI) so buyers are
billed for what they consume. You report usage to Fours with the same
[Metering API](/metering/) you use for every other marketplace; Fours submits it to OCI on an
hourly cadence.

Oracle's usage model differs from the other marketplaces in one important way, described next.

## You report an amount, not a quantity

:::warning
For Oracle entitlements, the value you report **is the monetary amount** — not a quantity that Fours
multiplies by a rate. Reporting `10` means **10 units of currency**, not 10 units of consumption.
:::

OCI has no usage-dimension catalog and no per-dimension pricing, so there is no rate for Fours to apply.
This means:

- The value you send is forwarded to OCI as the charge, in the entitlement's currency.
- Your own system owns the pricing calculation — compute the amount before you report it.
- Decimal amounts are supported; the submitted amount is rounded to 5 decimal places (OCI's
  per-record limit), and an amount that rounds to zero is skipped.

If you are porting an integration from AWS, Azure, or GCP, this is the one change you must make: send money
where you previously sent a quantity.

## Usage keys are open

Because there is no dimension catalog to validate against, Oracle accepts **any** usage key:

- You may report against any key name you choose; it is registered on the entitlement the first time it is
  seen, and no configuration step is required in advance.
- The key is submitted to OCI as the `usageDimensionName`.
- An entitlement may accumulate at most **100 distinct usage keys**. This matches the maximum number of
  records OCI accepts in a single submission, so an entitlement that stays within the limit can always be
  reported. Beyond it, further new keys are rejected at ingestion.

## Commit and usage are separate

An offer's commit or prepaid amount does **not** reduce reported usage. Fours forwards Oracle usage exactly
as reported, with no commit, credit, or included-usage deduction applied. Track commit consumption
separately from metered usage.

## Reporting cadence and windows

- Fours aggregates each entitlement's pending usage and submits it to OCI **hourly**.
- A submission carries at most **100 usage records** — one per non-zero usage key — which is OCI's own
  per-call limit.
- A submission is **all-or-nothing**: if OCI rejects any record in the batch, the whole batch is rejected
  and no usage in it is recorded.
- The window Fours tells OCI is the span of the **usage** — from the earliest to the latest usage timestamp
  in the batch — not the hour the run happened to execute in. Usage you report late, or backfill with an
  older timestamp, is therefore attributed to when it actually occurred. The report record you see in
  Fours carries its own, wider window based on when the usage arrived, so the two legitimately differ.
- Zero-amount records are skipped — OCI rejects them, and a report containing only zero amounts is treated
  as a successful no-op.

## Duplicate protection

Every record Fours submits carries an identifier derived **deterministically** from the usage it
represents — the organization, the entitlement, the exact set of usage record groups in the submission, and
the dimension key. Resubmitting the same set therefore produces the same identifiers, and OCI recognises the
repeat and ignores it. Fours sends the same identity as OCI's `opc-retry-token` as well, a second, 24-hour
backstop. If OCI reports that the usage was already recorded, Fours treats the submission as successful.

That is what makes an **automatic** retry safe: it resends an identical submission.

:::warning
**A manual retry is only as safe as the group set it rebuilds.** Retrying a `REPORT_FAILED` usage record
group returns it to `CREATED`, and the next hourly run re-aggregates **every** `CREATED` group for that
entitlement. If any group has been created in the meantime — or you retry only part of a failed batch — the
set differs from the original submission, so the derived identifiers differ and **OCI cannot recognise the
resubmission as a repeat**. The risk case is a submission that actually reached OCI but was recorded as
failed on Fours' side, for example a timeout or a lost acknowledgement.

Reconcile in OCI before retrying — see [Confirm in OCI before a manual retry](#confirm-in-oci-before-a-manual-retry).
:::

This is the sequence, and where the two retry paths diverge:

```d2
direction: down
shape: sequence_diagram

suger: "Fours"
oci: "OCI"

suger -> oci: "submitUsageRecords\nid = hash(org, entitlement, group set, dimension)"
oci -> suger: "timeout — outcome unknown"

auto: "Automatic retry (safe)" {
  suger -> oci: "same submission, same ids"
  oci -> suger: "already recorded → ignored, no second charge"
}

manual: "Manual retry (verify first)" {
  suger -> suger: "group returns to CREATED;\nnext run re-aggregates every CREATED group"
  suger -> oci: "different group set → different ids"
  oci -> suger: "not recognised as a repeat → CHARGED AGAIN"
}
```

### Confirm in OCI before a manual retry

Fours keeps the full audit of every OCI submission on the usage record report, so you can check exactly what
was sent before you resend it. Fetch the report with
[List usage record reports](/api/list-usage-record-reports/) and read:

| Field on the report | What it tells you |
|---|---|
| `info.oracleMeteringRequest.records[].id` | The exact OCI usage-record identifiers that were submitted. These are what OCI deduplicates on |
| `info.oracleMeteringRequest.records[].amount` / `.usageDimensionName` | The amount and dimension in that submission |
| `info.oracleMeteringRequest.idempotencyToken` | The `opc-retry-token` sent with the call |
| `info.oracleMeteringResponse.opcRequestId` | OCI's `opc-request-id` for the call — quote this to Oracle Support when checking whether a submission landed |
| `info.oracleMeteringResponse.error` | Why OCI rejected it, when it did |

Then, in the OCI console, check the metered usage for the offer (`marketplaceOfferId`) over the report's
usage window. Retry only when the usage is **absent** in OCI. If it is present, the submission landed and
the `REPORT_FAILED` status is a lost acknowledgement — delete the group instead of retrying it, or contact
[support@suger.io](mailto:support@suger.io) so the report can be reconciled without double-billing.

Oracle's own rule is the same one: a retry of a usage record must reuse the original record ID, and a new
ID must not be minted because a request timed out or failed retryably. See
[Oracle's metered-usage record reference](https://docs.oracle.com/en-us/iaas/Content/Marketplace/usage-based-record-fwd.htm).

## Viewing reported usage

Reported Oracle usage appears in the console under **Metering**, with `ORACLE` available in the partner
filter on both the usage list and the aggregated reports. Failed submissions are visible there, and
alerting covers usage that stays unreported.

## Prerequisites

- A verified [Oracle Marketplace integration](/oracle-marketplace/integration).
- An active entitlement derived from an accepted [private offer](/oracle-marketplace/private-offers).
- The OCI IAM policy that permits usage submission must be granted in your partner tenancy. Without it,
  submissions are rejected with an authorization error.
