Suger

Report Usage via API

Overview

You report usage to Suger, against a Suger entitlement; Suger aggregates pending usage and submits it to OCI on an hourly cadence. The endpoints are the same generic Metering API used for every marketplace — this page documents the Oracle-specific field semantics.

The two rules that make Oracle different from AWS/Azure/GCP:

  1. The value you report is a monetary amount, not a quantity. OCI has no dimension catalog and no per-dimension rate card, so Suger applies no rate — "records": {"usage": 10} bills 10 units of the entitlement’s currency.
  2. Usage keys are open. Any key name is accepted and auto-registered on the entitlement the first time it is seen — no dimension configuration in advance. An entitlement may accumulate at most 100 distinct keys.

Endpoints

PurposeEndpointOperation
Report one group (deduplicated by id)POST /org/{orgId}/entitlement/{entitlementId}/usageRecordGroupReportUsageRecordGroup
Report a batch (no dedup key)POST /org/{orgId}/batchCreateUsageRecordGroupsBatchReportUsageRecordGroups
List groups (check status / reported time)GET /org/{orgId}/usageRecordGroupListUsageRecordGroups

Auth: Authorization: Bearer <access_token> — see OAuth App.

Prefer the single-group endpoint with your own id for anything automated: the id is the idempotency key, so a retried request cannot double-report. The batch endpoint carries no dedup key.

Supporting operations (aggregate, validate, retry, delete) are documented in the generic Metering API reference.

Request fields — CreateUsageRecordGroupParams

FieldRequiredTypeNotes
idstring (≤36 chars)Your idempotency key, typically a UUID. Reporting the same id again within 15 days is rejected with a 400 instead of double-billing. Omitted → Suger generates one (and you lose dedup protection).
entitlementIDstringThe Suger entitlement to bill. Must belong to the org, partner ORACLE. In the single-group endpoint this comes from the URL path instead.
recordsmap<string, number>The data. Key → monetary amount (see dictionary below).
timestampRFC-3339 date-timeWhen the usage was generated (not when it is reported). Defaults to the report time.
billableRecordsMeteringUsageRecord[]Not supported for Oracle. This is the Metering API v2 field; Oracle reports v1 records only. A group reported with billableRecords instead of records is accepted at ingestion but skipped by the hourly OCI submission — the usage is never billed. Always use records.
metaInfoobjectRead-only. Populated by Suger (origin records, source, invoice linkages). Sending it has no effect.
usageAllocationsmapAWS-only feature; ignored for Oracle.

records — the field data dictionary

records is a flat map of usage key → amount:

"records": {
  "usage": 12.5,
  "api-calls": 3.99
}
AspectRule
Key (map key)Any name you choose — Oracle usage keys are open. The key is auto-registered on the entitlement on first use and becomes the OCI usageDimensionName. Use stable, human-readable names (usage, api-calls, gb-processed).
Key capAt most 100 distinct keys per entitlement, matching OCI’s per-submission record cap. The 101st new key is rejected at ingestion with a usage dimensions … exceeding the 100 cap error.
Value (map value)The monetary amount to bill, in the entitlement’s currency — not a consumption quantity. Decimals 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.
Zero valuesSkipped — OCI rejects zero-amount records. A group whose values are all zero is rejected at ingestion (400: all the quantity of usage records are zero).
Negative valuesRejected. Usage can only add charges; corrections go through Oracle support.
Commit interactionNone. Amounts are forwarded as-is; no commit/credit/included-usage deduction is applied.

Response fields — MeteringUsageRecordGroup

