Skip to content

Getting Started with Engagifii Events API

Table of Contents

Prerequisites

Before you begin integrating with the Events API, ensure you have:

  1. API Credentials

    • Client ID
    • Client Secret
    • Tenant Code
    • Identity Server URL
  2. Development Tools

    • HTTP client (Postman, curl, or programming language HTTP library)
    • JSON parser/viewer
    • Text editor or IDE
  3. Network Requirements

    • HTTPS support (TLS 1.2 or higher)
    • Ability to make outbound HTTPS requests
    • No IP whitelisting required (API is publicly accessible)

Authentication Setup

Step 1: Obtain Access Token

The Events API uses OAuth 2.0 client credentials flow. First, get an access token from the Identity Server:

bash
# Request access token
curl -X POST "{IDENTITY_SERVER_URL}/connect/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "client_id={YOUR_CLIENT_ID}" \
  -d "client_secret={YOUR_CLIENT_SECRET}" \
  -d "grant_type=client_credentials" \
  -d "scope=EventsApi"

Response:

json
{
  "access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjE1Njk...",
  "expires_in": 3600,
  "token_type": "Bearer",
  "scope": "EventsApi"
}

Step 2: Store and Refresh Token

  • Tokens expire after 1 hour (3600 seconds)
  • Implement automatic token refresh before expiration
  • Store tokens securely (never in client-side code)

Environment Setup

Development Environment

javascript
// Node.js example configuration
const config = {
  apiBaseUrl: 'https://engagifii-prod-event.azurewebsites.net',
  identityServerUrl: '{YOUR_IDENTITY_SERVER_URL}',
  clientId: process.env.ENGAGIFII_CLIENT_ID,
  clientSecret: process.env.ENGAGIFII_CLIENT_SECRET,
  tenantCode: process.env.ENGAGIFII_TENANT_CODE,
  apiVersion: '1.0'
};

Python Configuration

python
# Python example configuration
import os
from datetime import datetime, timedelta

class EngagifiiConfig:
    API_BASE_URL = 'https://engagifii-prod-event.azurewebsites.net'
    IDENTITY_SERVER_URL = os.environ.get('IDENTITY_SERVER_URL')
    CLIENT_ID = os.environ.get('ENGAGIFII_CLIENT_ID')
    CLIENT_SECRET = os.environ.get('ENGAGIFII_CLIENT_SECRET')
    TENANT_CODE = os.environ.get('ENGAGIFII_TENANT_CODE')
    API_VERSION = '1.0'

C# Configuration

csharp
// C# example configuration
public class EngagifiiConfig
{
    public string ApiBaseUrl { get; set; } = "https://engagifii-prod-event.azurewebsites.net";
    public string IdentityServerUrl { get; set; }
    public string ClientId { get; set; }
    public string ClientSecret { get; set; }
    public string TenantCode { get; set; }
    public string ApiVersion { get; set; } = "1.0";
}

Your First API Call

Complete Working Example - List Events

JavaScript/Node.js

javascript
const axios = require('axios');

class EngagifiiClient {
  constructor(config) {
    this.config = config;
    this.accessToken = null;
    this.tokenExpiry = null;
  }

  async getAccessToken() {
    if (this.accessToken && this.tokenExpiry > Date.now()) {
      return this.accessToken;
    }

    const tokenResponse = await axios.post(
      `${this.config.identityServerUrl}/connect/token`,
      new URLSearchParams({
        client_id: this.config.clientId,
        client_secret: this.config.clientSecret,
        grant_type: 'client_credentials',
        scope: 'EventsApi'
      }),
      {
        headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
      }
    );

    this.accessToken = tokenResponse.data.access_token;
    this.tokenExpiry = Date.now() + (tokenResponse.data.expires_in * 1000);
    
    return this.accessToken;
  }

