Skip to main content

Overview

Campaigns capture structured user intent through interactive mechanics. They generate first-party preference signals (USER_DECLARED) that feed into the agentic product feed’s intent scoring. Campaigns belong to a creator within your organization and follow a defined lifecycle from draft to completion.

Campaign Types

TypeMechanicIntent Signal
SWIPEBinary preference (like/dislike on product images)Product preference direction
MULTIVARIANTVote between attribute options (e.g., “Which shade?”)Attribute value preference
SURVEYStructured question-and-answerExplicit preference declarations
UGCUser-generated content submissionContent creation + implicit preference

Create a Campaign

curl -X POST https://api.podium.build/api/v1/campaign \
  -H "Authorization: Bearer $PODIUM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "creatorId": "clcreator_abc",
    "type": "MULTIVARIANT"
  }'
FieldTypeRequiredDescription
creatorIdstringYesCUID of the owning creator
typeenumYesSWIPE, MULTIVARIANT, SURVEY, or UGC
This creates a campaign in DRAFT status. Configure it with a PUT before publishing.

Configure a Draft Campaign

Use PUT /campaign/{id} to set up the campaign content, timing, and reward structure:
curl -X PUT https://api.podium.build/api/v1/campaign/clcamp_xyz \
  -H "Authorization: Bearer $PODIUM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Which shade is your vibe?",
    "description": "Vote on your favorite lip shade and earn 50 points!",
    "hero": [{ "url": "https://cdn.example.com/campaign-hero.jpg", "type": "image" }],
    "startDate": "2026-04-01T00:00:00.000Z",
    "endDate": "2026-04-30T23:59:59.000Z",
    "maxParticipants": 5000,
    "showInstructions": true,
    "showLeaderboard": true,
    "rateLimit": 1,
    "reward": {
      "points": 50,
      "maxSupply": 10000
    },
    "attributes": [
      {
        "title": "Lip Shade",
        "hasImages": true,
        "options": [
          { "value": "Berry Bliss" },
          { "value": "Nude Glow" },
          { "value": "Crimson Night" },
          { "value": "Coral Dream" }
        ]
      }
    ]
  }'

Configuration Fields

FieldTypeDescription
titlestringCampaign title
descriptionstringCampaign description
heroMediaAsset[]Hero images/videos
logostringCampaign logo URL
videostringVideo URL
startDatedatetimeWhen campaign goes live
endDatedatetimeWhen campaign closes
maxParticipantsintegerMax participants (null = unlimited)
showInstructionsbooleanShow instruction card
showLeaderboardbooleanShow participation leaderboard
rateLimitintegerMax participations per user (0 = unlimited)
rewardobject{ points, maxSupply } — points per completion
attributesarrayVoting attributes for MULTIVARIANT campaigns
questionsarrayQuestions for SURVEY campaigns

Campaign Lifecycle

StatusDescription
DRAFTBeing configured — editable via PUT
SUBMITTEDAwaiting admin review
APPROVEDApproved, ready to publish
PUBLISHEDLive, accepting participation
ENDEDParticipation closed, analytics available

Submit for Review

curl -X PATCH https://api.podium.build/api/v1/campaign/clcamp_xyz/submit \
  -H "Authorization: Bearer $PODIUM_API_KEY"

Publish

curl -X PATCH https://api.podium.build/api/v1/campaign/clcamp_xyz/publish \
  -H "Authorization: Bearer $PODIUM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "requiresReview": false }'
Set requiresReview: false to skip the SUBMITTED → APPROVED step and publish directly.

Update a Published Campaign

Only a subset of fields can be changed after publishing:
curl -X PATCH https://api.podium.build/api/v1/campaign/clcamp_xyz \
  -H "Authorization: Bearer $PODIUM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Updated Campaign Title",
    "description": "Revised description",
    "hero": [{ "url": "https://cdn.example.com/new-hero.jpg", "type": "image" }],
    "showInstructions": false,
    "showLeaderboard": true
  }'
Editable after publish: title, description, hero, showInstructions, showLeaderboard, status.

Participation

Cast Votes (MULTIVARIANT)

curl -X POST https://api.podium.build/api/v1/campaign/clcamp_xyz/vote \
  -H "Authorization: Bearer $PODIUM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "clxyz1234567890",
    "votes": [
      { "attributeId": 1, "optionId": 3 },
      { "attributeId": 2, "optionId": [1, 4] }
    ]
  }'
FieldTypeRequiredDescription
userIdstringYesParticipating user’s CUID
votesarrayYesArray of vote objects
votes[].attributeIdnumberYesCampaign attribute ID
votes[].optionIdnumber | number[]YesSelected option(s) — single or multi-select
Voting creates a CampaignJourney record linking the user to the campaign and records individual CampaignVote entries. If a reward is configured, points are awarded automatically.

Submit Survey (SURVEY)

