Skip to main content
You sell a course or digital product on an external gateway (Hotmart, Kiwify, Eduzz, Stripe Checkout) and want the purchase to automatically unlock access to a group, course or space inside your Cativa community. This guide walks through the recommended architecture and the endpoints you use to assign the badge as soon as the purchase is confirmed.

Scenario

A customer buys “Premium Course” on Hotmart. Within seconds they get access to the “Premium Students” group and to the course inside your Cativa community. The bridge between both sides is the badge-as-permission concept: the Premium badge is configured in the Console as the access requirement on that group and course. Once the user gets the badge, access shows up automatically. When the badge is removed, access is gone.

Prerequisites

  1. Cativa API Key — generated in the Console (Developers > API Keys). See Quick Start: API Key. Every call uses Authorization: Bearer cativa_live_....
  2. Badge configured in the Console — create the Premium badge (or whatever your product is called) and configure it as the access requirement on the group/course. See Badges as Permissions.
  3. Purchase webhook from your gateway — Hotmart, Kiwify, Eduzz and Stripe fire a webhook to your server’s endpoint when a purchase is confirmed. Do not point the gateway webhook directly at Cativa — you need a proxy server that receives, validates and translates the event.
  4. A reliable buyer email — every gateway sends the email in the purchase payload. That’s the join key with the Cativa user.

Architecture

You’re the broker between gateway and Cativa. That gives you control to:
  • Validate the gateway webhook (each one has its own signature — check the gateway docs).
  • Handle idempotency (Hotmart can fire the same webhook twice).
  • Log the gateway purchase ID for audit/reconciliation.
  • Decide the right badge based on which product was purchased.
You can optionally subscribe to the Cativa user_received_badge webhook to fire a welcome email, update your CRM, or log an analytics event.

Implementation

1

Receive the gateway webhook

Each gateway has its own webhook format and its own signing mechanism. Configure the webhook in the gateway dashboard pointing to an endpoint on your server (e.g. https://myapp.com/webhooks/hotmart).Cativa does not document the gateway webhook formats — refer to the official docs:Receiver skeleton (Express, Hotmart example):
Always verify the gateway webhook signature before trusting the data. Without it, anyone who finds your URL could grant arbitrary badges.
2

Resolve or create the user on Cativa by email

Two situations:Case A — the buyer already has a Cativa account: find their User.Id from the email with GET /admin/users/email/{email}.
200 OK response (illustrative; full schema in the API Reference, Users tag):
To avoid one call per purchase, keep a local email → cativa_user_id table populated by Cativa’s user_created webhook and look it up locally:
Case B — the buyer does not have a Cativa account yet: the lookup above returns 404. You have two options:
  • Create directly via API with POST /admin/users (schema in the API Reference, Users tag) — creates the account on the spot and returns the id, which you use right away to assign the badge.
  • Invite and complete later: register the intent in pendingGrants, send the tenant’s sign-up link, and complete the assignment when the user_created webhook arrives (see step 4).
3

Assign the badge

Map the gateway productId to the Cativa badgeId configured in the Console.Badge assignment via partner API Key is available. You have two options:
  • Assign by email (POST /admin/membership/badges/{badgeId}/users/by-email) — no need to resolve the userId first; Cativa matches on the buyer’s email. Ideal for the webhook, where you only have the email.
  • Assign by id (POST /admin/membership/badges/{badgeId}/users/{userId}) — when you already have the userId (e.g. from the user_created webhook).
Assign by email:
200 OK response (illustrative; full schema in the API Reference, Badge tag):
Inside the full handler, with the userId already resolved:
Cativa guarantees that assigning the same badge twice is idempotent (see Badges as Permissions) — so retries caused by timeouts or gateway redelivery do not double-grant. The purchaseId check above still avoids redundant calls and helps reconciliation.
4

(Optional) React to the user_received_badge webhook

Cativa fires user_received_badge every time a badge is assigned (regardless of whether it came from the API, Console, or another flow). Subscribe a listener to it if you want to:
  • Send a welcome email with a link to the community
  • Update the contact status in your CRM
  • Track conversion in analytics
See Subscribing and verifying webhooks for the listener-subscription steps and HMAC verification. The event payload is documented at user_received_badge and looks like this (illustrative):
Receiver skeleton:

Cancellation and chargeback

When the gateway cancels or charges back, you want to remove the badge to revoke access.
Badge removal via partner API Key is availableDELETE /admin/membership/badges/{badgeId}/users/{userId}. See the schema in the API Reference tab (Badge tag). Removal is idempotent too: removing a badge that isn’t assigned returns success without error.
Removing the badge is enough — group, course and space access tied to the badge disappears immediately.

Common errors

Most common case. The customer bought on Hotmart before joining your community.Fix: step 2 above covers it — register the intent in pendingGrants and send the invite. Subscribe the user_created webhook and, when sign-up happens, complete the assignment:
Happens when the customer pays with a personal email and joins the community with a corporate one. No automatic fix.Fix: offer an “I already bought, but I’m logged in with a different email” page in your app where the customer enters the purchase email. You validate the purchase ID locally and assign the badge to the logged-in user (not to the purchase email).
Badge assignment in Cativa is idempotent: applying the same badge twice produces the same final state. But for safety, store the gateway purchaseId in a local table and check before:
This also helps audit/reconcile later (e.g. financial report vs grants).
Each gateway fires a webhook when the renewal is charged successfully (e.g. Hotmart SUBSCRIPTION_CHARGE_SUCCESS). Treat it as an idempotent handlePurchase — re-apply the badge (no effect if already there). If the renewal fails (e.g. card declined), treat it as handleCancellation.
You need to react to chargeback fast — the gateway webhook arrives, you remove the badge, access to the resources tied to it disappears. Don’t rely on a nightly batch job for this.
Map a product to multiple badges when needed. Example: product Premium Course unlocks both Premium (course access) and Mentoring-2026 (mentoring group access). Make two assignments inside handlePurchase.

Next steps

Cativa webhooks

Subscribe listeners for user_created (cover the “bought before signing up” case) and user_received_badge (trigger post-access actions).

Sync members from your CRM

If you also run a CRM, combine this flow with tag sync to have a single hub of permissions.