  async listEvents(pageNumber = 1, pageSize = 10) {
    const token = await this.getAccessToken();
    
    const response = await axios.post(
      `${this.config.apiBaseUrl}/api/${this.config.apiVersion}/event/list`,
      {
        PageNumber: pageNumber,
        PageSize: pageSize,
        OnlyUpcoming: true
      },
      {
        headers: {
          'Authorization': `Bearer ${token}`,
          'api-version': this.config.apiVersion,
          'tenant-code': this.config.tenantCode,
          'Content-Type': 'application/json'
        }
      }
    );

    return response.data;
  }
}

// Usage
(async () => {
  const client = new EngagifiiClient(config);
  try {
    const events = await client.listEvents(1, 10);
    console.log(`Found ${events.totalCount} events`);
    console.log('Events:', events.data);
  } catch (error) {
    console.error('Error:', error.response?.data || error.message);
  }
})();

Python

python
import requests
from datetime import datetime, timedelta

class EngagifiiClient:
    def __init__(self, config):
        self.config = config
        self.access_token = None
        self.token_expiry = None
    
    def get_access_token(self):
        if self.access_token and self.token_expiry > datetime.now():
            return self.access_token
        
        token_response = requests.post(
            f"{self.config.IDENTITY_SERVER_URL}/connect/token",
            data={
                'client_id': self.config.CLIENT_ID,
                'client_secret': self.config.CLIENT_SECRET,
                'grant_type': 'client_credentials',
                'scope': 'EventsApi'
            },
            headers={'Content-Type': 'application/x-www-form-urlencoded'}
        )
        
        token_data = token_response.json()
        self.access_token = token_data['access_token']
        self.token_expiry = datetime.now() + timedelta(seconds=token_data['expires_in'])
        
        return self.access_token
    
    def list_events(self, page_number=1, page_size=10):
        token = self.get_access_token()
        
        response = requests.post(
            f"{self.config.API_BASE_URL}/api/{self.config.API_VERSION}/event/list",
            json={
                'PageNumber': page_number,
                'PageSize': page_size,
                'OnlyUpcoming': True
            },
            headers={
                'Authorization': f'Bearer {token}',
                'api-version': self.config.API_VERSION,
                'tenant-code': self.config.TENANT_CODE,
                'Content-Type': 'application/json'
            }
        )
        
        return response.json()

# Usage
client = EngagifiiClient(EngagifiiConfig())
events = client.list_events(1, 10)
print(f"Found {events['totalCount']} events")
for event in events['data']:
    print(f"- {event['name']} ({event['startDateTime']})")

C#/.NET

csharp
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json;
using System.Collections.Generic;

public class EngagifiiClient
{
    private readonly HttpClient _httpClient;
    private readonly EngagifiiConfig _config;
    private string _accessToken;
    private DateTime _tokenExpiry;

    public EngagifiiClient(EngagifiiConfig config)
    {
        _config = config;
        _httpClient = new HttpClient();
    }

    private async Task<string> GetAccessTokenAsync()
    {
        if (!string.IsNullOrEmpty(_accessToken) && _tokenExpiry > DateTime.UtcNow)
        {
            return _accessToken;
        }

        var tokenRequest = new FormUrlEncodedContent(new[]
        {
            new KeyValuePair<string, string>("client_id", _config.ClientId),
            new KeyValuePair<string, string>("client_secret", _config.ClientSecret),
            new KeyValuePair<string, string>("grant_type", "client_credentials"),
            new KeyValuePair<string, string>("scope", "EventsApi")
        });

        var tokenResponse = await _httpClient.PostAsync(
            $"{_config.IdentityServerUrl}/connect/token", 
            tokenRequest
        );

        var tokenJson = await tokenResponse.Content.ReadAsStringAsync();
        dynamic tokenData = JsonConvert.DeserializeObject(tokenJson);
        
        _accessToken = tokenData.access_token;
        _tokenExpiry = DateTime.UtcNow.AddSeconds((int)tokenData.expires_in);
        
        return _accessToken;
    }

