Skip to main content

Overview

Podium includes a programmable points ledger. Points are earned through purchases, campaign participation, API grants, and reward interactions. They can be spent on order discounts, reward redemption, and token presales. Points are scoped to your organization and optionally to a specific creator within it. This lets brands offer creator-specific loyalty programs while maintaining a unified points balance.

Earning Points

Via API (Agent/Programmatic)

Grant or deduct points directly. This is the primary method for companion agents and backend automations.
curl -X POST https://api.podium.build/api/v1/user/clxyz1234567890/points \
  -H "Authorization: Bearer $PODIUM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 100,
    "creatorId": "clcreator_abc",
    "details": {
      "source": "beauty-companion",
      "action": "survey-completed",
      "campaignId": "clcamp_xyz"
    }
  }'
FieldTypeRequiredDescription
amountintegerYesNon-zero integer. Positive = earn, negative = deduct
creatorIdstringNoScope to a specific creator
detailsobjectNoArbitrary metadata stored with the transaction
The details object is stored verbatim with the PointTransaction record for audit and analytics. A points-received event is published on successful grants.

Via Purchase

When a product has pointEligible: true, purchases automatically earn points based on the creator’s pointsPerDollar configuration. The earning happens as part of the purchase-processed event handler.

Via Campaign Completion

Campaign rewards are configured per-campaign via the CampaignReward model (see Campaigns). Points are awarded automatically when a user completes their CampaignJourney — after voting, submitting a survey, or completing UGC.

Transaction Types

TypeDirectionSource
APIEarn or SpendProgrammatic grants/deductions via the API
CAMPAIGNEarnCampaign participation rewards
PURCHASEEarnPurchase rewards (based on creator’s pointsPerDollar)
NFT_REDEMPTIONSpendRedeeming on-chain rewards
PRESALESpendToken presale purchases

Spending Points at Checkout

Points can be applied as a discount during the checkout flow using a two-phase commit pattern that prevents points from being spent on failed orders.

Step 1: Apply Points During Checkout

curl -X POST https://api.podium.build/api/v1/user/clxyz1234567890/order/clord_xyz/checkout \
  -H "Authorization: Bearer $PODIUM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "points": 500 }'
This reserves 500 points against the order and reduces the payment amount accordingly. The points value is deducted from the order total before creating the PaymentIntent.

Step 2a: Finalize (Payment Succeeded)

curl -X PUT https://api.podium.build/api/v1/user/clxyz1234567890/order/clord_xyz/points/finalize \
  -H "Authorization: Bearer $PODIUM_API_KEY"
Commits the point reservation. After this call, the points are permanently deducted and cannot be reverted.

Step 2b: Revert (Payment Failed)

curl -X POST https://api.podium.build/api/v1/user/clxyz1234567890/order/clord_xyz/points/revert \
  -H "Authorization: Bearer $PODIUM_API_KEY"
Deletes the PURCHASE point transactions for the order and returns the points to the user’s balance. This only works on orders in OPEN status.
Always finalize or revert points after payment completes. Leaving points in a reserved state causes balance inconsistencies.

Get Points Balance

curl https://api.podium.build/api/v1/user/clxyz1234567890/points \
  -H "Authorization: Bearer $PODIUM_API_KEY"
{
  "balance": 2500,
  "creatorBalances": [
    { "creatorId": "clcreator_abc", "balance": 1500 },
    { "creatorId": "clcreator_def", "balance": 1000 }
  ]
}
Optionally scope to a single creator: ?creatorId=clcreator_abc.

Points Transaction History

curl "https://api.podium.build/api/v1/user/clxyz1234567890/points/history?page=1&limit=20" \
  -H "Authorization: Bearer $PODIUM_API_KEY"

Query Parameters

ParamTypeDescription
pageintegerPage number (1-indexed)
limitintegerItems per page
creatorIdstringFilter to a specific creator

Response

{
  "data": [
    {
      "id": 1234,
      "userId": "clxyz1234567890",
      "amount": 100,
      "type": "API",
      "creatorId": "clcreator_abc",
      "createdAt": "2026-03-07T12:00:00.000Z",
      "details": {
        "source": "beauty-companion",
        "action": "survey-completed"
      }
    },
    {
      "id": 1235,
      "userId": "clxyz1234567890",
      "amount": -500,
      "type": "PURCHASE",
      "creatorId": null,
      "createdAt": "2026-03-07T14:30:00.000Z",
      "orderId": "clord_xyz"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 20,
    "total": 47
  }
}

PointTransaction Model

FieldTypeDescription
idintegerAuto-increment ID
userIdstringUser CUID
amountintegerPoints amount (positive = earn, negative = spend)
typeenumAPI, CAMPAIGN, PURCHASE, NFT_REDEMPTION, PRESALE
creatorIdstring | nullCreator scope (null = org-wide)
createdAtdatetimeTransaction timestamp
organizationIdstringParent organization

Linked Transaction Records

Each PointTransaction may have one linked detail record depending on the source:
Linked ModelTransaction TypeContains
ApiPointTransactionAPIdetails metadata object
CampaignRewardTransactionCAMPAIGNjourneyId, campaign reference
UserOrderTransactionPURCHASEorderId, order reference
NftRedemptionTransactionNFT_REDEMPTIONreward reference
PresaleRewardTransactionPRESALEpresale reference

Endpoint Summary

MethodPathDescription
GET/user/{id}/pointsGet balance (optional ?creatorId=)
POST/user/{id}/pointsGrant/deduct points
GET/user/{id}/points/historyTransaction history (paginated)
POST/user/{id}/order/{orderId}/checkoutApply points at checkout
PUT/user/{id}/order/{orderId}/points/finalizeCommit point spend
POST/user/{id}/order/{orderId}/points/revertRevert point spend