Skip to main content
Vortex handles the complete invitation lifecycle — sending invites via email/SMS/share links, tracking clicks and conversions, managing referral programs, and optimizing your invitation flows with A/B testing. You focus on your product; Vortex handles the growth mechanics.

Installation

pip install vortex-python-sdk

Quick Start

Generate a secure token for Vortex components
from vortex_sdk import Vortex

vortex = Vortex(api_key=os.environ["VORTEX_API_KEY"])

# Generate a token for the current user
token = vortex.generate_token(user={"id": "user-123", "email": "user@example.com"})

# Pass the token to your frontend component
# <VortexInvite token={token} />

Integration Flow

Vortex uses a split architecture: your backend signs tokens with the SDK, and your frontend renders components that use those tokens to securely interact with Vortex.
1

Install the backend SDK

Add this SDK to your Python project
pip install vortex-python-sdk
2

Initialize the client

Create a Vortex client with your API key (keep this on the server!)
from vortex_sdk import Vortex

vortex = Vortex(api_key=os.environ["VORTEX_API_KEY"])
3

Generate a token for the current user

When a user loads a page with a Vortex component, generate a signed token on your server
token = vortex.generate_token(user={"id": current_user.id})
4

Pass the token to your frontend

Include the token in your page response or API response
return {"vortex_token": token}
5

Render a Vortex component with the token

Use the React/Angular/Web Component with the token
import { VortexInvite } from "@teamvortexsoftware/vortex-react";

<VortexInvite token={vortexToken} />
6

Vortex handles the rest

The component securely communicates with Vortex servers, displays the invitation UI, sends emails/SMS, tracks conversions, and reports analytics

Methods

Core Methods

generate_token()

Generate a signed token for use with Vortex components. This method generates a signed JWT token containing your payload data. The token can be passed to widgets via the token prop to authenticate and authorize the request.
generate_token(payload: GenerateTokenPayload | dict[str, Any], options: GenerateTokenOptions | dict[str, Any] | NoneType = None) -> str
Parameters:
NameTypeRequiredDescription
payload`GenerateTokenPayloaddict[str, Any]`Data to sign (user, component, scope, vars, etc.) At minimum, include user.id for secure invitation attribution.
options`GenerateTokenOptionsdict[str, Any]NoneType`Optional configuration. Supports expires_in (default: 30 days).
Returns: str — Signed JWT token string

get_invitation()

Get a specific invitation by ID
get_invitation(invitation_id: str) -> InvitationResult
Parameters:
NameTypeRequiredDescription
invitation_idstrInvitation ID
Returns: InvitationResult — Invitation object

accept_invitation()

Accept a single invitation (recommended method) This is the recommended method for accepting invitations.
accept_invitation(invitation_id: str, user: AcceptUser | dict[str, Any]) -> dict
Parameters:
NameTypeRequiredDescription
invitation_idstrSingle invitation ID to accept
user`AcceptUserdict[str, Any]`User object with email/phone/name
Returns: dict — API response

get_invitations_by_target()

Get invitations for a specific target
get_invitations_by_target(target_type: Literal[email, username, phoneNumber], target_value: str) -> list[InvitationResult]
Parameters:
NameTypeRequiredDescription
target_typeLiteral[email, username, phoneNumber]Type of target (email, username, or phoneNumber)
target_valuestrTarget value
Returns: list[InvitationResult] — List of invitations

revoke_invitation()

Revoke an invitation
revoke_invitation(invitation_id: str) -> dict
Parameters:
NameTypeRequiredDescription
invitation_idstrInvitation ID to revoke
Returns: dict — API response

accept_invitations()

