Orishare
Concepts

Programs

Currencies and the ledger, tiers, rewards, challenges, segments and historical counters.

Currencies and the ledger

Every award is a ledger entry in integer minor units. Entries are lots with a remaining balance; spends and expiries consume lots oldest-expiry first. Pending awards (confirm_after) count in pending until the confirmation job moves them to available. Manual adjustments are POST /ledger_entries with a reason; negative adjustments spend FIFO and respect the currency's negative_balance policy.

Tier programs

{ name, currency, basis, levels[], downgrade_check }. basis is lifetime_earned, earned_rolling_days or balance; levels are ascending thresholds starting at 0. Rules upgrade customers with tier.evaluate; the downgrade job re-evaluates at each local day or month boundary; operators can set a level directly (audited). Removing a level customers hold needs reassign_to; changing the basis needs reevaluate: true.

Rewards

{ name, cost, currency, availability, expiry_after }. Rules issue them; customers redeem an issuance (POST /reward_issuances/{id}/redeem), which spends the cost in the same transaction and fails with insufficient_balance otherwise. Cancelling refunds the cost by a reversal entry and releases availability; expiry does not refund.

Challenges

{ qualifying: { event, conditions? }, target, period, contribution_key?, enrollment, repeatable, completion_actions[] }. Each qualifying event contributes once per contribution_key value; reaching target completes the period exactly once and applies the completion actions in the same transaction. Explicit enrollment gates progress; revoke and reevaluate are audited operator actions.

Segments

Static segments have explicit members; dynamic segments are a condition over customer.attributes.* evaluated live at rule time. Campaign audiences and rule conditions reference segments by name, so a referenced segment cannot be renamed or deleted.

Historical counters

{ name, event, window, filter? } counts events per customer and window and is read as customer.counters.<name>. A definition registered after events exist starts backfilling; rules that read it skip with counter_not_ready until POST /counter_definitions/{id}/backfill (inline for small histories, a job otherwise) marks it ready.

On this page