TeamVortexSoftware.VortexSDK 1.19.0

dotnet add package TeamVortexSoftware.VortexSDK --version 1.19.0
                    
NuGet\Install-Package TeamVortexSoftware.VortexSDK -Version 1.19.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="TeamVortexSoftware.VortexSDK" Version="1.19.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="TeamVortexSoftware.VortexSDK" Version="1.19.0" />
                    
Directory.Packages.props
<PackageReference Include="TeamVortexSoftware.VortexSDK" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add TeamVortexSoftware.VortexSDK --version 1.19.0
                    
#r "nuget: TeamVortexSoftware.VortexSDK, 1.19.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package TeamVortexSoftware.VortexSDK@1.19.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=TeamVortexSoftware.VortexSDK&version=1.19.0
                    
Install as a Cake Addin
#tool nuget:?package=TeamVortexSoftware.VortexSDK&version=1.19.0
                    
Install as a Cake Tool

vortex-csharp-sdk

Version Language

Invitation infrastructure for modern apps

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. Learn more about Vortex →

Why This SDK?

This backend SDK securely signs user data for Vortex components. Your API key stays on your server, while the signed token is passed to the frontend where Vortex components render the invitation UI.

  • Keep your API key secure — it never touches the browser
  • Sign user identity for attribution — know who sent each invitation
  • Control what data components can access via scoped tokens
  • Verify webhook signatures for secure event handling

How It Works

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.

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│   Your Server   │     │  User Browser   │     │  Vortex Cloud   │
│    (this SDK)   │     │   (component)   │     │                 │
└────────┬────────┘     └────────┬────────┘     └────────┬────────┘
         │                       │                       │
         │  1. GenerateToken()   │                       │
         │◄──────────────────────│                       │
         │                       │                       │
         │  2. Return token      │                       │
         │──────────────────────►│                       │
         │                       │                       │
         │                       │  3. Component calls   │
         │                       │     API with token    │
         │                       │──────────────────────►│
         │                       │                       │
         │                       │  4. Render UI,        │
         │                       │     send invitations  │
         │                       │◄──────────────────────│
         │                       │                       │

Integration Flow

1. Install the backend SDK [backend]

Add this SDK to your .NET project

dotnet add package TeamVortexSoftware.VortexSDK

2. Initialize the client [backend]

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

using TeamVortexSoftware.VortexSDK;

var client = new VortexClient(
    Environment.GetEnvironmentVariable("VORTEX_API_KEY")
);

3. Generate a token for the current user [backend]

When a user loads a page with a Vortex component, generate a signed token on your server

var token = client.GenerateToken(new GenerateTokenPayload
{
    User = new TokenUser { Id = currentUser.Id }
});

4. Pass the token to your frontend [backend]

Include the token in your page response or API response

return Ok(new { vortexToken = token });

5. Render a Vortex component with the token [frontend]

Use the React/Angular/Web Component with the token

import { VortexInvite } from "@teamvortexsoftware/vortex-react";

<VortexInvite token={vortexToken} />

6. Vortex handles the rest [vortex]

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

Security Model

⚠️ Important: Your Vortex API key is a secret that grants full access to your account. It must never be exposed to browsers or client-side code.

By signing tokens on your server, you:

  • Keep your API key secret (it never leaves your server)
  • Control exactly what user data is shared with components
  • Ensure invitations are attributed to real, authenticated users
  • Prevent abuse — users can only send invitations as themselves
When Signing is Optional

Token signing is controlled by your component configuration in the Vortex dashboard.


Quick Start

Generate a secure token for Vortex components

using TeamVortexSoftware.VortexSDK;

var client = new VortexClient(Environment.GetEnvironmentVariable("VORTEX_API_KEY"));

var payload = new GenerateTokenPayload
{
    User = new TokenUser { Id = "user-123", Email = "user@example.com" }
};

var token = client.GenerateToken(payload);

Installation

dotnet add package TeamVortexSoftware.VortexSDK

<details> <summary>Other package managers</summary>

PackageManager:

Install-Package TeamVortexSoftware.VortexSDK

</details>

Initialization