Accept multiple invitations using the new User format (preferred)
accept_invitations(invitation_ids: list[str], user_or_target: AcceptUser | InvitationTarget | dict[str, Any] | list[InvitationTarget | dict[str, str]]) -> dict
Parameters:
NameTypeRequiredDescription
invitation_idslist[str]List of invitation IDs to accept
user_or_target`AcceptUserInvitationTargetdict[str, Any]list[InvitationTargetdict[str, str]]`User object with email/phone/name (preferred) OR legacy target format (deprecated)
Returns: dict — API response Example (new format): user = AcceptUser(email=“user@example.com”, name=“John Doe”) result = await client.accept_invitations([“inv-123”], user) Example (legacy format - deprecated): target = InvitationTarget(type=“email”, value=“user@example.com”) result = await client.accept_invitations([“inv-123”], target)

delete_invitations_by_scope()

Delete all invitations for a specific group
delete_invitations_by_scope(scope_type: str, scope: str) -> dict
Parameters:
NameTypeRequiredDescription
scope_typestrType of group
scopestrGroup ID
Returns: dict — API response

get_invitations_by_scope()

Get invitations for a specific group
get_invitations_by_scope(scope_type: str, scope: str) -> list[InvitationResult]
Parameters:
NameTypeRequiredDescription
scope_typestrType of group
scopestrGroup ID
Returns: list[InvitationResult] — List of invitations

reinvite()

Reinvite for a specific invitation
reinvite(invitation_id: str) -> InvitationResult
Parameters:
NameTypeRequiredDescription
invitation_idstrInvitation ID to reinvite
Returns: InvitationResult — Updated invitation object

get_autojoin_domains()

Get autojoin domains configured for a specific scope
get_autojoin_domains(scope_type: str, scope: str) -> AutojoinDomainsResponse
Parameters:
NameTypeRequiredDescription
scope_typestrThe type of scope (e.g., “organization”, “team”, “project”)
scopestrThe scope identifier (customer’s group ID)
Returns: AutojoinDomainsResponse — AutojoinDomainsResponse with autojoin_domains and associated invitation

configure_autojoin()

Configure autojoin domains for a specific scopeThis endpoint syncs autojoin domains - it will add new domains, remove domains not in the provided list, and deactivate the autojoin invitation if all domains are removed (empty array).
configure_autojoin(scope: str, scope_type: str, domains: list[str], component_id: str, scope_name: Optional[str] = None, metadata: Optional[dict[str, Any]] = None) -> AutojoinDomainsResponse
Parameters:
NameTypeRequiredDescription
scopestrThe scope identifier (customer’s group ID)
scope_typestrThe type of scope (e.g., “organization”, “team”)
domainslist[str]Array of domains to configure for autojoin
component_idstrThe component ID
scope_nameOptional[str]Optional display name for the scope
metadataOptional[dict[str, Any]]Optional metadata to attach to the invitation
Returns: AutojoinDomainsResponse — AutojoinDomainsResponse with updated autojoin_domains and associated invitation

Types

GenerateTokenPayload

Payload for generate_token() - used to generate secure tokens for Vortex components
FieldTypeRequiredDescription
userTokenUserThe authenticated user who will be using the Vortex component
componentstrComponent ID to generate token for (from your Vortex dashboard)
scopestrScope identifier to restrict invitations (format: “scopeType:scopeId”)
varsdictCustom variables to pass to the component for template rendering

TokenUser

User data for token generation - represents the authenticated user sending invitations
FieldTypeRequiredDescription
idstrUnique identifier for the user in your system. Used to attribute invitations.
emailstrUser’s email address. Used for reply-to in invitation emails.
namestrDisplay name shown to invitation recipients (e.g., “John invited you”)
avatar_urlstrURL to user’s avatar image. Displayed in invitation emails and widgets.
admin_scopesList[str]List of scope IDs where this user has admin privileges
allowed_email_domainsList[str]Restrict invitations to specific email domains (e.g., [“acme.com”])

AcceptUser

User data for accepting invitations - identifies who accepted the invitation
FieldTypeRequiredDescription
emailstrEmail address of the accepting user. At least one of email or phone is required.
phonestrPhone number with country code. At least one of email or phone is required.
namestrDisplay name of the accepting user (shown in notifications to inviter)
is_existingboolWhether user was already registered. True=existing, False=new signup, None=unknown.