FieldTypeNotes
idstringThe group’s ID (yours, or generated). Used for retry/delete and as the dedup key.
organizationID / entitlementID / buyerIDstringOwnership. buyerID is resolved from the entitlement.
partnerstringORACLE.
recordsmapThe records as stored (after any dimension mapping; for Oracle open keys this equals what you sent).
statusstringLifecycle state — see below.
creationTime / lastUpdateTimedate-timeBookkeeping.
usageRecordReportIDstringSet once the hourly job folds the group into an OCI submission — joins to GET /org/{orgId}/usageRecordReport.
reportedTimedate-time | nullWhen the group was reported to OCI. null until then.
metaInfo.originRecordsmapThe records exactly as you reported them, before any conversion.
metaInfo.timestampdate-timeThe usage-generation timestamp you supplied.
metaInfo.sourcestringAPI for groups created this way.

Status lifecycle

StatusMeaning
CREATEDAccepted and queued; the hourly job will pick it up.
REPORTEDFolded into an OCI submission; usageRecordReportID and reportedTime are set.
REPORT_FAILEDThe OCI submission failed. Inspect, then retry (moves it back to CREATED).
INVALIDRejected by validation after creation.
DELETEDHard-deleted via the delete endpoint.

What Suger submits to OCI

Each key/amount pair becomes one record in OCI’s submitUsageRecords call (at most 100 records per call, all-or-nothing):

OCI fieldSourced from
idDerived deterministically from the group ID + key, so an automatic retry is idempotent.
marketplaceOfferIdThe entitlement’s Oracle private-offer OCID.
usageDimensionNameThe records map key (the literal usage when no specific dimension applies).
amountThe records map value, at full precision.
currencyCodeThe entitlement’s currency.
timeUsageStarted / timeUsageEndedThe aggregation window of the hourly report run.

Example

Report one group, idempotent by id:

curl -L -X POST 'https://api.suger.cloud/org/YOUR_ORG_ID/entitlement/YOUR_ENTITLEMENT_ID/usageRecordGroup' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
  -H 'Content-Type: application/json' \
  --data-raw '{
    "id": "2f9c1e58-9a1b-4c7e-b1d2-8f3a5c6d7e90",
    "records": {
      "usage": 12.5,
      "api-calls": 3.99
    },
    "timestamp": "2026-08-05T00:00:00Z"
  }'

Response (trimmed):

{
  "id": "2f9c1e58-9a1b-4c7e-b1d2-8f3a5c6d7e90",
  "organizationID": "YOUR_ORG_ID",
  "partner": "ORACLE",
  "entitlementID": "YOUR_ENTITLEMENT_ID",
  "buyerID": "gHYis9RKU",
  "records": { "usage": 12.5, "api-calls": 3.99 },
  "status": "CREATED",
  "metaInfo": {
    "originRecords": { "usage": 12.5, "api-calls": 3.99 },
    "timestamp": "2026-08-05T00:00:00Z",
    "source": "API"
  }
}

Report a batch — the body is an array; each entry needs entitlementID + records (the response is the array of created groups, one per entry, with generated ids):

curl -L -X POST 'https://api.suger.cloud/org/YOUR_ORG_ID/batchCreateUsageRecordGroups' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
  -H 'Content-Type: application/json' \
  --data-raw '[
    {
      "entitlementID": "YOUR_ENTITLEMENT_ID",
      "records": { "usage": 0.75 },
      "timestamp": "2026-08-05T00:00:00Z"
    },
    {
      "entitlementID": "ANOTHER_ENTITLEMENT_ID",
      "records": { "api-calls": 4.2 }
    }
  ]'

Since batch entries carry no caller-supplied id, a retried batch request re-creates the groups — use the single-group endpoint when you need idempotency.

Errors

ResponseCause / fix
400: the record id … has already been reported in the last 15 daysA group with the same id was reported within the 15-day dedup window — this is the dedup working. Do not resend with a new id unless the usage is genuinely new.
400: all the quantity of usage records are zeroEvery value in records is 0. Zero-amount records are never billable; skip the report instead.
400: … usage dimensions, exceeding the 100 cap …The report would push the entitlement past 100 distinct usage keys. Reuse existing keys, or prune the entitlement’s registered dimensions.
400 naming the entitlementThe entitlement doesn’t exist, isn’t in this org, or isn’t in a reportable state.