This guide builds a membership program end to end: define the tiers, decide what each one grants, enrol people, gate an event and a reward on those grants, and act on renewals. Everything here needs an organization-scoped token.
A membership here is enrolment in one of your organization's tiers
(/organizations/{slug}/memberships). It is separate from staff, a role on
the organization's team such as owner or manager
(/organizations/{slug}/staff), and from a user's subscription, their own
plan with Davi. Someone can hold a paid tier without being staff, or run the
organization without holding a tier.
1. Define the tiers
curl -X POST "https://api.davi.social/api/v1/organizations/ORG_SLUG/membership-tiers" \
-H "Authorization: Bearer ORG_SCOPED_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Gold",
"description": "Priority access and double points",
"price_cents": 999,
"payment_interval": "monthly",
"entitlements": {
"activity.vip_lounge": null,
"reward.points_multiplier": 2
}
}'
name,price_centsandpayment_intervalare required.price_cents: 0makes a free tier.payment_intervalisdaily,weekly,monthly,yearlyorone_time.- Creating and updating tiers takes
org:tiers:manage.
Choose the entitlement keys first
entitlements defines what the program grants. Each key is a capability you
gate on later, and you choose the vocabulary.
- A
nullvalue is a boolean capability: the key's presence is the grant. - A non-null value carries configuration, such as a multiplier.
Name keys for what they unlock, not who gets them. activity.vip_lounge
survives a tier being renamed, split or retired; gold_tier_perk does not.
Gates name a key, never a tier, so to give two tiers the same access you grant
both the same key. Adding a tier later does not mean revisiting any gate.
The reserved member key is implicit. Every active member holds it whatever
their tier. It is stripped if you set it on a tier and never appears in a tier
response. Use it as the gate for "any member, any tier".
2. Enrol people
curl -X POST "https://api.davi.social/api/v1/organizations/ORG_SLUG/memberships" \
-H "Authorization: Bearer ORG_SCOPED_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "user_uuid": "USER_UUID", "membership_tier_slug": "gold" }'
POST .../memberships (scope membership:join) enrols somebody in a tier, named
by slug. To upgrade or downgrade, PATCH the member's membership with a new
tier (membership:tier:update) rather than cancelling and rejoining.
For a negotiated rate or a comped membership, set custom_tier_price_cents and
custom_tier_payment_interval on the membership instead of defining a tier
nobody else will hold. Entitlements still come from the tier: a custom price
changes what somebody pays, never what they can reach.
A membership is active, expired or cancelled. Only active grants
entitlements, so an expired member holds no keys at all, including member.
Claiming a card can enrol somebody. If a card carries a membership tier and its claimant is not already a member, claiming creates the membership. Your program can gain members you never enrolled through this endpoint, so a member count kept in your own records will drift from Davi's.
3. Gate what members reach
Activities, sessions and reward templates each carry one required_entitlement,
with the same rules everywhere:
required_entitlement | Who passes |
|---|---|
null | Everyone |
"member" | Any active member, at any tier |
| any other key | Only members whose tier grants that key |
To make an event members-only, set it on the activity or session:
curl -X PATCH "https://api.davi.social/api/v1/activities/ACTIVITY_SLUG" \
-H "Authorization: Bearer ORG_SCOPED_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "required_entitlement": "activity.vip_lounge" }'
A session inherits from its activity and can override it, so a members-only series can still have one open session for newcomers.
To make a reward members-only, set it on the reward template. Two consequences:
- The entitlement gate is independent of the ticket gate. A ticket holder must still satisfy it. See Running an Event.
- A gated reward cannot be issued to somebody without an account, because a wallet with no owner holds no entitlements. Leave the gate unset on rewards you hand out at a door.
4. Read a member's entitlements
One call resolves a member's tier and everything it grants. It takes a
client_credentials token belonging to the organization, with
membership:entitlements:read; see Feature Gating.
curl "https://api.davi.social/api/v1/organizations/ORG_SLUG/memberships/USER_UUID/entitlements" \
-H "Authorization: Bearer TOKEN"
{
"has_membership": true,
"tier_slug": "gold",
"entitlements": { "reward.points_multiplier": 2, "activity.vip_lounge": null, "member": null }
}
Someone with no membership gets has_membership: false and empty entitlements,
not an error.
The resolved set includes the reserved member key, so an "any member, any
tier" check is a lookup. For a single key, GET .../entitlements/{key} answers
granted directly. Feature Gating covers both, and
which tokens can call them.
5. Act on joins, renewals and departures
Subscribe your webhook endpoint to the membership events:
| Event | Use it to |
|---|---|
membership.joined | Welcome a new member, issue a joining reward |
membership.renewed | Thank a returning member |
membership.left | Revoke anything you granted outside Davi |
A membership whose term runs out sends no event, including one that served out
a cancellation. Access stops at valid_until; to act on a lapse, read the
membership list on a schedule and compare each valid_until with now.
To issue a reward automatically on renewal instead of handling the event yourself, register a reward trigger on the same condition.
Next
- Membership Tiers and Members: the membership endpoints in full.
- Feature Gating: reading entitlements in your own product.
- Running an Event: the gates in an event flow.