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.

Installation

go get github.com/teamvortexsoftware/vortex-go-sdk

Quick Start

Generate a secure token for Vortex components
import "github.com/teamvortexsoftware/vortex-go-sdk"

client := vortex.NewClient(os.Getenv("VORTEX_API_KEY"))

// Generate a token for the current user
token, err := client.GenerateToken(vortex.GenerateTokenPayload{
    User: &vortex.TokenUser{ID: "user-123", Email: "user@example.com"},
})

// Pass the token to your frontend component

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 Go server
go get github.com/teamvortexsoftware/vortex-go-sdk
2

Initialize the client

Create a Vortex client with your API key (keep this on the server!)
import "github.com/teamvortexsoftware/vortex-go-sdk"

client := vortex.NewClient(os.Getenv("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, err := client.GenerateToken(vortex.GenerateTokenPayload{
User: &vortex.TokenUser{ID: currentUser.ID},
})
4

Pass the token to your frontend

Include the token in your page response or API response
json.NewEncoder(w).Encode(map[string]string{"vortexToken": 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

GenerateToken()

GenerateToken creates a signed JWT 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. Parameters:
  • payload: Data to sign (user, component, scope, vars, etc.) At minimum, include user.ID for secure invitation attribution.
  • options: Optional configuration. Supports ExpiresIn (default: 30 days).
Returns:
  • Signed JWT token string
  • error if API key format is invalid or token generation fails
GenerateToken(payload *GenerateTokenPayload, options *GenerateTokenOptions) (string, error)
Parameters:
NameTypeRequiredDescription
payload*GenerateTokenPayload
options*GenerateTokenOptions
Returns: (string, error)
// Sign just the user (minimum for secure attribution)
token, err := client.GenerateToken(&GenerateTokenPayload{
User: &TokenUser{ID: "user-123"},
}, nil)

// Sign full payload
token, err := client.GenerateToken(&GenerateTokenPayload{
Component: "widget-abc",
User: &TokenUser{
ID:    "user-123",
Name:  "Peter",
Email: "peter@example.com",
},
Scope: "workspace_456",
Vars:  map[string]interface{}{"company_name": "Acme"},
}, nil)

// Custom expiration (default is 30 days)
token, err := client.GenerateToken(payload, &GenerateTokenOptions{
ExpiresIn: "1h", // or 3600 (seconds)
})

GetInvitation()

GetInvitation retrieves a specific invitation by ID
GetInvitation(invitationID string) (*InvitationResult, error)
Parameters:
NameTypeRequiredDescription
invitationIDstring
Returns: (*InvitationResult, error)

AcceptInvitation()

AcceptInvitation accepts a single invitation (recommended method) This is the recommended method for accepting invitations. Parameters:
  • invitationID: Single invitation ID to accept
  • user: User object with email and/or phone
Returns:
  • *InvitationResult: The accepted invitation result
  • error: Any error that occurred
AcceptInvitation(invitationID string, user *AcceptUser) (*InvitationResult, error)
Parameters:
NameTypeRequiredDescription
invitationIDstring
user*AcceptUser
Returns: (*InvitationResult, error)
email := "user@example.com"
user := &AcceptUser{Email: &email}
result, err := client.AcceptInvitation("inv-123", user)

GenerateJWT()

GenerateJWT(user *User, extra map[string]interface{}, opts any) (string, error)
Parameters:
NameTypeRequiredDescription
user*User
extramap[string]interface{}
optsany
Returns: (string, error)

GetInvitationsByTarget()

GetInvitationsByTarget retrieves invitations by target type and value.
GetInvitationsByTarget(targetType string, targetValue string) ([]InvitationResult, error)
Parameters:
NameTypeRequiredDescription
targetTypestring
targetValuestring
Returns: ([]InvitationResult, error)

RevokeInvitation()

RevokeInvitation revokes an invitation.
RevokeInvitation(invitationID string) error
Parameters:
NameTypeRequiredDescription
invitationIDstring
Returns: error

AcceptInvitations()

AcceptInvitations accepts multiple invitations.Supports three formats:
  1. *AcceptUser (preferred): user with email/phone/name
  2. InvitationTarget (deprecated): single target
  3. []InvitationTarget (deprecated): multiple targets (calls API once per target)
Example with AcceptUser (preferred):email := “user@example.com” name := “John Doe” user := &vortex.AcceptUser{Email: &email, Name: &name} result, err := client.AcceptInvitations(invitationIds, user)Example with InvitationTarget (deprecated):target := vortex.InvitationTarget{Type: “email”, Value: “user@example.com”} result, err := client.AcceptInvitations(invitationIds, target)
AcceptInvitations(invitationIDs []string, userOrTarget interface{}) (*InvitationResult, error)
Parameters:
NameTypeRequiredDescription
invitationIDs[]string
userOrTargetinterface{}
Returns: (*InvitationResult, error)

DeleteInvitationsByGroup()

Deprecated: Use DeleteInvitationsByScope instead
DeleteInvitationsByGroup(groupType string, groupID string) error
Parameters:
NameTypeRequiredDescription
groupTypestring
groupIDstring
Returns: error

GetInvitationsByGroup()

Deprecated: Use GetInvitationsByScope instead
GetInvitationsByGroup(groupType string, groupID string) ([]InvitationResult, error)
Parameters:
NameTypeRequiredDescription
groupTypestring
groupIDstring
Returns: ([]InvitationResult, error)

DeleteInvitationsByScope()

DeleteInvitationsByScope deletes all invitations for a specific group
DeleteInvitationsByScope(groupType string, groupID string) error
Parameters:
NameTypeRequiredDescription
groupTypestring
groupIDstring
Returns: error

GetInvitationsByScope()

GetInvitationsByScope retrieves invitations for a specific group.
GetInvitationsByScope(groupType string, groupID string) ([]InvitationResult, error)
Parameters:
NameTypeRequiredDescription
groupTypestring
groupIDstring
Returns: ([]InvitationResult, error)

Reinvite()

Reinvite sends a reinvitation for a specific invitation
Reinvite(invitationID string) (*InvitationResult, error)
Parameters:
NameTypeRequiredDescription
invitationIDstring
Returns: (*InvitationResult, error)

GetAutojoinDomains()

GetAutojoinDomains retrieves autojoin domains configured for a specific scope.Parameters:
  • scopeType: The type of scope (e.g., “organization”, “team”, “project”)
  • scope: The scope identifier (customer’s group ID)
Returns autojoin domains and associated invitation
GetAutojoinDomains(scopeType string, scope string) (*AutojoinDomainsResponse, error)
Parameters:
NameTypeRequiredDescription
scopeTypestring
scopestring
Returns: (*AutojoinDomainsResponse, error)
result, err := client.GetAutojoinDomains("organization", "acme-org")
if err != nil {
log.Fatal(err)
}
for _, domain := range result.AutojoinDomains {
fmt.Printf("Domain: %s\n", domain.Domain)
}

ConfigureAutojoin()

ConfigureAutojoin(request *ConfigureAutojoinRequest) (*AutojoinDomainsResponse, error)
Parameters:
NameTypeRequiredDescription
request*ConfigureAutojoinRequest
Returns: (*AutojoinDomainsResponse, error)

SyncInternalInvitation()

ConfigureAutojoin configures 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).
SyncInternalInvitation(request *SyncInternalInvitationRequest) (*SyncInternalInvitationResponse, error)
Parameters:
NameTypeRequiredDescription
request*SyncInternalInvitationRequest
Returns: (*SyncInternalInvitationResponse, error)
scopeName := "Acme Corporation"
result, err := client.ConfigureAutojoin(&vortex.ConfigureAutojoinRequest{
Scope:       "acme-org",
ScopeType:   "organization",
ScopeName:   &scopeName,
Domains:     []string{"acme.com", "acme.org"},
ComponentID: "component-123",
})
SyncInternalInvitation syncs an internal invitation action (accept or decline)

This method notifies Vortex that an internal invitation was accepted or declined
within your application, so Vortex can update the invitation status accordingly.


result, err := client.SyncInternalInvitation(&vortex.SyncInternalInvitationRequest{
CreatorID:   "user-123",
TargetValue: "user-456",
Action:      "accepted",
ComponentID: "component-uuid-789",
})

Types

GenerateTokenPayload

GenerateTokenPayload represents the payload for token generation - used to create secure tokens for Vortex components
FieldTypeRequiredDescription
user*TokenUserThe authenticated user who will be using the Vortex component
componentstringComponent ID to generate token for (from your Vortex dashboard)
scopestringScope identifier to restrict invitations (format: “scopeType:scopeId”)
varsmap[string]interface{}Custom variables to pass to the component for template rendering
Extramap[string]interface{}Additional fields to include in token

TokenUser

TokenUser represents user data for token generation - the authenticated user sending invitations
FieldTypeRequiredDescription
idstringUnique identifier for the user in your system. Used to attribute invitations.
emailstringUser’s email address. Used for reply-to in invitation emails.
namestringDisplay name shown to invitation recipients (e.g., “John invited you”)
avatarUrlstringURL to user’s avatar image. Displayed in invitation emails and widgets.
adminScopes[]stringList of scope IDs where this user has admin privileges
allowedEmailDomains[]stringRestrict invitations to specific email domains (e.g., [“acme.com”])
Extramap[string]interface{}Additional fields included in token

AcceptUser

AcceptUser represents user data for accepting invitations - identifies who accepted
FieldTypeRequiredDescription
email*stringEmail address of the accepting user. At least one of Email or Phone is required.
phone*stringPhone number with country code (e.g., “+15551234567”). At least one of Email or Phone is required.
name*stringDisplay name of the accepting user (shown in notifications to inviter)
isExisting*boolWhether user was already registered. true=existing, false=new signup, nil=unknown. Used for conversion analytics.

InvitationResult

InvitationResult represents a complete invitation as returned by the Vortex API
FieldTypeRequiredDescription
idstringUnique identifier for this invitation
accountIdstringYour Vortex account ID
clickThroughsintNumber of times the invitation link was clicked
formSubmissionDatamap[string]interface{}Data submitted through the invitation form, including standard fields and any custom fields configured on your widget
configurationAttributesmap[string]interface{}Deprecated: Use FormSubmissionData instead. Contains the same data.
attributesmap[string]interface{}Custom attributes attached to this invitation
createdAtstringISO 8601 timestamp when the invitation was created
deactivatedboolWhether this invitation has been revoked or expired
deliveryCountintNumber of times the invitation was sent (including reminders)
deliveryTypes[]stringChannels used to deliver: “email”, “phone”, “share”, “internal”
foreignCreatorIdstringYour internal user ID for the person who created this invitation
invitationTypestringType: “single_use” (1:1), “multi_use” (1:many), or “autojoin”
modifiedAt*stringISO 8601 timestamp of last modification
statusstringCurrent status: queued, sending, sent, delivered, accepted, shared, unfurled
target[]InvitationTargetList of invitation recipients with their contact info and status
viewsintNumber of times the invitation page was viewed
widgetConfigurationIdstringWidget configuration ID used for this invitation
deploymentIdstringDeployment ID this invitation belongs to
groups[]InvitationScopeScopes (teams/orgs) this invitation grants access to
scopes[]InvitationScopePreferred alias for Groups
accepts[]InvitationAcceptanceList of acceptance records if the invitation was accepted
scope*stringPrimary scope identifier (e.g., “team-123”)
scopeType*stringType of the primary scope (e.g., “team”, “organization”)
expiredboolWhether this invitation has passed its expiration date
expires*stringISO 8601 timestamp when this invitation expires
metadatamap[string]interface{}Custom metadata attached to this invitation
passThrough*stringPass-through data returned unchanged in webhooks and callbacks
source*stringSource identifier for tracking (e.g., “ios-app”, “web-dashboard”)
subtype*stringSubtype for analytics segmentation (e.g., “pymk”, “find-friends”)
creatorName*stringDisplay name of the user who created this invitation
creatorAvatarUrl*stringAvatar URL of the user who created this invitation

InvitationTarget

InvitationTarget represents the target recipient of an invitation
FieldTypeRequiredDescription
typestringDelivery channel: “email”, “phone”, “share” (link), or “internal” (in-app)
valuestringTarget address: email, phone number with country code, or share link ID
name*stringDisplay name of the recipient (e.g., “John Doe”)
avatarUrl*stringAvatar URL for the recipient, shown in invitation lists and widgets

InvitationScope

InvitationScope represents a scope/group the invitation grants access to
FieldTypeRequiredDescription
idstringVortex internal UUID for this scope record
accountIdstringYour Vortex account ID
groupIdstringYour internal scope/group identifier
scopeIdstringPreferred alias for Scope (same value as groupId)
typestringScope type (e.g., “team”, “organization”, “workspace”)
namestringDisplay name for the scope (e.g., “Engineering Team”)
createdAtstringISO 8601 timestamp when the scope was created

AutojoinDomain

AutojoinDomain represents an autojoin domain - users with matching email domains automatically join the scope
FieldTypeRequiredDescription
idstringUnique identifier for this autojoin configuration
domainstringEmail domain that triggers autojoin (e.g., “acme.com”)

Client

Client represents a Vortex API client

GenerateJWTOptions

GenerateJWTOptions represents options for JWT generation
FieldTypeRequiredDescription
expiresIninterface{}JWT expiry: duration string (“5m”, “1h”, “7d”) or seconds as int. Default: 30 days

GenerateTokenOptions

GenerateTokenOptions represents options for token generation
FieldTypeRequiredDescription
expiresIninterface{}Token expiry: duration string (“5m”, “1h”, “7d”) or seconds as int. Default: 30 days

Group

Group represents a scope/group for JWT generation - defines user’s team/org membership in tokens
FieldTypeRequiredDescription
typestringScope type (e.g., “team”, “organization”, “workspace”)
id*stringLegacy scope identifier. Use Scope instead.
groupId*stringYour internal scope/group identifier (preferred)
namestringDisplay name for the scope (e.g., “Engineering Team”)

Identifier

Identifier represents a user identifier - used in JWT generation to link user across channels
FieldTypeRequiredDescription
typestringIdentifier type: “email”, “phone”, “username”, or custom type
valuestringThe identifier value (email address, phone number, etc.)

InvitationAcceptance

InvitationAcceptance represents a record of an invitation being accepted
FieldTypeRequiredDescription
idstringUnique identifier for this acceptance record
accountIdstringYour Vortex account ID
acceptedAtstringISO 8601 timestamp when the invitation was accepted
targetInvitationTargetThe target that accepted the invitation

Inviter

Inviter represents information about the user creating the invitation
FieldTypeRequiredDescription
userIdstringRequired: Your internal user ID for the inviter
userEmail*stringOptional: Email of the inviter
name*stringOptional: Display name of the inviter (preferred)
avatarUrl*stringOptional: Avatar URL of the inviter (preferred)
userName*stringDeprecated: use Name instead
userAvatarUrl*stringDeprecated: use AvatarUrl instead

JWTPayload

JWTPayload represents the payload for JWT generation (legacy format) - use JWTPayloadSimple instead
FieldTypeRequiredDescription
userIdstringYour internal user ID (required for invitation attribution)
identifiers[]IdentifierLegacy: List of user identifiers. Use userEmail instead.
groups[]GroupLegacy: List of groups/scopes. Use scope parameter instead.
role*stringLegacy: User role. No longer used.

JWTPayloadSimple

JWTPayloadSimple represents the simplified JWT payload (recommended format)
FieldTypeRequiredDescription
userIdstringYour internal user ID (required for invitation attribution)
userEmailstringUser’s email address (used for identification)
userIsAutojoinAdmin*boolWhether user can manage autojoin settings for their scopes

User

User represents user data for JWT generation - the authenticated user sending invitations
FieldTypeRequiredDescription
idstringYour internal user ID (required for invitation attribution)
emailstringUser’s email address (used for identification and reply-to)
name*stringDisplay name shown to recipients (e.g., “John invited you”)
avatarUrl*stringAvatar URL displayed in invitation emails and widgets (must be HTTPS)
userName*stringDeprecated: use Name instead
userAvatarUrl*stringDeprecated: use AvatarUrl instead
adminScopes[]stringList of scopes where user has admin privileges (e.g., [“autojoin”])
allowedEmailDomains[]stringRestrict invitations to these email domains (e.g., [“acme.com”])
Extramap[string]interface{}Additional fields included in signing

VortexAnalyticsEvent

VortexAnalyticsEvent represents a client-side behavioral telemetry event from Vortex widgets
FieldTypeRequiredDescription
idstringUnique identifier for this analytics event
namestringEvent name (e.g., “widget.opened”, “invite.sent”, “link.clicked”)
accountIdstringYour Vortex account ID
organizationIdstringOrganization ID if using multi-org setup
projectIdstringProject ID the event belongs to
environmentId*stringEnvironment ID (production, staging, etc.)
deploymentId*stringDeployment ID the event is associated with
widgetConfigurationId*stringWidget configuration ID that generated this event
foreignUserId*stringYour internal user ID who triggered the event
sessionId*stringClient session ID for grouping related events
payloadmap[string]interface{}Event-specific payload data
platform*stringPlatform: “web”, “ios”, “android”, “react-native”
segmentation*stringA/B test segmentation identifier
timestampstringISO 8601 timestamp when the event occurred

VortexEvent

VortexEvent is the union type for webhook and analytics events - use IsWebhookEvent/IsAnalyticsEvent to determine type
FieldTypeRequiredDescription
namestringAnalytics: Event name (e.g., “widget.opened”)
organizationIdstringAnalytics: Organization ID if using multi-org setup
projectIdstringAnalytics: Project ID the event belongs to
deploymentId*stringAnalytics: Deployment ID the event is associated with
widgetConfigurationId*stringAnalytics: Widget configuration ID
foreignUserId*stringAnalytics: Your internal user ID
sessionId*stringAnalytics: Client session ID
payloadmap[string]interface{}Analytics: Event-specific payload data
platform*stringAnalytics: Platform (“web”, “ios”, “android”)
segmentation*stringAnalytics: A/B test segmentation identifier

VortexWebhookEvent

VortexWebhookEvent represents a server-side state change event from Vortex
FieldTypeRequiredDescription
idstringUnique identifier for this webhook event
typestringEvent type (e.g., “invitation.accepted”, “member.created”)
timestampstringISO 8601 timestamp when the event occurred
accountIdstringYour Vortex account ID
environmentId*stringEnvironment ID (production, staging, etc.)
sourceTablestringInternal: database table that triggered this event
operationstringDatabase operation: “INSERT”, “UPDATE”, or “DELETE”
datamap[string]interface{}Event payload containing the relevant entity data

VortexWebhookSignatureError

VortexWebhookSignatureError wraps signature verification failures with context
FieldTypeRequiredDescription
MessagestringDetailed error message explaining the signature verification failure

VortexWebhooks

VortexWebhooks provides webhook verification and parsing.

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

import (
    "encoding/json"
    "net/http"
    "os"
    
    "github.com/teamvortexsoftware/vortex-go-sdk"
)

func webhookHandler(w http.ResponseWriter, r *http.Request) {
    secret := os.Getenv("VORTEX_WEBHOOK_SECRET")
    signature := r.Header.Get("X-Vortex-Signature")
    
    body, _ := io.ReadAll(r.Body)
    
    // Verify the signature
    if !vortex.VerifyWebhook(body, signature, secret) {
        http.Error(w, "Invalid signature", http.StatusBadRequest)
        return
    }
    
    // Parse the event
    var event vortex.WebhookEvent
    json.Unmarshal(body, &event)
    
    switch event.Type {
    case "invitation.accepted":
        // User accepted an invitation — activate their account
        log.Printf("Accepted: %v", event.Data)
    case "member.created":
        // New member joined via invitation
        log.Printf("New member: %v", event.Data)
    }
    
    json.NewEncoder(w).Encode(map[string]bool{"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
VortexErrorReturned for validation errors (e.g., missing API key, invalid parameters) or API failures. Wraps the underlying error with context.

Resources