Create a Private Offer via API
Overview
Create an Oracle Cloud Marketplace private offer programmatically with the Suger
CreateOffer endpoint. Suger creates the offer in OCI, attaches the
contract document, and sends it to the buyer — the same flow the console runs, driven from your own
system.
The call is asynchronous. Suger validates the request, persists a DRAFT offer, returns it
immediately, and then works with OCI in the background. The offer’s real status arrives through the
hourly marketplace sync; poll the offer to follow it.
Prerequisites
- An Oracle Marketplace integration connected at the organization level.
- The product synced into Suger from your OCI listing — Suger resolves the listing OCID from the product’s external ID, so a product created by hand will not work. See List a Product.
- The buyer’s tenancy OCID, or an existing Suger buyer record whose partner is
ORACLE. - A contract document (EULA) reachable over
https, or already uploaded to Suger. - An access token — see OAuth App.
Endpoint
POST https://api.suger.cloud/org/{orgId}/offer
| Operation ID | CreateOffer |
| Auth | Authorization: Bearer <access_token> |
| Body | A WorkloadOffer object |
| Success | 200 with the created WorkloadOffer |
Request fields
Top level
| Field | Required | Notes |
|---|---|---|
partner | ✅ | ORACLE |
service | ✅ | MARKETPLACE |
offerType | ✅ | PRIVATE. Oracle supports no other type — CPPO_OUT and channel offers are rejected. |
productID | ✅ | Suger product ID. Must be an Oracle-synced product carrying the listing OCID. |
name | ✅ | Becomes the offer’s displayName in OCI. Oracle rejects an empty name. |
buyerID | ⬜ | A Suger buyer to link. Required only if you omit info.oracleOffer.buyerTenancyOCID; the buyer must belong to partner ORACLE. |
info
| Field | Required | Notes |
|---|---|---|
info.eulaUrl | ✅ | The contract document. Either an https URL that Suger fetches server-side, or the key of a file you uploaded to Suger. Plain http is rejected. Must resolve to a PDF of at most 1MB (Oracle’s per-attachment limit). |
info.additionalEulaUrls | ⬜ | Further contract documents, same format and limits as info.eulaUrl. Each becomes its own attachment on the OCI offer (unlike AWS, where additional EULAs are merged into one document). |
info.currency | ⬜ | ISO-4217 code. Defaults to USD. |
info.commits | ⬜ | The offer’s line items. Their total becomes the offer’s totalAmount — see Pricing below. |
info.oracleOffer
Oracle-specific fields, an OracleMarketplaceOffer object.
| Field | Required | Notes |
|---|---|---|
sellerPrimaryContact | ✅ | Must include email. Oracle fails the send with SELLER_INFORMATION_IS_NULL without it. |
buyerPrimaryContact | ✅ | Must include email. Oracle rejects the send without a buyer contact. |
buyerTenancyOCID | ✅* | The buyer’s OCI tenancy OCID. *Required unless you set buyerID to a linked Oracle buyer; when both are present, this field wins. |
buyerCompanyName | ⬜ | Buyer’s company name. |
description | ⬜ | Offer description shown in OCI. |
duration | ⬜ | ISO-8601 contract duration after the start date. Defaults to P1Y (one year). |
timeStartDate | ⬜ | When the accepted offer becomes active. Defaults to tomorrow. |
timeAcceptBy | ⬜ | Deadline for the buyer to accept. Defaults to 30 days out. |
Contact objects take firstName, lastName, and email.
Pricing
Oracle offers are sent to OCI with a single ONE_TIME billing cycle and one total amount. Suger
computes that total from info.commits:
totalAmount = round( Σ (commit.rate × commit.quantity) )
- A commit with no
quantitycounts as1. - The sum is rounded to the nearest whole unit of currency, never truncated.
- Omit
info.commitsentirely and the offer is created with a total of0.
Example
The default shape below carries no info.commits, so the offer is sent with a $0 total —
the usage-only pattern, where consumption is billed separately via
Usage Metering. To carry a contract amount instead, add
commit lines (see Pricing):
"commits": [{ "name": "Platform subscription", "rate": 50000, "quantity": 1 }]
curl -L -X POST 'https://api.suger.cloud/org/YOUR_ORG_ID/offer' \
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
--data-raw '{
"partner": "ORACLE",
"service": "MARKETPLACE",
"offerType": "PRIVATE",
"productID": "KVvfb0Vhv",
"name": "Acme Corp - Annual Contract 2026",
"info": {
"currency": "USD",
"eulaUrl": "https://acme.example.com/legal/eula-2026.pdf",
"additionalEulaUrls": [
"https://acme.example.com/legal/annex-a-2026.pdf"
],
"oracleOffer": {
"description": "Annual platform subscription for Acme Corp.",
"duration": "P1Y",
"buyerTenancyOCID": "ocid1.tenancy.oc1..aaaaaaaaexamplebuyertenancy",
"buyerCompanyName": "Acme Corp",
"buyerPrimaryContact": {
"firstName": "Ada",
"lastName": "Lovelace",
"email": "ada@acme.example.com"
},
"sellerPrimaryContact": {
"firstName": "Grace",
"lastName": "Hopper",
"email": "grace@yourcompany.com"
}
}
}
}'
The response is the persisted offer. Note status — it is the Suger record, not yet the OCI state:
{
"id": "FIwCbefqu",
"organizationID": "YOUR_ORG_ID",
"partner": "ORACLE",
"service": "MARKETPLACE",
"offerType": "PRIVATE",
"productID": "KVvfb0Vhv",
"buyerID": "gHYis9RKU",
"name": "Acme Corp - Annual Contract 2026",
"status": "DRAFT",
"info": {
"currency": "USD",
"visibility": "PRIVATE",
"deliveryMethod": "PRIVATE"
}
}
Keep the returned id. It is the Suger offer ID used for every follow-up call, and it doubles as the
idempotency token for the OCI create — a retried submission will not produce a duplicate
buyer-visible offer.
Track the offer
curl -L -X GET 'https://api.suger.cloud/org/YOUR_ORG_ID/offer/FIwCbefqu' \
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN'
Once OCI has the offer, info.oracleOffer.offerID holds the private-offer OCID and
info.oracleOffer.offerStatus holds Oracle’s raw status. Suger maps that raw status onto its own:
Oracle offerStatus | Suger status |
|---|---|
DRAFT | DRAFT |
PENDING_MARKETPLACE | PENDING_MARKETPLACE_APPROVAL |
PENDING_BUYER | PENDING_ACCEPTANCE |
ACCEPTED | ACCEPTED |
ACTIVE | ACTIVE |
ENDED, EXPIRED | EXPIRED |
FAILED_SEND, FAILED_ACCEPT | CREATE_FAILED |
When the offer reaches ACTIVE, Suger derives an entitlement for the buyer. Buyers are deduped by
tenancy OCID, so repeat deals with the same customer attach to the same buyer record.
Withdraw an offer
curl -L -X POST 'https://api.suger.cloud/org/YOUR_ORG_ID/offer/FIwCbefqu/cancel' \
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN'
Oracle allows withdrawing any offer the buyer has not yet accepted, so this is valid while the offer is
PENDING_ACCEPTANCE or PENDING_MARKETPLACE_APPROVAL. Once accepted, it can no longer be withdrawn.
Validation errors
These are returned as 400 before anything is created in OCI, so a rejected request never leaves an
orphaned draft in your marketplace account.
| Message | Fix |
|---|---|
invalid offer type ... to create private offer in Oracle Marketplace | Set offerType to PRIVATE. |
offer name is required | Set name. |
info.eulaUrl is required | Provide a contract document. |
info.eulaUrl ... must be an https URL | Use https, not http. |
info.oracleOffer.sellerPrimaryContact (with email) is required | Add the seller contact with an email. |
info.oracleOffer.buyerPrimaryContact (with email) is required | Add the buyer contact with an email. |
buyer tenancy OCID is required ... | Set info.oracleOffer.buyerTenancyOCID, or link an Oracle buyer via buyerID. |
Two further checks need OCI context and therefore surface after the API has returned, as a
CREATE_FAILED offer rather than a 400:
- The product must resolve to an Oracle listing OCID.
- A linked
buyerIDmust belong to partnerORACLE; a buyer imported from another marketplace is refused.