A reward template defines what can be issued — points plus optional content
(a badge, certificate, coupon, or attachment). You issue it by redeeming it to
a recipient, either directly or automatically via a trigger. All paths are
under https://api.davi.social/api/v1; org actions use an
org-scoped token.
1. Create a reward template
curl -X POST "https://api.davi.social/api/v1/organizations/ORG_SLUG/rewards" \
-H "Authorization: Bearer ORG_SCOPED_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Check-in Badge",
"points": 100,
"supply_total": null,
"content_config": { "storage_type": "platform" }
}'
Fields: name, points (required), optional description, category,
activity_uuid (link to an event), and supply_total (null = unlimited). The
content_config.storage_type controls how content is produced:
platform— Davi renders the content fromcontent_template.external— your webhook generates it (external_webhook_uuid); redemptions are asynchronous.dynamic— reserved for per-recipient generation. Variable interpolation is being reworked and isn't currently dependable — preferplatformorexternal.
Templates start as drafts. Move one through its lifecycle by PATCHing its
status — published makes a draft live, draft returns it to draft (only while
it has no redemptions), and archived withdraws it:
curl -X PATCH "https://api.davi.social/api/v1/rewards/REWARD_SLUG" \
-H "Authorization: Bearer ORG_SCOPED_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "status": "published" }'
Scopes: reward:create to create, reward:manage to update / publish.
2. Redeem a reward
Issue the reward to a recipient with POST /rewards/{reward_slug}/redeem
(scope reward:redeem):
curl -X POST "https://api.davi.social/api/v1/rewards/REWARD_SLUG/redeem" \
-H "Authorization: Bearer ORG_SCOPED_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"identifier": { "type": "username", "value": "ada" },
"scope": "single-use",
"idempotency_key": "unique-per-redemption"
}'
Recipients
The identifier is an IdentifierRef — { "type": …, "value": … } where
type is one of card, wallet, username, user_id, or link. This resolves
even to a custodial wallet for someone without a Davi account yet.
Sync vs. async results
- Completed (platform/dynamic):
{ "status": "completed", "transaction_id": … }. - Pending (external):
{ "status": "pending", "delivery_uuid": … }— pollGET /rewards/deliveries/{delivery_uuid}until it reportscompleted(with atransaction_id) orfailed.
The recipient reads the issued content via
GET /rewards/transactions/{transaction_id}.
3. Automate with triggers
Instead of redeeming by hand, a reward trigger issues a template automatically
when a matching event occurs. Create one with
POST /organizations/{organization_slug}/reward-triggers (scope reward:manage):
curl -X POST \
"https://api.davi.social/api/v1/organizations/ORG_SLUG/reward-triggers" \
-H "Authorization: Bearer ORG_SCOPED_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Reward 5 check-ins",
"reward_template_uuid": "REWARD_UUID",
"trigger_scopes": ["activity.checked_in:count:5"],
"deduplication_window_seconds": 300
}'
trigger_scopesare patterns describing the condition, e.g.activity.checked_in:count:5(the 5th check-in) oractivity.registered:first. These are unrelated to OAuth scopes.deduplication_window_secondsprevents the same trigger from firing twice for a user within the window (default300;nullto disable).
When an activity check-in matches, Davi issues the reward to that user automatically.
Next
- Activities & check-ins — the events that fire triggers.
- Webhooks — get notified on
reward.redeemed.