Community Service
The Community Service manages cross-platform community registrations, configurations, and security key storage. It provides a unified way to connect Discord servers, Telegram groups, and other platform communities to Loyalteez brands.
Overview
The Community Service handles:
- Community Registration - Two-step secure registration flow
- Security Key Management - Encrypted storage (AES-256-GCM)
- Configuration Management - Event settings, metadata, options
- Default Event Creation - Platform-specific default monitoring rules
Base URL
https://services.loyalteez.app/community
Endpoints
Register Community
Start the registration process. This creates a pending community record and returns an activation token.
POST /community/register
Request Body
{
"platform": "telegram",
"brandId": "0x1234567890abcdef1234567890abcdef12345678",
"securityKey": "your-64-char-hex-security-key",
"adminId": "5150836861",
"metadata": {
"setupInitiatedBy": "5150836861"
}
}
| Field | Type | Required | Description |
|---|---|---|---|
platform | string | Yes | Platform identifier: discord, telegram, twitter, etc. |
brandId | string | Yes | Brand wallet address (42 chars, starts with 0x) |
securityKey | string | Yes | Brand security key (64 char hex string) |
adminId | string | Yes | Platform user ID of the registering admin |
metadata | object | No | Additional metadata to store |
Response
{
"success": true,
"activationToken": "abc123xyz",
"expiresAt": "2026-01-22T15:30:00.000Z",
"message": "Registration successful. Use this token to activate in your community."
}
Errors
| Status | Error | Description |
|---|---|---|
| 400 | Missing required fields | Platform, brandId, securityKey, or adminId not provided |
| 400 | Invalid Brand ID format | Brand ID must be 42 chars starting with 0x |
| 400 | Invalid security key | Security key validation failed against the brand |
Activate Community
Complete the registration by providing the activation token and community ID.
POST /community/activate
Request Body
{
"activationToken": "abc123xyz",
"communityId": "-5009994438",
"communityName": "My Awesome Community",
"metadata": {
"chatType": "supergroup"
}
}
| Field | Type | Required | Description |
|---|---|---|---|
activationToken | string | Yes | Token from registration step |
communityId | string | Yes | Platform-specific community identifier |
communityName | string | No | Human-readable community name |
metadata | object | No | Additional metadata to store |
Response
{
"success": true,
"communityId": "-5009994438",
"brandId": "0x1234567890abcdef1234567890abcdef12345678",
"message": "Community activated successfully!",
"eventsCreated": [
"telegram_daily_checkin",
"gm_checkin",
"gn_checkin",
"telegram_join",
"telegram_admin_reward"
]
}
Errors
| Status | Error | Description |
|---|---|---|
| 400 | Missing activation token or community ID | Required fields not provided |
| 400 | Invalid or expired activation token | Token not found or expired |
| 409 | Community already exists | A community with this ID already exists |
Get Community Configuration
Retrieve the full configuration for a community.
GET /community/:platform/:communityId
Parameters
| Parameter | Description |
|---|---|
platform | Platform identifier (e.g., telegram, discord) |
communityId | Platform-specific community identifier |
Response
{
"success": true,
"data": {
"communityId": "-5009994438",
"platform": "telegram",
"brandId": "0x1234567890abcdef1234567890abcdef12345678",
"communityName": "My Awesome Community",
"status": "active",
"config": {
"welcomeMessage": "Welcome to {community}!",
"dailyEvent": "telegram_daily_checkin"
},
"events": [
{
"eventName": "telegram_daily_checkin",
"eventType": "telegram_daily_checkin",
"ltzReward": 10,
"cooldownHours": 24,
"isActive": true
}
],
"createdAt": "2026-01-22T14:00:00.000Z",
"updatedAt": "2026-01-22T14:30:00.000Z"
}
}
Errors
| Status | Error | Description |
|---|---|---|
| 404 | Community not found | No community with this platform/ID combination |
Update Community Configuration
Update configuration, metadata, or settings for a community.
PATCH /community/:platform/:communityId
Request Body
{
"config": {
"welcomeMessage": "Welcome aboard!",
"dailyEvent": "custom_daily_event"
},
"communityName": "Updated Community Name"
}
| Field | Type | Required | Description |
|---|---|---|---|
config | object | No | Configuration object to merge |
communityName | string | No | Update community name |
status | string | No | Update status (active, inactive) |
Response
{
"success": true,
"message": "Configuration updated",
"data": {
"communityId": "-5009994438",
"config": {
"welcomeMessage": "Welcome aboard!",
"dailyEvent": "custom_daily_event"
}
}
}
Get Security Key
Retrieve the decrypted security key for a community. Used internally by platform integrations for HMAC signing.
GET /community/:platform/:communityId/security-key
Response
{
"success": true,
"securityKey": "your-64-char-hex-security-key"
}
Errors
| Status | Error | Description |
|---|---|---|
| 404 | Community not found | No community with this platform/ID combination |
| 500 | Decryption failed | Internal error decrypting security key |
This endpoint is intended for internal use by platform bot workers. Security keys should never be exposed to end users.
Disconnect Community
Deactivate a community. This doesn't delete the record but sets status to inactive.
DELETE /community/:platform/:communityId
Query Parameters
| Parameter | Required | Description |
|---|---|---|
confirm | Yes | Must be true to confirm deletion |
Response
{
"success": true,
"message": "Community disconnected successfully"
}
Database Schema
The Community Service uses the brand_communities table:
CREATE TABLE brand_communities (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
platform TEXT NOT NULL, -- 'discord', 'telegram', etc.
community_id TEXT, -- Platform-specific ID (null while pending)
brand_id TEXT NOT NULL, -- Brand wallet address
community_name TEXT, -- Human-readable name
encrypted_security_key TEXT, -- AES-256-GCM encrypted
security_key_iv TEXT, -- Encryption IV
config_metadata JSONB DEFAULT '{}', -- Configuration settings
status TEXT DEFAULT 'pending', -- pending, active, inactive
activation_token TEXT, -- For two-step activation
activation_expires_at TIMESTAMPTZ, -- Token expiration
admin_user_id TEXT, -- Who set up the community
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
CONSTRAINT unique_platform_community
UNIQUE (platform, community_id)
);
CREATE INDEX idx_brand_communities_brand
ON brand_communities(brand_id);
CREATE INDEX idx_brand_communities_status
ON brand_communities(status);
CREATE INDEX idx_brand_communities_token
ON brand_communities(activation_token);
Default Events by Platform
When a community is activated, platform-specific default events are created:
Telegram
| Event | Type | LTZ | Cooldown | Description |
|---|---|---|---|---|
telegram_daily_checkin | daily | 10 | 24h | Daily check-in reward |
gm_checkin | natural | 25 | 24h | "Good morning" detection |
gn_checkin | natural | 15 | 24h | "Good night" detection |
telegram_join | welcome | 50 | One-time | New member bonus |
message_quality | quality | 10 | 1h | Quality message (disabled by default) |
telegram_admin_reward | manual | Variable | None | Admin-granted rewards |
Discord
| Event | Type | LTZ | Cooldown | Description |
|---|---|---|---|---|
discord_daily_checkin | daily | 10 | 24h | Daily check-in reward |
gm_checkin | natural | 25 | 24h | "Good morning" detection |
gn_checkin | natural | 15 | 24h | "Good night" detection |
discord_join | welcome | 50 | One-time | New member bonus |
message_quality | quality | 10 | 1h | Quality message |
discord_admin_reward | manual | Variable | None | Admin-granted rewards |
Security
Security Key Encryption
Security keys are encrypted at rest using AES-256-GCM:
- A random 12-byte IV is generated for each key
- The key is encrypted using the service's
ENCRYPTION_KEY - Both the encrypted key and IV are stored in the database
- Decryption happens in-memory only when needed
Two-Step Activation
The two-step activation flow protects against:
- Key Exposure: Security keys are never sent in public channels
- Unauthorized Setup: Only users who complete the DM flow can activate
- Token Expiration: Activation tokens expire after 1 hour
Integration Example
Telegram Bot Setup Flow
// Step 1: User DMs bot with /setup
// Bot collects brandId and securityKey through conversation
// Step 2: Register community
const response = await fetch('https://services.loyalteez.app/community/register', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
platform: 'telegram',
brandId: '0x...',
securityKey: 'abc123...',
adminId: userId
})
});
const { activationToken } = await response.json();
// Send token to user in DM
// Step 3: User uses /activate <token> in group
const activateResponse = await fetch('https://services.loyalteez.app/community/activate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
activationToken,
communityId: chatId,
communityName: chatTitle
})
});
// Community is now active!
Next Steps
- Streak Service - Track daily activity streaks
- Leaderboard Service - Generate community rankings
- Achievement Service - Manage achievements
- Perks Service - Handle perk redemption