CreateInvitationTarget

Target specification when creating an invitation - where to send the invite
FieldTypeRequiredDescription
typestrDelivery channel: “email”, “phone”, “share”, or “internal”
valuestrTarget address: email address, phone number with country code, or internal user ID
namestrDisplay name of the recipient (used in email greetings)

CreateInvitationScope

Scope specification when creating an invitation - what group/team to invite into
FieldTypeRequiredDescription
typestrScope type (e.g., “team”, “organization”, “workspace”)
group_idstrYour internal identifier for this scope/group
namestrDisplay name for the scope (shown in invitation emails)

Identifier

Email or phone identifier for looking up users
FieldTypeRequiredDescription
typestrIdentifier type: “email” or “phone”
valuestrThe email address or phone number (with country code for phone)

ConfigureAutojoinRequest

Request to configure autojoin domains for a scope
FieldTypeRequiredDescription
scope_typestrType of scope (e.g., “team”, “workspace”)
scope_idstrYour internal identifier for the scope
domainsList[str]List of email domains to enable autojoin for (e.g., [“acme.com”])

SyncInternalInvitationRequest

Request to sync an internal invitation (for tracking invitations made outside Vortex)
FieldTypeRequiredDescription
inviter_idstrYour internal user ID for the person who sent the invitation
targetCreateInvitationTargetThe invitation recipient
scopesList[CreateInvitationScope]Scopes/groups the invitation grants access to

InvitationResult

Complete invitation details as returned by the Vortex API
FieldTypeRequiredDescription
idstrUnique identifier for this invitation
account_idstrYour Vortex account ID
click_throughsintNumber of times the invitation link was clicked
created_atstrISO 8601 timestamp when the invitation was created
deactivatedboolWhether this invitation has been revoked or expired
delivery_countintNumber of times the invitation was sent (including reminders)
delivery_typesList[str]Channels used to deliver: “email”, “phone”, “share”, “internal”
foreign_creator_idstrYour internal user ID for the person who created this invitation
invitation_typestrType: “single_use”, “multi_use”, or “autojoin”
statusstrCurrent status: queued, sending, sent, delivered, accepted, shared
targetList[InvitationTarget]List of invitation recipients with their contact info and status
viewsintNumber of times the invitation page was viewed
groupsList[InvitationScope]Scopes (teams/orgs) this invitation grants access to
expiredboolWhether this invitation has passed its expiration date
expiresstrISO 8601 timestamp when this invitation expires
inviterInviterInformation about who sent the invitation

InvitationTarget

Target recipient of an invitation (from API response)
FieldTypeRequiredDescription
typestrDelivery channel: “email”, “phone”, “share”, or “internal”
valuestrTarget address: email, phone number with country code, or share link ID
namestrDisplay name of the recipient
avatar_urlstrAvatar URL for the recipient
statusstrDelivery status for this specific target

InvitationScope

Scope/group that the invitation grants access to (from API response)
FieldTypeRequiredDescription
idstrVortex internal UUID for this scope record
account_idstrYour Vortex account ID
group_idstrYour internal scope/group identifier
typestrScope type (e.g., “team”, “organization”, “workspace”)
namestrDisplay name for the scope
created_atstrISO 8601 timestamp when the scope was created

InvitationAcceptance

Details about an invitation acceptance event
FieldTypeRequiredDescription
idstrUnique identifier for this acceptance record
invitation_idstrID of the invitation that was accepted
emailstrEmail of the user who accepted
phonestrPhone of the user who accepted
namestrName of the user who accepted
is_existingboolWhether the user already had an account
created_atstrISO 8601 timestamp when the acceptance occurred

Inviter