curl -X POST https://api.podium.build/api/v1/campaign/clcamp_survey/survey \
  -H "Authorization: Bearer $PODIUM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "clxyz1234567890",
    "responses": [
      { "questionId": 1, "answer": "Hydrating serums" },
      { "questionId": 2, "answer": ["Sensitive", "Dry"] },
      { "questionId": 3, "answer": "I prefer fragrance-free products" }
    ]
  }'
FieldTypeRequiredDescription
userIdstringYesParticipating user’s CUID
responsesarrayYesArray of response objects
responses[].questionIdnumberYesCampaign question ID
responses[].answerstring | string[]YesAnswer — single or multi-choice
Survey responses are stored as CampaignResponse records and feed into the enrichment pipeline as USER_DECLARED preference data.

Get Survey Report

curl https://api.podium.build/api/v1/campaign/clcamp_survey/survey/report \
  -H "Authorization: Bearer $PODIUM_API_KEY"
Returns aggregated response distributions per question.

Configure a Campaign Reward

Link an on-chain reward to a campaign:
curl -X PUT https://api.podium.build/api/v1/campaign/clcamp_xyz/nft \
  -H "Authorization: Bearer $PODIUM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Shade Voter Badge",
    "description": "Awarded for participating in the Lip Shade vote",
    "imageUrl": "https://cdn.example.com/badge.png",
    "points": 100,
    "externalUrl": "https://brand.com/campaign/shade-vote"
  }'
FieldTypeDescription
namestringReward token name
descriptionstringReward description
imageUrlstringStatic image URL
animationUrlstringAnimated media URL
pointsintegerPoints cost to redeem
externalUrlstringExternal link
At least one of imageUrl or animationUrl is required.

Analytics

Campaign Overview

curl https://api.podium.build/api/v1/campaign/clcamp_xyz/analytics \
  -H "Authorization: Bearer $PODIUM_API_KEY"

Available Analytics Endpoints

EndpointReturns
/campaign/{id}/analyticsOverall participation and response metrics
/campaign/{id}/analytics/participantsPaginated participant list
/campaign/{id}/analytics/participants/countTotal participant count
/campaign/{id}/analytics/participants/growthParticipation growth over time
/campaign/{id}/analytics/responsesResponse data breakdown
/campaign/{id}/analytics/responses/growthResponse growth over time
/campaign/{id}/attributesVote distributions per attribute/option

Attribute Vote Distribution

curl https://api.podium.build/api/v1/campaign/clcamp_xyz/attributes \
  -H "Authorization: Bearer $PODIUM_API_KEY"
[
  {
    "id": 1,
    "title": "Lip Shade",
    "options": [
      { "id": 1, "value": "Berry Bliss", "voteCount": 1247 },
      { "id": 2, "value": "Nude Glow", "voteCount": 982 },
      { "id": 3, "value": "Crimson Night", "voteCount": 1534 },
      { "id": 4, "value": "Coral Dream", "voteCount": 887 }
    ]
  }
]

Campaign Model

FieldTypeDescription
idstringCUID2 identifier
typeenumSWIPE, MULTIVARIANT, SURVEY, UGC
statusenumLifecycle status
titlestringCampaign title
descriptionstringCampaign description
startDatedatetimeGo-live timestamp
endDatedatetimeEnd timestamp
maxParticipantsintegerParticipant cap
showInstructionsbooleanShow instruction card
showLeaderboardbooleanShow leaderboard
rateLimitintegerMax participations per user
creatorIdstringOwning creator CUID
publishedAtdatetimeWhen campaign was published
createdAtdatetimeCreation timestamp
ModelPurpose
CampaignAttributeVoting dimensions for MULTIVARIANT (title, hasImages)
CampaignAttributeOptionIndividual vote options within an attribute
CampaignQuestionSurvey questions for SURVEY campaigns
CampaignResponseIndividual survey answers
CampaignJourneyA user’s participation record (links user, campaign, votes/responses)
CampaignVoteIndividual vote on an attribute option
CampaignRewardPoints reward configuration per campaign
CampaignRewardTransactionPoints awarded for campaign completion

Endpoint Summary

MethodPathDescription
POST/campaignCreate campaign
GET/campaign/{id}Get campaign
PUT/campaign/{id}Update draft
PATCH/campaign/{id}Update published
DELETE/campaign/{id}Delete campaign
PATCH/campaign/{id}/submitSubmit for review
PATCH/campaign/{id}/publishPublish
PUT/campaign/{id}/nftConfigure reward
GET/campaign/{id}/attributesAttribute distributions
POST/campaign/{id}/voteCast votes
POST/campaign/{id}/surveySubmit survey
GET/campaign/{id}/survey/reportSurvey report
GET/campaign/{id}/analyticsAnalytics overview
GET/campaign/{id}/analytics/participantsParticipants
GET/campaign/{id}/analytics/participants/countParticipant count
GET/campaign/{id}/analytics/participants/growthGrowth
GET/campaign/{id}/analytics/responsesResponse data
GET/campaign/{id}/analytics/responses/growthResponse growth