Integration · Revenue operations
How to build subscription and entitlement provisioning
A customer signs on Friday and waits until Wednesday for the seats they bought. Here is how provisioning that keeps up actually works, the prompts that build it, and what running it demands.
Built with Tray Headless
- System Salesforce
- Step Derive entitlement
- Step Provision on start date
- Step Reconcile nightly
- System Product
Entitlement is derived from the contract rather than set by hand, and a nightly reconciliation catches any drift between what was sold and what is live.
The short answer
What is subscription and entitlement provisioning?
Subscription provisioning is four parts: entitlement derived from the contract instead of typed by somebody, activation on the contract start date instead of at signature, mid-term changes treated as amendments to the same subscription, and a reconciliation that catches drift between what was sold and what is live. Where this usually goes wrong is drift. Entitlement edited directly in the product to unblock somebody is invisible to billing, and the customer keeps that access for years.
What matters here
- Derive entitlement from the contract. A number typed into the product by a support agent is a number nobody will ever reconcile.
- Activate on the contract start date, not at signature. Those differ and billing follows the contract.
- Handle mid-term changes as amendments to the same subscription, never as a second one.
- Reconcile nightly. Entitlement edited in the product to unblock somebody is revenue leaking silently.
- Never downgrade automatically on non-payment without a human. Suspension is a commercial decision.
Who this is for
You run revenue operations or product operations at a subscription company. Contracts are signed and access is granted by hand, and nobody is quite sure the two still agree.
How it works in practice
Everything that sits between a contract being signed and a customer having what they bought.
- 1
Entitlement is derived from the closed contract
Products, seats, limits and term, computed rather than typed.
- 2
Provisioning is scheduled for the contract start date
Which is often not the signature date, and billing follows the contract.
- 3
Admin access goes to the named contact
With an invitation, so somebody can actually get in on day one.
- 4
Mid-term changes amend the same subscription
Co-terminated, prorated, and never a second subscription for one customer.
- 5
A nightly reconciliation compares sold against live
Any difference is drift, and drift in either direction is a problem.
- 6
Expiry warns, not cuts
Renewal in progress means access continues; a decision to suspend is made by a person.
What provisioning is made of
Four, and the last is where the money quietly leaks.
Derived entitlement
Seats, features and limits computed from the contract line items. A typed number is one nobody can reconcile later.
Start-date activation
Scheduled to the contract start instead of fired at signature, because billing follows the contract and access should too.
Amendments in place
Seat and plan changes applied to the live subscription, prorated to the existing term end, so the product never holds two entitlements for one customer.
Drift reconciliation
A nightly comparison of entitlement against what the product actually grants. Manual edits are invisible until you look.
The Tray Headless prompts
Paste these into Claude Code or Codex with the Tray Headless plugin installed. Each stage runs on its own. The systems named in them are the worked example rather than a requirement, and every prompt says so.
Once per project, run
/tray-workflows:set-workspace
to pick the workspace these build in. Point it at a sandbox first.
- 1
Start here: map contract lines to entitlement
Everything downstream is this mapping.
Headless skills
build-workflowUse build-workflow. The systems in play are Salesforce and our product's admin API, or whatever we run in those seats. I need contract line items with products, quantities and term dates, and from the product the entitlement model: plans, seats, feature flags and usage limits. Then build the mapping from product code to entitlement as a table finance and product both understand. Every SKU we sell has to resolve to a concrete entitlement, and any SKU that does not is a sale nobody can fulfil.
- 2
Derive entitlement, and activate on the start date
Signature date and start date are different, and billing follows one of them.
Headless skills
build-workflowtray-patternsUse build-workflow. On closed won, derive the entitlement from the contract lines: plan, seat count, feature flags, usage limits, term start and end. Schedule activation for the contract start date rather than firing at signature. Those are frequently weeks apart, billing follows the contract, and granting access early gives away product you have not billed for. Provision the admin user from the named technical contact and send them an invitation. A subscription that is live but which nobody can log into is not provisioned, and it generates a support ticket on day one. Write the subscription id back to the opportunity so the two are linked permanently.
- 3
Treat mid-term changes as amendments
A second subscription for one customer breaks the renewal figure.
Handle changes against the existing subscription, never by creating a new one: Seat increase: apply immediately, prorate to the existing term end Seat decrease: apply at renewal unless the contract allows otherwise, and never silently remove a named user Plan upgrade: apply immediately with proration Plan downgrade: apply at renewal, and flag for revenue recognition Term extension: co-terminate everything to the new end date Every amendment links to the parent contract. A mid-term upgrade filed as a new subscription produces two records for one customer, and the renewal number is wrong from that point onward.
- 4
Reconcile nightly, in both directions
Manual edits in the product are invisible until you look.
Headless skills
tray-gotchastray-patternsUse tray-gotchas, then reconcile nightly between contract and product: Seats provisioned above what was sold, which is revenue leaking Seats below what was sold, which is a customer not getting what they paid for Features enabled with no contract line behind them Active subscriptions with no contract at all Contracts past their end date with access still live Report both directions. The over-provisioned list is usually longer and it is almost always somebody enabling something to unblock a customer, which is the right instinct and the wrong permanent state. Do not correct automatically. Report it and let a person decide, because removing access a customer is actively using is a conversation.
- 5
Warn at expiry, never cut automatically
Suspension is a commercial decision, not a scheduled job.
At term end, warn instead of cut: 30 days out, tell the account owner and customer success On the end date, if a renewal is in progress, continue access and flag it. Cutting off a customer mid-renewal loses the renewal. If there is no renewal and no engagement, suspend instead of delete, and require a person to confirm. Never automatically downgrade or suspend on non-payment. Route it to credit control and the account owner, and let a human decide. Then report: time from signature to working access, provisioning failures, drift in both directions, and expiries handled without a decision, which should be zero.
- 6
Check it end to end, then hand the mapping over
Because the catalogue changes and the mapping has to keep up.
Run the per-step schema checks and the whole-workflow audit before this touches production. Then open the same workflow in Tray Build so revenue operations and product can maintain the SKU to entitlement mapping in the visual canvas. A new plan should be sellable and fulfillable the same week.
What it connects to
The contract says what was sold, the product grants it, and billing has to agree with both.
Salesforce
Read the closed contract and its line items, and write the subscription id and provisioning status back.
Reads and writes
NetSuite
Read the billing subscription and term, so entitlement and invoicing agree instead of drifting apart.
Reads
Okta
Provision the internal staff who administer entitlements. Customer identity belongs in the customer identity provider, not in the workforce directory.
Reads and writes
Gmail
Send the welcome and the invitation, because a live subscription nobody can log into is not provisioned.
Writes
Slack
Tell the account team when provisioning completes, and raise drift to whoever can decide about it.
Writes
Same build, other stacks
The design does not change if you run something else in one of these seats. The same prompts build it against Microsoft Dynamics 365, SAP S/4HANA, Google BigQuery, Microsoft Teams, Azure Active Directory or Microsoft Outlook.
Named systems are the ones most teams run, not the only ones that work. Each is an authentication in your Tray workspace, referenced by name, so the workflow never holds a credential. Where we have a connector page, the name links to it.
Running it in production
This grants paid access to your product. Drift in either direction costs money or goodwill.
The platform runs it, not a laptop under a desk
Scheduled activation on future start dates and the nightly reconciliation run on the same engine, whether or not anybody is watching.
Entitlement is always traceable to a contract line
Which line granted which seats and features. That is what makes the drift report actionable, not a list of mysteries.
Credentials live in the workspace, never in the repo
The product admin credential can grant paid access to anybody. It lives in your workspace, scoped and separately rotatable.
Revenue and product own the mapping
SKU to entitlement opens in Tray Build, so a new plan is sellable and fulfillable in the same week it is created.
Nothing is revoked automatically
Drift is reported and expiry is warned. Removing access a customer is using is a commercial conversation, not a scheduled job.
Questions people ask
Why activate on the start date rather than at signature?
Because those are frequently weeks apart and billing follows the contract. Granting access early gives away product you have not billed for, and doing it late generates a support ticket on day one.
Why handle changes as amendments?
Because the product would then grant access twice for one customer, and the older subscription usually keeps its entitlement long after the upgrade replaced it.
What is entitlement drift?
The gap between what was sold and what the product actually grants. It usually comes from somebody enabling a feature to unblock a customer, which is the right instinct and the wrong permanent state.
Should access be cut automatically at term end?
No. Warn at thirty days, continue access if a renewal is in progress, and require a person to confirm any suspension. Cutting a customer off mid-renewal loses the renewal.
Should non-payment trigger a downgrade?
Not automatically. Route it to credit control and the account owner. Suspension is a commercial decision with consequences a scheduled job cannot weigh.
Vibe-coding app guides
Vibe-code an entire app with Helix
This moves the data between systems. It does not give anybody a screen to work in. Build that app in Claude Code, Codex or Cursor, then deploy and run it governed on Tray Helix. Same kind of guide, same kind of prompts.
How to build a renewal tracker (opens helix.tray.ai in a new tab)
Related guides
Revenue operations
How to build an order-to-cash integration
Closed-won to sales order to invoice to cash applied, as a CRM to ERP integration. Idempotent writes, a reconciliation loop, and the Headless prompts that build it.
Revenue operations
How to build a billing to CRM sync
Put invoice and payment state where the account team works, without letting the CRM become a second billing system. The Headless prompts that build it.
Platform engineering
How to build webhook fan-out
Acknowledge before you fan out, verify the signature first, retry per consumer, and make replay possible. The Headless prompts that build it.
Last reviewed September 2026.