var client = new VortexClient(Environment.GetEnvironmentVariable("VORTEX_API_KEY"));

Environment Variables

Variable Required Description
VORTEX_API_KEY Your Vortex API key

Core Methods

These are the methods you'll use most often.

GenerateToken()

Generate a signed token for use with Vortex widgets

Signature:

GenerateToken(GenerateTokenPayload payload, GenerateTokenOptions? options): string

Parameters:

Name Type Required Description
payload GenerateTokenPayload Data to sign (user, component, scope, vars, etc.)
options GenerateTokenOptions? Optional configuration (ExpiresIn)

Returns: string — Signed JWT token string

Added in v0.8.0


GetInvitationAsync()

Get a specific invitation by ID

Signature:

GetInvitationAsync(string invitationId): Task<Invitation>

Parameters:

Name Type Required Description
invitationId string The invitation ID

Returns: Task<Invitation> — The invitation details

Added in v0.1.0


AcceptInvitationAsync()

Accept a single invitation (recommended method)

Signature:

AcceptInvitationAsync(string invitationId, AcceptUser user): Task<Invitation>

Parameters:

Name Type Required Description
invitationId string Single invitation ID to accept
user AcceptUser User with email or phone (and optional name)

Returns: Task<Invitation> — Invitation result

Added in v0.6.0


All Methods

<details> <summary>Click to expand full method reference</summary>

GetInvitationsByTargetAsync()

Get invitations by target (email or sms)

Signature:

GetInvitationsByTargetAsync(string targetType, string targetValue): Task<List<Invitation>>

Parameters:

Name Type Required Description
targetType string Type of target (email, phone)
targetValue string The target value

Returns: Task<List<Invitation>> — List of invitations

Added in v0.1.0


RevokeInvitationAsync()

Revoke (delete) an invitation

Signature:

RevokeInvitationAsync(string invitationId): Task

Parameters:

Name Type Required Description
invitationId string The invitation ID to revoke

Returns: Task

Added in v0.1.0


AcceptInvitationsAsync()

Accept multiple invitations using the new User format (preferred)

Signature:

AcceptInvitationsAsync(List<string> invitationIds, AcceptUser user): Task<Invitation>

Parameters:

Name Type Required Description
invitationIds List<string> List of invitation IDs to accept
user AcceptUser User with email or phone (and optional name)

Returns: Task<Invitation> — Invitation result

Added in v0.1.0


DeleteInvitationsByScopeAsync()

Delete all invitations for a specific scope

Signature:

DeleteInvitationsByScopeAsync(string groupType, string groupId): Task

Parameters:

Name Type Required Description
groupType string The scope type (organization, team, etc.)
groupId string The scope identifier

Returns: Task

Added in v0.4.0


GetInvitationsByScopeAsync()

Get all invitations for a specific scope

Signature:

GetInvitationsByScopeAsync(string groupType, string groupId): Task<List<Invitation>>

Parameters:

Name Type Required Description
groupType string The scope type (organization, team, etc.)
groupId string The scope identifier

Returns: Task<List<Invitation>> — List of invitations for the scope

Added in v0.4.0


ReinviteAsync()

Reinvite a user (send invitation again)

Signature:

ReinviteAsync(string invitationId): Task<Invitation>

Parameters:

Name Type Required Description
invitationId string The invitation ID to reinvite

Returns: Task<Invitation> — The reinvited invitation result

Added in v0.2.0


CreateInvitationAsync()

Create an invitation from your backend. This method allows you to create invitations programmatically using your API key, without requiring a user JWT token. Useful for server-side invitation creation, such as "People You May Know" flows or admin-initiated invitations.

Signature:

CreateInvitationAsync(CreateInvitationRequest request): Task<CreateInvitationResponse>

Parameters:

Name Type Required Description
request CreateInvitationRequest The create invitation request

Returns: Task<CreateInvitationResponse> — CreateInvitationResponse with id, shortLink, status, and createdAt

Example:

// Create an email invitation
var request = new CreateInvitationRequest(
    "widget-config-123",
    CreateInvitationTarget.Email("invitee@example.com"),
    new Inviter("user-456", "inviter@example.com", "John Doe")
);
request.Groups = new List&lt;CreateInvitationScope&gt;
{
    new("team", "team-789", "Engineering")
};
var response = await client.CreateInvitationAsync(request);
// Create an internal invitation (PYMK flow)
var pymkRequest = new CreateInvitationRequest(
    "widget-config-123",
    CreateInvitationTarget.Internal("internal-user-abc"),
    new Inviter("user-456")
);
pymkRequest.Source = "pymk";
var response = await client.CreateInvitationAsync(pymkRequest);

Added in v0.1.0


GetAutojoinDomainsAsync()

Get autojoin domains configured for a specific scope

Signature:

GetAutojoinDomainsAsync(string scopeType, string scope): Task<AutojoinDomainsResponse>

Parameters:

Name Type Required Description
scopeType string The type of scope (e.g., "organization", "team", "project")
scope string The scope identifier (customer's group ID)

Returns: Task<AutojoinDomainsResponse> — AutojoinDomainsResponse with autojoin domains and invitation

Added in v0.6.0


ConfigureAutojoinAsync()

Configure autojoin domains for a specific scope

Signature:

ConfigureAutojoinAsync(ConfigureAutojoinRequest request): Task<AutojoinDomainsResponse>

Parameters:

Name Type Required Description
request ConfigureAutojoinRequest The configure autojoin request

Returns: Task<AutojoinDomainsResponse> — AutojoinDomainsResponse with updated autojoin domains

Added in v0.6.0


SyncInternalInvitationAsync()

Sync an internal invitation action (accept or decline)

Signature:

SyncInternalInvitationAsync(SyncInternalInvitationRequest request): Task<SyncInternalInvitationResponse>

Parameters:

Name Type Required Description
request SyncInternalInvitationRequest The sync internal invitation request

Returns: Task<SyncInternalInvitationResponse> — SyncInternalInvitationResponse with processed count and invitationIds

Example:

var request = new SyncInternalInvitationRequest("user-123", "user-456", "accepted", "component-uuid");
var response = await client.SyncInternalInvitationAsync(request);
Console.WriteLine($"Processed: {response.Processed}");

Added in v0.1.0


</details>

Types

<details> <summary>Click to expand type definitions</summary>

GenerateTokenPayload

Payload for GenerateToken - used to generate secure tokens for Vortex components

Field Type Required Description
user TokenUser? The authenticated user who will be using the Vortex component
component string? Component ID to generate token for (from your Vortex dashboard)
scope string? Scope identifier to restrict invitations to a specific team/org (format: "scopeType:scopeId")
vars Dictionary<string, object>? Custom variables to pass to the component for template rendering

TokenUser

User data for GenerateToken - represents the authenticated user sending invitations

Field Type Required Description
id string? Unique identifier for the user in your system. Used to attribute invitations and track referral chains.
name string? Display name shown to invitation recipients (e.g., "John invited you")
email string? User's email address. Used for reply-to in invitation emails.
avatarUrl string? URL to user's avatar image. Displayed in invitation emails and widgets.
adminScopes List<string>? List of scope IDs where this user has admin privileges (e.g., ["team:team-123"])

AcceptUser

User data for accepting invitations - identifies who accepted the invitation

Field Type Required Description
email string? Email address of the user accepting. At least one of Email or Phone is required.
phone string? Phone number with country code (e.g., "+15551234567"). At least one of Email or Phone is required.
name string? Display name of the accepting user (shown in notifications to inviter)
isExisting bool? Whether user was already registered. true=existing, false=new signup, null=unknown. Used for conversion analytics.

Invitation

Complete invitation details as returned by the Vortex API

Field Type Required Description
id string Unique identifier for this invitation
accountId string Your Vortex account ID
clickThroughs int Number of times the invitation link was clicked
formSubmissionData Dictionary<string, object>? Invitation form data submitted by the user, including invitee identifiers (such as email addresses, phone numbers, or internal IDs) and the values of any custom fields.
configurationAttributes Dictionary<string, object>?
attributes Dictionary<string, object>? Custom attributes attached to this invitation
createdAt string ISO 8601 timestamp when the invitation was created
deactivated bool Whether this invitation has been revoked or expired
deliveryCount int Number of times the invitation was sent (including reminders)
deliveryTypes List<DeliveryType> Channels used to deliver this invitation (email, sms, share link)
foreignCreatorId string Your internal user ID for the person who created this invitation
invitationType InvitationType Type of invitation: single_use (1:1), multi_use (1:many), or autojoin
modifiedAt string? ISO 8601 timestamp of last modification
status InvitationStatus Current status: queued, sending, sent, delivered, accepted, shared, unfurled
target List<InvitationTarget> List of invitation recipients with their contact info and status
views int Number of times the invitation page was viewed
widgetConfigurationId string Widget configuration ID used for this invitation
deploymentId string Deployment ID this invitation belongs to
groups List<InvitationScope> Scopes (teams/orgs) this invitation grants access to
accepts List<InvitationAcceptance>? List of acceptance records if the invitation was accepted (optional)
scope string? Primary scope identifier (e.g., "team-123")
scopeType string? Type of the primary scope (e.g., "team", "organization")
expired bool Whether this invitation has passed its expiration date
expires string? ISO 8601 timestamp when this invitation expires
metadata Dictionary<string, object>? Custom metadata attached to this invitation
passThrough string? Pass-through data returned unchanged in webhooks and callbacks
source string? Source identifier for tracking (e.g., "ios-app", "web-dashboard")
subtype string? Subtype for analytics segmentation (e.g., "pymk", "find-friends")
creatorName string? Display name of the user who created this invitation
creatorAvatarUrl string? Avatar URL of the user who created this invitation

InvitationTarget

Represents the target recipient of an invitation

Field Type Required Description
type InvitationTargetType Delivery channel: email, phone, share (link), or internal (in-app)
value string Target address: email, phone number with country code, or share link ID
name string? Display name of the recipient (e.g., "John Doe")
avatarUrl string? Avatar URL for the recipient, shown in invitation lists and widgets

InvitationScope

Invitation group from API responses This matches the MemberGroups table structure from the API

Field Type Required Description
id string Vortex internal UUID
accountId string Vortex account ID
groupId string Customer's group ID (the ID they provided to Vortex)
type string Group type (e.g., "workspace", "team")
name string Group name
createdAt string ISO 8601 timestamp when the group was created

CreateInvitationTarget

Target recipient when creating an invitation

Field Type Required Description
type CreateInvitationTargetTypeEnum Delivery channel: email, phone, or internal (in-app)
value string Target address: email, phone number (with country code), or internal user ID
name string? Display name of the recipient (shown in invitation emails and UI)
avatarUrl string? Avatar URL for the recipient (displayed in invitation lists)

Inviter

Information about the user sending the invitation - used for attribution and display

Field Type Required Description
userId string Your internal user ID for the inviter (required for attribution)
userEmail string? Inviter's email address (used for reply-to and identification)
name string? Display name shown to recipients (e.g., "John invited you to...")
avatarUrl string? Avatar URL displayed in invitation emails and widgets

User

User data for JWT generation - represents the authenticated user sending invitations. Only Id is required. Email is optional but recommended for invitation attribution.

Field Type Required Description
id string Your internal user ID (required for invitation attribution)
email string? User's email address (optional, used for reply-to in invitation emails)
name string? Display name shown to recipients (e.g., "John invited you")
avatarUrl string? Avatar URL displayed in invitation emails and widgets (must be HTTPS)
adminScopes List<string>? List of scopes where user has admin privileges (e.g., ["autojoin"])
allowedEmailDomains List<string>? Restrict invitations to these email domains (e.g., ["acme.com"])

Identifier

Identifier for a user - used in JWT generation to link user across channels

Field Type Required Description
type string Identifier type: "email", "phone", "username", or custom type
value string The identifier value (email address, phone number, etc.)

Group

Scope/group for JWT generation - defines user's team/org membership in tokens

Field Type Required Description
type string Scope type (e.g., "team", "organization", "workspace")
id string? Legacy scope identifier. Use Scope/groupId instead.
groupId string? Your internal scope/group identifier (preferred)
name string Display name for the scope (e.g., "Engineering Team")

InvitationAcceptance

Record of an invitation being accepted

Field Type Required Description
id string Unique identifier for this acceptance record
accountId string Your Vortex account ID
acceptedAt string ISO 8601 timestamp when the invitation was accepted
target InvitationTarget? The target that accepted the invitation

CreateInvitationScope

Group information for creating invitations

Field Type Required Description
type string Group type (e.g., "team", "organization")
groupId string Your internal group ID
name string Display name of the group

UnfurlConfig

Configuration for link unfurl (Open Graph) metadata. Controls how the invitation link appears when shared on social platforms or messaging apps.

Field Type Required Description
title string? The title shown in link previews (og:title)
description string? The description shown in link previews (og:description)
image string? The image URL shown in link previews (og:image) - must be HTTPS
type string? The Open Graph type (og:type) - e.g., 'website', 'article', 'product'
siteName string? The site name shown in link previews (og:site_name)

AutojoinDomain

Autojoin domain - users with matching email domains automatically join the scope

Field Type Required Description
id string Unique identifier for this autojoin configuration
domain string Email domain that triggers autojoin (e.g., "acme.com")

</details>

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

Verifying Webhooks

Always verify webhook signatures using VortexWebhooks.VerifySignature() to ensure requests are from Vortex. The signature is sent in the X-Vortex-Signature header.

Example: ASP.NET Core webhook handler

using TeamVortexSoftware.VortexSDK;
using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("webhooks")]
public class WebhookController : ControllerBase
{
    private readonly VortexWebhooks _webhooks = new(
        Environment.GetEnvironmentVariable("VORTEX_WEBHOOK_SECRET")
    );