Information about the user who sent an invitation
FieldTypeRequiredDescription
idstrYour internal user ID for the inviter
emailstrEmail address of the inviter
namestrDisplay name of the inviter
avatar_urlstrAvatar URL of the inviter

AutojoinDomain

Autojoin domain configuration - users with matching email domains automatically join
FieldTypeRequiredDescription
idstrUnique identifier for this autojoin configuration
domainstrEmail domain that triggers autojoin (e.g., “acme.com”)

AutojoinDomainsResponse

Response from get_autojoin_domains()
FieldTypeRequiredDescription
domainsList[AutojoinDomain]List of configured autojoin domains

SyncInternalInvitationResponse

Response from sync_internal_invitation()
FieldTypeRequiredDescription
invitationInvitationResultThe created or updated invitation
createdboolTrue if a new invitation was created, False if existing was updated

VortexWebhookEvent

Webhook event payload delivered to your endpoint
FieldTypeRequiredDescription
idstrUnique identifier for this webhook delivery
typestrEvent type (e.g., “invitation.accepted”, “member.created”)
timestampstrISO 8601 timestamp when the event occurred
datadictEvent-specific payload data

Webhooks

Webhooks let your server receive real-time notifications when events happen in Vortex. Use them to sync invitation state with your database, trigger onboarding flows, update your CRM, or send internal notifications.

Setup

  1. Go to your Vortex dashboard → Integrations → Webhooks tab
  2. Click “Add Webhook”
  3. Enter your endpoint URL (must be HTTPS in production)
  4. Copy the signing secret — you’ll use this to verify webhook signatures
  5. Select which events you want to receive

Example

Flask webhook handler
from flask import Flask, request, jsonify
from vortex_sdk import VortexWebhooks
import os

app = Flask(__name__)
webhooks = VortexWebhooks(os.environ["VORTEX_WEBHOOK_SECRET"])

@app.route("/webhooks/vortex", methods=["POST"])
def handle_webhook():
    payload = request.get_data()
    signature = request.headers.get("X-Vortex-Signature")
    
    # Verify the signature
    if not webhooks.verify_signature(payload, signature):
        return jsonify({"error": "Invalid signature"}), 400
    
    # Parse the event
    event = webhooks.parse_event(payload)
    
    if event["type"] == "invitation.accepted":
        # User accepted an invitation — activate their account
        print(f"Accepted: {event['data']}")
    elif event["type"] == "member.created":
        # New member joined via invitation
        print(f"New member: {event['data']}")
    
    return jsonify({"received": True})

Events

EventDescription
invitation.createdA new invitation was created
invitation.acceptedAn invitation was accepted by the recipient
invitation.deactivatedAn invitation was deactivated (revoked or expired)
invitation.email.deliveredInvitation email was successfully delivered
invitation.email.bouncedInvitation email bounced (invalid address)
invitation.email.openedRecipient opened the invitation email
invitation.link.clickedRecipient clicked the invitation link
invitation.reminder.sentA reminder email was sent for a pending invitation
member.createdA new member was created from an accepted invitation
group.member.addedA member was added to a scope/group
deployment.createdA new deployment configuration was created
deployment.deactivatedA deployment was deactivated
abtest.startedAn A/B test was started
abtest.winner_declaredAn A/B test winner was declared
email.complainedRecipient marked the email as spam

Use Cases

  • Activate users on acceptance — When invitation.accepted fires, mark the user as active in your database and trigger your onboarding flow.
  • Track invitation performance — Monitor email.delivered, email.opened, and link.clicked events to measure invitation funnel metrics.
  • Sync team membership — Use member.created and group.member.added to keep your internal membership records in sync.
  • Alert on delivery issues — Watch for email.bounced events to proactively reach out via alternative channels.

Error Handling

ErrorDescription
VortexWebhookSignatureErrorRaised when webhook signature verification fails. Check that you are using the raw request body and the correct signing secret.
VortexApiErrorRaised for validation errors (e.g., missing API key, invalid parameters)

Resources