The best enterprise credit allocation pattern is simple: treat every client payment as an idempotent order, target the subscriber with `licenseCode`, and confirm delivery using `credit.allocated` webhooks.
This avoids double-crediting and keeps your fulfillment status synchronized even when retries happen.
Recommended API contract
Use this contract for every allocate request from your backend:
- `credits`: integer credits to deliver to the subscriber
- `externalRef`: your internal order ID (must be stable across retries)
- `licenseCode`: use instead of storing subscriber IDs whenever possible
Why `externalRef` matters
Stripe and your own payment flow can trigger retries. By using a stable `externalRef`, SpringOS will reuse the same allocation record instead of incrementing credits twice.
This is the main guardrail against over-crediting due to duplicate webhooks.
Webhook fulfillment loop
When SpringOS completes delivery, it emits `credit.allocated` for your enterprise account.
Use the webhook payload (including allocation ID / subscriber reference) to mark the order fulfilled and notify your customer.
Operational edge cases
If a license is not active or a subscriber cannot be resolved, the allocate request should fail and you should not mark the order fulfilled.
If auto top-up triggers and cannot charge (for example missing payment method), subscribe to `credit.pool.low` so you can correct the setup before the pool runs dry.