    public async Task<EventListResponse> ListEventsAsync(int pageNumber = 1, int pageSize = 10)
    {
        var token = await GetAccessTokenAsync();
        
        var request = new HttpRequestMessage(HttpMethod.Post, 
            $"{_config.ApiBaseUrl}/api/{_config.ApiVersion}/event/list");
        
        request.Headers.Add("Authorization", $"Bearer {token}");
        request.Headers.Add("api-version", _config.ApiVersion);
        request.Headers.Add("tenant-code", _config.TenantCode);
        
        request.Content = new StringContent(
            JsonConvert.SerializeObject(new 
            {
                PageNumber = pageNumber,
                PageSize = pageSize,
                OnlyUpcoming = true
            }),
            System.Text.Encoding.UTF8, 
            "application/json"
        );

        var response = await _httpClient.SendAsync(request);
        var json = await response.Content.ReadAsStringAsync();
        
        return JsonConvert.DeserializeObject<EventListResponse>(json);
    }
}

// Usage
var config = new EngagifiiConfig
{
    ClientId = Environment.GetEnvironmentVariable("ENGAGIFII_CLIENT_ID"),
    ClientSecret = Environment.GetEnvironmentVariable("ENGAGIFII_CLIENT_SECRET"),
    TenantCode = Environment.GetEnvironmentVariable("ENGAGIFII_TENANT_CODE"),
    IdentityServerUrl = Environment.GetEnvironmentVariable("IDENTITY_SERVER_URL")
};

var client = new EngagifiiClient(config);
var events = await client.ListEventsAsync(1, 10);

Console.WriteLine($"Found {events.TotalCount} events");
foreach (var evt in events.Data)
{
    Console.WriteLine($"- {evt.Name} ({evt.StartDateTime})");
}

Common Integration Patterns

1. Event Registration Flow

javascript
// Complete registration flow
async function registerForEvent(eventId, memberId, bundleIds) {
  // Step 1: Check event availability
  const event = await client.getEvent(eventId);
  if (event.availableRegistrantsCapacity <= 0) {
    throw new Error('Event is full');
  }

  // Step 2: Check member eligibility
  const eligibility = await client.checkEligibility(eventId, memberId);
  if (!eligibility.isEligible) {
    throw new Error(`Not eligible: ${eligibility.reason}`);
  }

  // Step 3: Create registration
  const registration = await client.createRegistration({
    eventId: eventId,
    memberId: memberId,
    bundleIds: bundleIds,
    registrationType: 'Member'
  });

  // Step 4: Handle approval if needed
  if (registration.requiresApproval) {
    await client.submitForApproval(registration.id);
  }

  return registration;
}

2. Exhibitor Booth Management

python
def manage_exhibitor_booth(event_id, exhibitor_id):
    # Get available booths
    booths = client.get_available_booths(event_id)
    
    # Select preferred booths
    preferences = [booth['id'] for booth in booths[:3]]
    
    # Submit booth preferences
    result = client.submit_booth_preferences({
        'eventId': event_id,
        'exhibitorId': exhibitor_id,
        'preferredBoothIds': preferences,
        'alternativeBoothIds': []
    })
    
    # Check assignment status
    if result['assignmentType'] == 'Direct':
        print(f"Booth assigned: {result['assignedBoothId']}")
    else:
        print("Booth preferences recorded, awaiting assignment")
    
    return result

3. Bulk Operations with Pagination

csharp
public async Task<List<Registration>> GetAllRegistrationsAsync(Guid eventId)
{
    var allRegistrations = new List<Registration>();
    var pageNumber = 1;
    var pageSize = 100;
    var hasMoreData = true;

    while (hasMoreData)
    {
        var response = await client.GetRegistrationsAsync(eventId, pageNumber, pageSize);
        allRegistrations.AddRange(response.Data);
        
        hasMoreData = response.TotalCount > (pageNumber * pageSize);
        pageNumber++;
        
        // Add delay to respect rate limits
        await Task.Delay(100);
    }

    return allRegistrations;
}

