Appearance
Getting Started with Engagifii Events API
Table of Contents
- Prerequisites
- Authentication Setup
- Environment Setup
- Your First API Call
- Common Integration Patterns
- Testing Your Integration
- Troubleshooting
- Next Steps
Prerequisites
Before you begin integrating with the Events API, ensure you have:
API Credentials
- Client ID
- Client Secret
- Tenant Code
- Identity Server URL
Development Tools
- HTTP client (Postman, curl, or programming language HTTP library)
- JSON parser/viewer
- Text editor or IDE
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 result3. 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 data3. 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:
Explore Advanced Features
Implement Best Practices
- Set up webhook listeners for real-time updates
- Implement caching strategies
- Add comprehensive error handling
- Set up monitoring and alerting
Review Additional Documentation
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