    [HttpPost("vortex")]
    public IActionResult HandleWebhook(
        [FromBody] string body,
        [FromHeader(Name = "X-Vortex-Signature")] string signature)
    {
        // Verify the signature
        if (!_webhooks.VerifySignature(body, signature))
            return BadRequest("Invalid signature");

        // Parse the event
        var webhookEvent = _webhooks.ParseEvent(body);

        switch (webhookEvent.Type)
        {
            case "invitation.accepted":
                // User accepted an invitation — activate their account
                Console.WriteLine($"Accepted: {webhookEvent.Data}");
                break;
            case "member.created":
                // New member joined via invitation
                Console.WriteLine($"New member: {webhookEvent.Data}");
                break;
        }

        return Ok(new { received = true });
    }
}

Common 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.

Supported Events

Event Description
invitation.created A new invitation was created
invitation.accepted An invitation was accepted by the recipient
invitation.deactivated An invitation was deactivated (revoked or expired)
invitation.email.delivered Invitation email was successfully delivered
invitation.email.bounced Invitation email bounced (invalid address)
invitation.email.opened Recipient opened the invitation email
invitation.link.clicked Recipient clicked the invitation link
invitation.reminder.sent A reminder email was sent for a pending invitation
member.created A new member was created from an accepted invitation
group.member.added A member was added to a scope/group
deployment.created A new deployment configuration was created
deployment.deactivated A deployment was deactivated
abtest.started An A/B test was started
abtest.winner_declared An A/B test winner was declared
email.complained Recipient marked the email as spam

Error Handling

All SDK errors extend VortexException.

Error Description
VortexException Thrown for validation errors (e.g., missing API key, invalid parameters) or API failures

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.19.0 98 4/21/2026
1.15.0 98 4/8/2026
1.13.0 96 4/6/2026
1.10.0 107 2/25/2026
1.9.4 108 2/25/2026
1.9.3 108 2/20/2026
1.9.2 110 2/20/2026
1.9.1 109 2/16/2026
1.9.0 118 2/12/2026
1.7.0 115 2/5/2026
1.6.0 110 2/4/2026
1.4.0 115 2/3/2026
1.3.0 114 1/28/2026
1.1.3 127 1/5/2026
1.1.1 306 12/17/2025
1.1.0 303 12/16/2025
1.0.1 172 10/31/2025
1.0.0 216 10/21/2025