Contract Flow¶
A marketplace contract is the record of what a channel said, mirrored into Omnistrate, plus the fulfillment run that acts on it. This page covers what happens between a purchase and a served buyer, and how to read it when something stalls.
Fulfillment States¶
fulfillmentState is what Omnistrate decided, and it is the only thing that governs whether the buyer can deploy and be metered.
| State | Meaning | Buyer can deploy |
|---|---|---|
DISCOVERED | The purchase reached Omnistrate. Nothing exists on our side yet | No |
IDENTIFIED | Organization and root user created. The buyer has an Omnistrate identity | No |
AWAITING_ISV | Subscription request is PENDING. We are waiting on you | No |
READY | You confirmed. The request was approved and the subscription created | Yes |
SUSPENDED | The marketplace suspended the contract, usually non-payment | No |
DEPROVISIONING | A cancellation is being torn down | No |
CLOSED | Cancellation complete | No |
Branch on fulfillmentState, never on contractStatus
contractStatus is what the marketplace says, and it is normally ACTIVE from the instant of purchase. A contract at ACTIVE / AWAITING_ISV is a buyer who is paying and cannot yet be served. Reading contractStatus to decide whether to serve someone will serve them too early.
Fulfillment stages¶
The state is a summary. The stages are what actually ran, each stamped with when it started, when it ended and how long it took — recorded by the workflow rather than reconstructed for display.
| Stage | What happened | Parameters shown |
|---|---|---|
| Contract received | The arrival was resolved against the channel | Channel, external reference |
| Customer identified | The buyer became an organization and a root user | Buyer reference, buyer name |
| Contract held | The channel was asked to keep the buyer un-charged, where it can | Channel, whether it can hold |
| Subscription request created | A PENDING request against the mapped plan | Organization, plan, quantity |
| Handed off to ISV | You were told, and the SLA timer armed | Organization, root user email, handoff SLA |
| ISV confirmed | Your confirm arrived and the request was approved | Plan, quantity |
| Contract committed | The channel was told to begin charging | External reference, whether it can hold |
| Ready | The subscription exists. Deployments and metering are open | Subscription, organization |
| Closed | The contract ended | Contract state |
Contract held is a no-op on Suger, which cannot hold a contract — the buyer is already being charged by the marketplace before Omnistrate is called. The stage still appears, and says so, because "we did not do this and here is why" is more useful than a gap.
The handoff stage is the one that waits¶
Handed off to ISV stays In progress for as long as the contract sits in AWAITING_ISV. That is not a stall — the handoff is not complete when we have handed it over, it is complete when you answer.
Its parameters tell you how the buyer reached you and how long you have:
- Delivered by — either a signed webhook to your receiver, or the buyer's browser, on your callback URL. This is decided by whether a receiver is registered on the channel, not by the particular run.
- Handoff SLA — how long before the contract is flagged and
fulfillment.failedis emitted. - What the ISV has done so far — whether any inbound call has arrived for this contract. If nothing has, start with the receiver rather than with their onboarding.
Reading a contract when something is wrong¶
The contract screen carries four tabs, and they answer different questions.
Overview — what this stage did, with its timings.
Events — what Omnistrate emitted at this stage.
Contract payload — what the channel said, verbatim. This is the answer to "did the marketplace really tell us that".
Contract interactions — both directions of the integration in one ordered stream: the events we sent you and the calls you made back.
The interleaving is usually the diagnosis. "We sent contract.discovered at 09:04, they redeemed the handoff at 09:06 and never confirmed" is one sequence, and splitting it across two screens would make the support answer a manual merge of two lists.
Each outbound row carries the exact request bytes and the signature header that went with them, so when an ISV says a signature does not verify, you compare their digest against the one actually sent rather than against a recomputed copy.
The contracts list¶
FinOps Center → Marketplace Contracts shows every contract with the channel's state and Omnistrate's state as separate columns, because they answer different questions and a single merged column would hide exactly the case that matters.
The strip along the top groups contracts into quadrants. The one to watch is paying and not provisioned: a buyer the marketplace is charging whom nobody has confirmed. Simulated contracts are excluded from those totals by construction, so a rehearsal cannot turn the incident tile red.
When nobody confirms¶
If the handoff SLA passes with no confirm, the contract is flagged for an operator and fulfillment.failed is emitted to a registered receiver. The contract stays in AWAITING_ISV — it is not closed, and the buyer is not refunded — because the usual remedy is that the ISV confirms late.
fulfillment.failed does not carry a handoff token. The token only ever rides on contract.discovered. It outlives the SLA, so if you still hold it you can redeem and confirm afterwards.
Retry fulfillment on the contract re-enters the run and re-emits the handoff, which is the remedy when the first delivery never arrived.