Testing Your Integration

1. Use Test Data

Create test events and registrations in a sandbox environment:

javascript
// Test data creation
const testEvent = {
  name: `Test Event ${Date.now()}`,
  startDateTime: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // 7 days from now
  endDateTime: new Date(Date.now() + 8 * 24 * 60 * 60 * 1000),
  isFreeEvent: true,
  registrantsCapacity: 100,
  isRegistrationOn: true
};

const createdEvent = await client.createEvent(testEvent);
console.log('Test event created:', createdEvent.id);

2. Validate Responses

python
def validate_api_response(response):
    # Check status code
    assert response.status_code in [200, 201], f"Unexpected status: {response.status_code}"
    
    # Validate response structure
    data = response.json()
    assert 'data' in data or 'error' in data, "Invalid response structure"
    
    # Check for errors
    if 'error' in data:
        raise Exception(f"API Error: {data['error']['message']}")
    
    return data

3. Error Handling Tests

csharp
[Test]
public async Task TestInvalidAuthentication()
{
    var client = new EngagifiiClient(new EngagifiiConfig { 
        ClientId = "invalid",
        ClientSecret = "invalid" 
    });
    
    try
    {
        await client.ListEventsAsync();
        Assert.Fail("Should have thrown authentication exception");
    }
    catch (AuthenticationException ex)
    {
        Assert.IsTrue(ex.Message.Contains("invalid_client"));
    }
}

Troubleshooting

Common Issues and Solutions

1. Authentication Errors

Error: 401 Unauthorized

json
{
  "error": "invalid_token",
  "error_description": "The access token is invalid or has expired"
}

Solution:

  • Verify client credentials are correct
  • Ensure token hasn't expired
  • Check scope includes "EventsApi"

2. Tenant Code Issues

Error: 400 Bad Request

json
{
  "error": {
    "code": "INVALID_TENANT",
    "message": "Tenant code is missing or invalid"
  }
}

Solution:

  • Ensure tenant-code header is included
  • Verify tenant code is correct and active

3. Rate Limiting

Error: 429 Too Many Requests

json
{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded. Try again in 60 seconds"
  }
}

Solution:

  • Implement exponential backoff
  • Cache responses when possible
  • Use bulk endpoints instead of individual calls

4. Validation Errors

Error: 400 Bad Request

json
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Validation failed",
    "details": {
      "EventId": ["Event ID is required"],
      "MemberId": ["Member ID must be a valid GUID"]
    }
  }
}

Solution:

  • Check required fields are provided
  • Ensure data types match API specification
  • Validate GUIDs are properly formatted

Debug Mode

Enable detailed logging for troubleshooting:

javascript
// Enable debug logging
if (process.env.DEBUG) {
  axios.interceptors.request.use(request => {
    console.log('Starting Request:', request);
    return request;
  });

  axios.interceptors.response.use(response => {
    console.log('Response:', response);
    return response;
  });
}

Next Steps

Now that you have successfully integrated with the Events API:

  1. Explore Advanced Features

  2. Implement Best Practices

    • Set up webhook listeners for real-time updates
    • Implement caching strategies
    • Add comprehensive error handling
    • Set up monitoring and alerting
  3. Review Additional Documentation

  4. Get Support

    • Join our developer community
    • Contact technical support
    • Review FAQs and known issues

Sample Applications

Complete working sample applications with code examples:

  • Node.js Event Dashboard: Full-featured event management dashboard
  • Python Registration Bot: Automated registration system
  • C# Reporting Tool: Event analytics and reporting application

Each sample includes:

  • Complete source code
  • Setup instructions
  • Configuration examples
  • Unit tests
  • Docker deployment files